简介PDF文档《Robot Framework调用Python类方法-五RobotFramework基础》是系列第五讲面向自动化测试初学者、测试开发工程师及希望增强Robot Framework脚本能力的读者重点讲解RF基础语法与Python方法的结合方式。文档用完整Test Case示例贯穿核心语法先以Set Variable与Run Keyword If演示多分支判断根据变量值输出优秀、良好、及格、不及格再用:FOR配合IN RANGE和列表实现循环遍历随后通过Evaluate调用Python内置random模块生成随机数并导入自建的count.py文件调用add函数完成两数相加最后介绍Comment关键字与#注释写法。压缩包内共1个PDF文件大小83KB便于下载后随时查阅。目前已有853人学习下载内容案例集中、说明细致适合边读边练可帮助读者理解Robot Framework调用Python类与模块的完整思路快速上手编写可复用的自动化测试用例。1. 把 Robot Framework 和 Python 焊在一起这份基础讲义为什么值得照着敲一遍Robot Framework 的语法看起来简单但真到了要写分支、循环、调第三方 Python 库的场景很多人会卡在「关键字怎么组合」「变量类型怎么转」上。这份 PDF 是《RobotFramework 基础》系列第五讲前半节讲 if 分支后半节是重头戏——通过Evaluate调用 Python 方法和导入自定义.py文件等于把 RF 从关键字脚本工具升级成能和 Python 生态无缝对接的自动化框架。适合已经跑通 RF 安装、能写简单 test case 的测试开发也适合想把手头 Python 工具函数直接复用到 RF 用例里的团队。照着文档敲一遍你基本就摸清「RF 里哪些活该交给 Python、哪些活该留在关键字层」这条边界了。2. 分支逻辑不靠原生 ifRun Keyword If 的写法与排序陷阱2.1 为什么 RF 的 if 长得和 Python 不一样Robot Framework 本身是关键字驱动keyword-driven框架不提供 Python 里那种if condition: ...的结构化语法。官方给出的分支方案是Run Keyword If它本质上是一个「按条件决定要不要执行下一个关键字」的调度器。理解这一点很重要RF 里不存在代码块缩进只有「条件表达式 要调用的关键字 传给关键字的参数」想清楚这个模型后面写多层条件就不会晕。Run Keyword If的完整形式是Run Keyword If 条件表达式 关键字 关键字参数条件表达式里的比较运算符、、等会被 RF 解析成对应的 Python 比较。你不需要写return True之类的逻辑表达式结果本身直接决定「执行还是跳过」后面那个关键字。这里最容易踩的坑是条件表达式与后面的关键字之间至少要留两个空格RF 用它区分「条件」和「要执行的动作」少了空格它会把整行当成表达式的一部分直接报语法错误。2.2 一个完整的多层分支用例PDF 里的 test case 8 是个很好的起点我把它整理成可以直接跑的样子*** Test Cases *** test case8 ${a} Set Variable 59 Run Keyword If ${a} 90 Log 优秀 ... ELSE IF ${a} 70 Log 良好 ... ELSE IF ${a} 60 Log 及格 ... ELSE Log 不及格逻辑分成四段先定义变量${a}为 59第一个Run Keyword If判断${a} 90不满足就跳到ELSE IF继续判断${a} 70、${a} 60全不满足就落到ELSE输出「不及格」。这里有一个 PDF 里没细说的细节...是行连接符表示「这一行是上一行的延续」所以在Run Keyword If里条件、Log、输出值之间都用它衔接直到遇到下一个独立行。参数上需要注意Run Keyword If后面跟的「关键字」可以带参数比如Log 优秀里的「优秀」就是传给Log的参数。条件表达式里变量要写成${a}不能写裸的aRF 不会自动把它当变量处理。另外表达式和关键字之间我习惯统一用 2 个以上空格分隔不同版本对 4 个空格的标准对齐也认但 2 个是最低要求。2.3 多层条件别堆成山把分支里的动作拆成关键字真实项目里分支后面的动作往往不止Log一行而是「登录」「查询订单」「校验返回码」这种复合操作。如果全堆在Run Keyword If后面的同一行里可读性会迅速崩掉。这个 PDF 虽然没有展开讲但你能从它只给Log当动作的写法里看出来——动作越短越适合直接写在分支行里。常见做法是这样拆*** Keywords *** handle_score [Arguments] ${score} Run Keyword If ${score} 90 Log 优秀 ... ELSE IF ${score} 70 Log 良好 ... ELSE Log 继续加油 *** Test Cases *** test case8-refactor ${a} Set Variable 59 handle_score ${a}把整段分支封装成用户关键字handle_scoretest case 里只留一行调用。这样分支逻辑可以被多个用例复用test case 本身也更接近「业务描述」。如果你只照着 PDF 里第一版写用例一多就会发现每个用例都在重复同样的Run Keyword If链条维护起来全是复制粘贴。我的习惯是分支里的动作超过一个关键字就把整个分支块封装进*** Keywords ***段test case 只负责传参数。3. 循环的两副面孔IN RANGE 数值循环与遍历列表的展开细节3.1 老式 :FOR 语法的写法与 range 范围语义PDF 里给的是老式:FOR语法RF 4.0 之后推荐新式FOR ... END但理解老式写法对读旧项目仍有实际价值。先看数值循环*** Test Cases *** test case9 :FOR ${i} IN RANGE 10 \ Log ${i}:FOR定义循环变量${i}IN RANGE 10表示从 0 到 9 一共 10 次区间左闭右开这一点和 Python 的range(10)完全一致。循环体每一行必须以\开头这个反斜杠是老式语法的核心辨识点——它告诉 RF「下面这行属于循环体内部」。如果你漏写了\RF 会把Log ${i}当成孤立行在用例外面执行循环体实际是空的。IN RANGE还支持起点和步长IN RANGE 1 10 2表示 1、3、5、7、9。跑测试时我一般会先在 Log 里把循环变量打出来确认区间端点尤其是IN RANGE 10这种只写一个参数的写法新手容易当成「1 到 10」实际是「0 到 9」。没有比「数组越界或循环次数多一次」更典型的翻车现场了。3.2 遍历列表{list} 的标量展开列表遍历的写法是*** Test Cases *** test case10 {abc} Create List a b c :FOR ${i} IN {abc} \ Log ${i}Create List把a b c三个字符串放进列表变量{abc}。循环用IN {abc}不是IN ${abc}。这里有个非常容易踩的差异{abc}用在循环里表示「把列表元素逐个取出来」而${abc}则代表「整个列表作为一个字符串对象」。你如果写成:FOR ${i} IN ${abc}${i}拿到的会是[a, b, c]这个字符串的字面量而不是三个元素。这也是 PDF 里「通过 {} 存放列表」这句话背后的真正含义——符号的作用是「展开」在 RF 里展开为多个值在循环里就表现为逐个元素。顺着这个思路你还能用{abc}直接给关键字传多个参数比如My Keyword {abc}等价于My Keyword a b c这是 RF 里「列表拆包」的标准姿势。3.3 新式 FOR 语法与老式语法的共存注意RF 4.0 推荐的新式写法是这样*** Test Cases *** test case9-new FOR ${i} IN RANGE 10 Log ${i} END test case10-new {abc} Create List a b c FOR ${i} IN {abc} Log ${i} END新式语法去掉了:FOR的反斜杠\循环体靠缩进识别末尾必须写END。如果你在 RF 5.x 环境里跑老式:FOR通常还能运行但控制台会给出弃用警告DeprecationWarning。我在维护旧项目时碰到过两种混用的情况——同一个 suite 里既有:FOR又有FOR...ENDRF 运行并不会报错但代码风格割裂后来我统一用新式改写。对新项目直接用新式FOR...END就好PDF 里的老式语法只需要能读懂、能迁移。4. Evaluate 才是真正的「调用 Python 类方法」入口随机数、自定义函数与类型转换4.1 Evaluate 的基本模型一段可以被 RF 求值的 Python 表达式Evaluate是 PDF 里「强大」二字的落点。它的机制可以概括成RF 把你的参数字符串当作 Python 表达式去执行然后把表达式的结果返回给左边的变量。要注意的是Evaluate求值的是一段表达式不是多行代码所以你可以random.randint(1000, 9999)但不能再里面写import random。照 PDF 的随机数例子走一遍*** Test Cases *** test case11 ${d} Evaluate random.randint(1000, 9999) random Log ${d}Evaluate第一个参数是表达式第二个参数random是「模块引用」——它把 Python 的random模块注入到表达式的求值命名空间里。没有这个第二个参数表达式random.randint(...)会直接报NameError: name random is not defined。这是新手最容易忽略的点Evaluate不会自动 import 你需要的模块你得把模块对象作为额外参数传进去。如果你不想传第二个参数可以用__import__写进表达式Evaluate __import__(random).randint(1000, 9999)但可读性差一般我只在调试时临时用正式用例里还是老老实实把random挂到参数位。4.2 导入自定义 Python 模块从 D:/rf_test/count.py 说起PDF 里第 12 个用例是整份资料最有价值的部分——RF 调用自写 Python 函数。先按它的方式建文件# D:/rf_test/count.py def add(a, b): return a b if __name__ __main__: a add(4, 5) print(a)然后在 RF 里导入并调用*** Test Cases *** test case12 Import Library D:/rf_test/count.py ${a} Evaluate int(4) ${b} Evaluate int(5) ${add} add ${a} ${b} Log ${add}这里Import Library后面直接跟.py文件路径RF 会把该文件当作一个 Python 库加载文件里定义的add函数自动变成 RF 的关键字。调用add ${a} ${b}时RF 把${a}和${b}作为两个位置参数传给 Python 函数。核心在于类型RF 里所有变量都是字符串而 Python 的对字符串做拼接对整数才做加法。所以int(4)、int(5)先把字符串转成整数再交给add拿到结果才是数字9而不是字符串45。这是 RF 混编 Python 时最绕不过去的一道坎——任何想让 Python 函数按数值语义处理的参数都必须先用Evaluate int(...)或类似方式显式转类型。4.3 从函数到类方法真正把 Python 类加载进 RFPDF 标题写的是「调用 Python 类方法」正文示例用的却是函数。实际项目里更常见的是把一组方法放进类里RF 也支持这种用法不过Import Library的写法会稍有不同。假设count.py改成类结构# D:/rf_test/calculator.py class Calculator: def __init__(self): pass def add(self, a, b): return int(a) int(b) def multiply(self, a, b): return int(a) * int(b)RF 端导入时要注意类名必须和文件名一致大小写也建议一致否则 RF 识别不到*** Test Cases *** test case-calculator Import Library D:/rf_test/calculator.py ${calc} Calculator ${result} add ${calc} 3 6 Log ${result}Import Library加载的是Calculator类本身RF 会实例化它并把类里的方法注册成关键字。调用add时第一个参数是实例对象${calc}——RF 会自动把「当前导入的库实例」作为 self 隐式传进去你不用显式传 self但要把实例对象放在参数首位。上面例子里${calc}就是Calculator的实例后续3和6才是真正的业务参数。如果你不想在用例里手动创建实例可以在类里加一个类方法或直接用构造函数参数# D:/rf_test/calculator.py class Calculator: def add(self, a, b): return int(a) int(b)然后Import Library D:/rf_test/calculator.py之后直接add 3 6也行——RF 对有__init__无参的类导入时会自动实例化并把实例绑定为默认的库实例。两种方式在功能上几乎等价区别在于用例里要不要显式拿到实例句柄。我的建议是如果类里只有无状态方法让 RF 自动实例化最省事如果方法之间依赖实例属性比如先 set 后 get就显式创建实例传参避免共享状态在用例之间串味。再补一个 Evaluate 直接调类方法的姿势*** Test Cases *** test case-eval-class Import Library D:/rf_test/calculator.py ${result} Evaluate Calculator().add(6, 7) Calculator Log ${result}第二个参数Calculator把类对象注入表达式命名空间Calculator().add(...)完全按 Python 语法执行。这个写法的好处是不用区分「实例参数」和「业务参数」坏处是表达式里写复杂逻辑会很难看。我一般只在「一句 Python 能搞定、不值得为它建关键字」的临时计算里用它比如时间戳、哈希值、随机串。5. 避坑RF 调 Python 时最容易翻车的 5 个场景5.1...行连接符位置不对分支直接断掉现象Run Keyword If后面跟ELSE IF时用例报「No keyword with name ELSE found」或直接把ELSE IF当成关键字去解析。原因...必须放在行首且后面至少留一个空格再接ELSE IF。写成...ELSE IF或把...放在上一行末尾RF 都会认为ELSE IF是一个独立命令当然找不到同名关键字。解决检查每个...是否自成一行、前面没有多余字符、后面有空格。我建议在编辑器里把所有...行尾对齐肉眼扫一遍比让 RF 报错再猜快得多。5.2 条件表达式没有空格判断直接失效现象Run Keyword If ${a}90报错「Condition $ {a}90 is not a valid expression」。原因RF 的条件表达式里变量名、比较运算符之间需要空格分隔写成${a}90会被整体识别成一个无法求值的字符串。解决统一写成Run Keyword If ${a} 90运算符两侧各留一个空格。另外注意不要用单RF 条件里才是等值比较是赋值关键字。5.3 Import Library 用绝对路径时模块内部的 import 会跟着失效现象Import Library D:/rf_test/count.py成功后调用add总报找不到某个 Python 包。原因直接导入.py文件时RF 把文件路径加入sys.path但文件里import re、import requests这类语句依赖的是 Python 环境的全局sys.path。如果 Python 环境变量配置不全或你的自定义模块所在目录和 RF 工作目录不一致内部 import 会先挂掉。解决正式项目里推荐把自定义库放进 RF 的PYTHONPATH能扫到的目录然后Import Library count不带.py和路径。或者起用例前先设置环境变量PYTHONPATHD:/rf_test再Import Library count.py。个人经验是「用模块名、不要用路径」能少踩一半环境类的坑。5.4 字符串和整数比较${a} 是字符串拿它做数值判断要当心现象Run Keyword If ${a} 90在某些情况下输出结果和预期相反或者直接报比较错误。原因如果${a}是从接口返回或从文本里提取的它本质是字符串。Python 3 里字符串和整数用比较会抛TypeErrorRF 在解析条件时会尝试自动转换但碰上「非纯数字字符串」就无能为力。解决比较前先用Evaluate int(${a})显式转成整数或者用Convert To Integer关键字${a} Convert To Integer 59之后再进Run Keyword If就不会有类型层面的幺蛾子。RF 的自动类型转换只在「一眼能看出来是数字」时可靠别把命运交给它。5.5 老式 :FOR 的循环变量污染现象循环结束后${i}还保留着最后一个值下一个测试用例里没重新赋值就直接用它结果拿到的是旧数据。原因老式:FOR不会清理循环变量RF 的变量作用域是「suite 内全局」——循环创建或修改过的变量在整个用例文件里持续有效。解决循环结束后如需保持环境干净显式执行${i} Set Variable ${EMPTY}或者把循环放进专门的关键字里让变量作用域局限在关键字内部。RF 4.0 的新式FOR...END同样存在这个问题不要指望框架帮你回收。6. 回到第一现场亲手把 RF、Python 类方法和随机数串成一条用例前面五章把 if、循环、Evaluate、自定义模块拆开讲了最后把它们拼成一段能直接跑通的完整用例你就能在本地环境验证所有知识点。先确认 Python 环境正常——在终端执行python --version能输出版本号即可RF 对 Python 3.6 都兼容。然后建一个项目目录D:/rf_demo里面放两个文件。第一个是自定义 Python 类把它命名为math_util.pyimport random class MathUtil: def __init__(self): pass def add(self, a, b): return int(a) int(b) def random_score(self): return random.randint(60, 99)第二个是同目录下的 RF 用例文件demo.robot*** Settings *** Library math_util.py *** Test Cases *** demo score branch ${score} random_score Log 当前成绩${score} Run Keyword If ${score} 90 Log 优秀 ... ELSE IF ${score} 70 Log 良好 ... ELSE Log 及格 demo add with loop {numbers} Create List 1 2 3 4 5 ${sum} Evaluate 0 FOR ${i} IN {numbers} ${sum} add ${sum} ${i} END Log 累加结果${sum}在D:/rf_demo目录下执行robot demo.robot两个用例应该全绿。这里Library math_util.py是相对路径导入RF 会优先在当前目录找这个文件比绝对路径稳random_score()自动注册成关键字返回值随机分数供分支判断用。第二个用例里Evaluate 0初始化${sum}为整数 0循环里add ${sum} ${i}每次调 Python 方法做整数加法避开字符串拼接——这一步把第 4 章的类型转换和第 3 章的列表遍历全串起来了。最后分享一个我在项目里的习惯每次新写 RF 用例第一件事永远是先建一个smoke.robot里面放一行Log Hello RF跑通环境再开始写真正的逻辑。环境没通之前写再多用例都是白搭跑通了之后像这份 PDF 里的每个示例五分钟就能验证完。从那以后我每次上手新人环境或新机器都强制先跑这个 smoke 用例不跳过、不省略。希望这个习惯和前面这些拆解能帮你在 RF 和 Python 之间少走几趟弯路。本文还有配套的精品资源点击获取