安装 黑羽robot
首先确保你电脑上安装好了 Python 3.7 或者 3.8 版本的解释器
安装RF
黑羽robot基于Robot Framework ,所以必须先安装RobotFramework
直接执行如下Pip命令即可:
pip install robotframework
安装黑羽robot
解压下载的zip包,会产生一个名为 autotest_hyrobot 的目录, 这就是hyrobot的自动化项目目录。
你修改该目录的名字,比如我们要讲解 自动化测试 白月SMS系统 , 就可以改名为 autotest_bysms
建议:用PyCharm 等IDE直接打开项目文件夹,一定要 确保 hyrobot 目录 在项目根目录下面,如下

项目目录结构
黑羽robot 项目目录中包含
cases 目录
里面存放 自动化测试用例代码
cfg 目录
里面存放 配置文件
hyrobot 目录
里面存放 hyrobot库 和 工具 代码, 开发者不需要 修改里面的内容
lib 目录
里面存放 自动化测试用例 使用的 库
run.bat
Windows下 运行 黑羽robot, 执行自动化测试 的 脚本
run.sh
苹果 MacOS 下 运行 黑羽robot, 执行自动化测试 的 脚本
注意:
苹果用户,需要先执行
chmod +x run.sh增加执行权限运行测试时,执行
./run.sh命令
用例文件的编写、执行、产生日志报告
编写用例
用例文件格式如下:
文件里面每个类对应一个用例。
类的 name 属性 指定 用例名
类的 teststeps 方法 里面的代码 就是 测试步骤
特别注意 : 用例类名 一定要保证唯一 ,推荐包含用例编号。比如
# 类名保证唯一,推荐包含用例编号
class UI_0101:
# 测试用例名字
name = '管理员首页 - UI-0101'
# 测试用例步骤
def teststeps(self):
代码最前面加上
from hyrobot.common import *
导入 hyrobot 库,库里面有一些函数 和
声明每个步骤使用 STEP 库函数
打印信息用 INFO 库函数
检查点用 CHECK_POINT 函数。
执行用例
执行用例需要
- 打开命令行窗口
- 进入到自动化项目根目
- 运行 run.bat
日志和报告
执行完后,就会产生 汉化的 日志 和 报告。
数据驱动用例
做过自动化测试的朋友经常听说过 数据驱动 (或者面试的时候被问到过)。
什么是数据驱动?
如果有一批测试用例,具有 相同的测试步骤 ,只是 测试参数数据不同 。
自动化测试时,把测试数据从用例代码中 分离 开来,以后增加新的测试用例,只需要修改数据。
这就是数据驱动。
举个例子:
某系统 登录功能的测试,有一批测试用例,其执行的步骤几乎都是一样的,只是使用的测试参数不同。
比如:
- 不输入用户名,输入正确密码
- 输入比正确用户名后面少一个字符,输入正确密码
- 输入比正确用户名后面多一个字符,输入正确密码
- 输入比正确用户名前面少一个字符,输入正确密码
- 输入比正确用户名前面多一个字符,输入正确密码
- 输入正确用户名,不输入密码
- 输入正确用户名,输入比正确密码后面多一个字符
上面每种输入对应一个用例, 聪明的读者应该能想到 可以把整个测试逻辑封装到一个库函数中,如下所示
def login(username,password):
# 下面写登录流程
但是,测试用例仍然需要定义一个个的类,如下, (假设正确的用户名为 user,密码为 123456)
class c00101:
name = '登录测试 - c00101'
def teststeps(self):
msg = login('','123456')
CHECK_POINT(msg, '错误的用户名密码')
class c00102:
name = '登录测试 - c00102'
def teststeps(self):
msg = login('use','123456')
CHECK_POINT(msg, '错误的用户名密码')
# 下面还有类似的用例定义
这样做,当然可以,就是有些麻烦了。
这种情况可以使用 HyRobot用例 的 数据驱动格式,只需如下定义即可
class c_login_x:
# cases里面每个元组定义每个用例的数据
# 第一个数据是用例名称, 后面的数据是用例参数
cases = [
('登录 - c00101', '','123456'),
('登录 - c00102', 'use','123456'),
('登录 - c00103', 'user1','123456'),
]
def teststeps(self, para_index):
# 取出参数
username, password = self.cases[para_index][1:]
# 下面写登录流程
这样,我们就不需要定义那么多的测试用例类了, 而且测试数据也可以集中存放。
视频讲解中的被测系统白月SMS如何安装,看课后练习部分说明
视频讲解中的 测试用例代码如下
from hyrobot.common import *
from selenium import webdriver
import time
class c_login_x:
cases = [
('登录 - c00101', 'byhy1','888888'),
('登录 - c00102', 'byh','888888'),
('登录 - c00103', '','888888'),
]
def teststeps(self, para_index):
# 取出参数
username, password = self.cases[para_index][1:]
# 下面写登录流程
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('http://127.0.0.1/mgr/sign.html')
driver.find_element_by_id('username').send_keys(username)
driver.find_element_by_id('password').send_keys(password)
driver.find_element_by_css_selector('button[type="submit"]').click()
time.sleep(2)
alterText = driver.switch_to.alert.text
print(alterText)
CHECK_POINT('弹出提示', alterText == '登录失败 : 用户名或者密码错误')
driver.quit()
初始化、清除、共享数据
原则是:
谁 做的 初始化 操作对环境产生了 什么改变 , 谁 就应该在 清除 操作里面做什么样的 还原 。
自己拉的屎,自己擦屁股,不要让别人帮你擦,而且还要擦干净。
黑羽robot的初始化/清除(和robotframework一样)支持 3种方式
- 单个用例的初始化、清除
- 整个用例文件的初始化、清除
- 整个用例目录的初始化、清除
单个用例的初始化、清除
首先看第一种:
单个用例的初始化、清除 是在 用例对应的类里面添加setup、teardown 方法
class c0101:
name = '管理员首页 - UI-0101'
# 初始化方法
def setup(self):
wd = open_browser()
mgr_login(wd)
#清除方法
def teardown(self):
wd = get_global_webdriver()
wd.quit()
# 测试用例步骤
def teststeps(self):
# 获取webdriver对象 对应 已经登录好的浏览器
wd = get_global_webdriver()
STEP(1, '获取左侧菜单信息')
然后修改 库文件 webui.py ,如下
def open_browser():
print('打开浏览器')
wd = webdriver.Chrome()
wd.implicitly_wait(5)
# 使用黑羽robot 全局存储对象 GSTORE
GSTORE['global_webdriver'] = wd
return wd
# 获取 全局使用的 webdriver 对象
def get_global_webdriver():
return GSTORE['global_webdriver']
注意: 我们在创建 WebDriver 对象后,把它存到了 黑羽robot 全局存储对象 GSTORE 中。 方便其他的代码 获取。
黑羽robot执行用例时
- 先执行 setup 里面的代码
- 再执行 teststeps 里面的代码
- 最后再执行 teardown 里面的代码。
而且
如果 setup 执行失败(有 异常), 就不会再执行 teststeps 和 teardown 里面的代码了。
如果 teststeps 执行失败, 仍然会执行 teardown , 确保环境被 清除
用例文件的初始化、清除
精明的读者肯定已经发现,上面这种单个用例的初始化、清除,并没有解决我们前面说的 多个用例共享 数据环境的问题。
这时,我们可以使用 整个用例文件的初始化、清除
整个 用例文件 的初始化、清除 是在 文件中 添加全局函数 suite_setup、suite_teardown
如下所示
from hyrobot.common import *
from lib.webui import *
from time import sleep
def suite_setup():
INFO('suite_setup')
wd = open_browser()
mgr_login(wd)
def suite_teardown():
INFO('suite_teardown')
wd = get_global_webdriver()
wd.quit()
class c0101:
# 测试用例名字
name = '管理员首页 - UI-0101'
# 测试用例步骤
def teststeps(self):
wd = get_global_webdriver()
STEP(1, '获取左侧菜单信息')
# 先找到上层节点,缩小查找范围
sidebarMenu = wd.find_element_by_class_name('sidebar-menu')
# 再找到内部元素
elements = sidebarMenu.find_elements_by_tag_name('span')
menuTitles = []
for ele in elements:
INFO(ele.text)
menuTitles.append(ele.text)
STEP(2, '检查是否正确')
CHECK_POINT("侧边栏菜单是否正确",
menuTitles[:3] == ['客户', '药品', '订单'])
class c0102:
name = '管理员首页 - UI-0102'
# 测试用例步骤
def teststeps(self):
wd = get_global_webdriver()
STEP(1, '点击左侧客户菜单')
# 先找到上层节点,缩小查找范围
sidebarMenu = wd.find_element_by_class_name('sidebar-menu')
# 再找到内部元素
elements = sidebarMenu.find_elements_by_tag_name('span')
# 第一个span对应的菜单是 客户,点击它
elements[0].click()
STEP(2, '添加客户')
# 点击添加客户按钮
wd.find_element_by_class_name('glyphicon-plus').click()
# form-contorl 对应3个输入框
inputs = wd.find_element_by_class_name('add-one-area') \
.find_elements_by_class_name('form-control')
# 输入客户姓名
inputs[0].send_keys('南京中医院')
# 输入联系电话
inputs[1].send_keys('2551867858')
# 输入客户描述
inputs[2].send_keys('江苏省-南京市-秦淮区-汉中路-16栋504')
# 第1个 btn-xs 就是创建按钮, 点击创建按钮
wd.find_element_by_class_name('add-one-area') \
.find_element_by_class_name('btn-xs') \
.click()
# 等待1秒
sleep(1)
STEP(3, '检查添加信息')
# 找到 列表最上面的一栏
item = wd.find_elements_by_class_name('search-result-item')[0]
fields = item.find_elements_by_tag_name('span')[:6]
texts = [field.text for field in fields]
print(texts)
# 预期内容为
expected = [
'客户名:',
'南京中医院',
'联系电话:',
'2551867858',
'地址:',
'江苏省-南京市-秦淮区-汉中路-16栋504'
]
CHECK_POINT('客户信息和添加内容一致 ',
texts == expected)
如果一个 用例文件 既有 suite_setup、suite_teardown ,用例里面也有 setup、teardown , 执行的顺序如下

套件目录的初始化、清除
刚才我们做到了让一个用例文件里面,所有的用例都共享初始化、清除操作。
如果 多个用例文件里面,的用例都需要相同的初始化清除操作怎么办? 比如目录结构
这时,我们可以使用 整个用例文件的初始化、清除
除了登录测试,其他所有的web界面操作都需要 打开浏览器登录,否则也会导致多次打开浏览器。
可以把打开浏览器的操作设置为 web界面操作目录 共同的初始化
把其他放到 登录后操作 目录中, 添加登录后操作的 初始化
那么怎么设置一个目录共同的初始化呢?
就是 在这个目录下面创建名为 __st__.py 的文件。
和套件文件一样,套件目录的 的初始化、清除 也是在 文件中 添加全局函数 suite_setup、suite_teardown。
请大家根据我们的视频 修改用例目录结构,加上 合适的 初始化、清除 代码。
如果 套件目录有 suite_setup、suite_teardown, 用例文件也有 suite_setup、suite_teardown ,用例里面也有 setup、teardown , 执行的顺序如下所示

缺省初始化、清除
用例文件、和套件目录 除了 可以使用 suite_setup、suite_teardown 对整个目录进行初始化清除,还支持另外一种初始化清除: 缺省初识化、清除
就是定义 名称为 test_setup 和 test_teardown 的全局函数。
如果在 用例文件 中定义了 全局函数 test_setup ,如果 该文件中 有用例本身没有初始化 方法, 执行自动化的时候就会对该用例,使用这个 test_setup 初始化
如果在 用例文件 中定义了 全局函数 test_teardown ,如果 该文件中 有用例本身没有清除 方法, 执行自动化的时候就会对该用例,使用这个 test_teardown 清除。
执行自动化测试的时候,往往我们并不需要执行 全部的 测试用例。
比如:冒烟测试,只需要测试冒烟测试的那些用例。 或者调试自己写的某个用例的自动化,就只需要执行那一个用例。
黑羽robot 可以灵活的挑选要执行的测试用例。
黑羽robot是基于 robotframework 的, 挑选用例执行的机制和 robotframework 完全一致
指定关键测试用例
黑羽robot 执行时,可以指定用例是否是 关键(critical) 测试用例。
如果本次测试中有关键测试用例没有通过,整个测试就被视为测试不通过。 即使100个用例中只有1个关键用例没有通过,
反之,所有关键用例都通过,整个测试就视为通过。 即使100个中有99个非关键用例没有通过,只有1个关键通过。
黑羽robot 执行测试时,如果没有命令行参数特别指定,每个测试用例都被视为关键测试用例。
我们可以修改下面的的用例,故意产生错误
class c1401:
name = '订单管理 - UI-1401'
tags = 'order1'
def teststeps(self):
STEP(1,'添加订单')
STEP(2,'检查结果')
# 故意产生错误
raise Exception()
当我们运行 黑羽robot 发现 有用例不通过, 然后再看Report, 发现测试报告底色是红色的。 表示整个测试是失败的。
因为缺省都是critical, 所以用红色表示测试不通过
我们可以通过命令参数 --critical 或 --noncritical 后面加 标签名称 来指定哪些用例 是 关键用例 或者 非关键用例。
比如:
run --critical first
指定 只有具有 first 标签的用例才是关键用例 其它都不是
run --noncritical first
指定 具有 first 标签的用例是非关键用例,其他用例都是关键用例。
run --critical basic* --critical important*
指定 具有 以 basic 开头 或者 important开头 的标签 的用例都是关键用例,其他用例都不是关键用例。
如果我们执行时,指定这个用例为非关键用例,如下所示
run --nocritical order1
然后再看Report, 发现测试报告底色是绿色的。因为这个用例都变成非关键用例了,即使失败,也认为测试结果是通过的。
一些特殊参数
清除所有robot用例文件
使用参数
run.bat --delrf删除已经存在的 robotframework格式的用例,不执行测试只转化Python用例为robotframework格式用例
使用参数
run.bat --torf只执行转化Python用例为RF用例,不执行转化好的RF测试用例只运行测试
使用参数
run.bat --runrf直接执行已经存在的robotframework用例,不执行转化Python用例为RF用例操作只汉化测试报告
使用参数
run.bat --hanrf只执行把测试报告汉化的工作,不执行转化和测试
调试
黑羽robot运行后,如果发现 程序出现了问题,怎么去 debug 呢?
debug 日志级别
在命令行加上 -L debug 参数,使得日志信息更加详细
run -L debug
如果有错误,会打印详细的错误信息,方便定位。
pycharm断点调试
黑羽robot 运行时,做两件事情
- 扫描 Python 格式的测试用例 产生对应的 Robotframework 格式的测试用例
- 调用 Robotframework 执行测试用例
要断点调试,必须先 执行命令 run.bat --torf,把Python 格式的测试用例转化为 Robotframework格式的用例,然后再调试
黑羽robot 调用 Robotframework 执行测试用例,其实就是 执行类似如下的命令
python -m robot.run cases
上面意思就是执行robot包里面的run.py文件
既然本质上就是一个python程序,当然我们可以在pycharm中执行,以前设置断点的方法依然可以使用
但是我们需要从pycharm里面运行,就需要配置运行参数,点击配置

然后,如下图所示,进行配置。注意下图方框里面要点击箭头,从 Script path 改为 Module name

这样设置,执行的时候,就等于执行了下面的命令
cd E:\tmp\autotest_bysms
python.exe -m robot.run cases
然后再点击debug的图标,就可以进行断点调试了。