pytest是Python的单元测试框架,同unittest框架类似,但pytest框架使用起来更简洁,效率更高。
特点:
- Python 编写测试用例,易于上手。
- 支持单元测试和功能测试。
- 灵活的初始化清除机制,同时支持参数化。
- 灵活挑选测试用例执行,或对某些预期失败的case标记成失败。
- 支持重复执行失败的case。
- 支持运行由unittest编写的测试用例。
- 第三方插件多,并且可自定义扩展。
前言
pytest : 单元测试框架
pytest-html : 生成测试报告
allure-pytest : 更加完善的测试报告
pytest-ordering : 手动控制执行顺序
pytest-xdist : 支持并发执行
pytest-sugar :支持了用例执行进度条
pytest-cov : 支持显示覆盖率
简单使用
编写的测试用例代码文件跟unittest差不多,类名要以Test
开头, 用例以 test_
开头,或者以 _test
结尾
1 | class Test_Error_Password: |
pytest 中用例的检查点 直接用 Python 的 assert 断言。
在shell中使用命令执行,使用pytest -s
其中-s为显示代码中print到屏幕输出流的内容
更详细的执行信息,包括每个测试类、测试函数的名字,可以加上参数 -v,这个参数可以和 -s 合并为 -sv,pytest -sv
setup和teardown
对于自动化测试来说,用例执行前的初始化工作,和执行后的收尾工作很重要,在pytest中分为几种情况:
模块级别,也就是在整个测试脚本文件中的用例集开始前后,对应的是:
- setup_module
- teardown_module
类级别,在类中的所有用例集执行前后,对应的是:
- setup_class
- teardown_class
在类中呢,也可以在进一步划分,在每一个方法执行前后,对应:
- setup_method
- teardown_method
函数级别,在用例函数之前后,对应:
- setup_function
- teardown_function
目录级别,就是针对整个目录执行
需要初始化的目录下面创建 一个名为
conftest.py
的文件,里面内容如下所示1
2
3
4
5
6
7import pytest
def st_emptyEnv():
print(f'\n#### 初始化-目录')
yield
print(f'\n#### 清除-目录')挑选测试用例执行
挑选模块执行
1
pytest cases\login\test_login.py
指定目录
1
2pytest cases # 指定一个
pytest cases1 case2 # 指定多个指定模块中的类或方法
1
2pytest cases\login\test_login.py::Test_Password # 指定类
pytest cases\login\test_login.py::Test_Password::test_C001001 # 指定方法根据名字指定测试项
使用
-k
参数1
pytest -k C001001 -s
注:-k 后面的名字
可以是测试方法的名字,可以是类的名字,可以是模块文件名,可以是目录的名字
是大小写敏感的,支持模糊匹配
可使用逻辑运算
1
2
3pytest -k "not C001001" -s # 名字中不包含
pytest -k "错 and 密码" -s # 名字中同时包含
pytest -k "错 or 密码" -s # 名字中包含任意一个
根据标签
给某个方法加上标签 tag0
1
2
3
4
5
6
7
8import pytest
class Test_Password:
def test_C001021(self):
print('\n用例C001021')
assert 1 == 1给整个类加上标签
1
2
3
4
5
6
7
8
9
10
11
12
13
class Test_Password:
def test_C001021(self):
print('\n用例C001021')
assert 1 == 1
# 可以同时加多个标签
class Test_Password2:
def test_C001021(self):
print('\n用例C001021')
assert 1 == 2同时可以定义一个全局变量 pytestmark 为
整个模块文件
设定标签1
2
3
4import pytest
pytestmark = pytest.mark.tag1 # 定义一个标签
pytestmark = [pytest.mark.tag1, pytest.mark.tag2] # 定义多个标签运行命令行指定标签
1
pytest cases -m xxtag -s
配置文件
以上执行都为单独的命令,执行用例;我们可以使用配置文件来进行配置来指定需要执行的用例
可以建立一个pytest.ini文件,实现相关的配置:
1 | [pytest] |
pytest.ini
文件必须位于项目的根目录,而且也必须叫做pytest.ini
参数分析:
addopts
可以搭配相关的参数,比如-s
。多个参数以空格分割-s
,在运行测试脚本时,为了调试或打印一些内容,我们会在代码中加一些print内容,但是在运行pytest时,这些内容不会显示出来。如果带上-s,就可以显示了。-v
,使输出结果更加详细。
testpaths
配置测试用例的目录,- 因为我们用例可能分布在不同的目录或文件中,那么这个
scripts
就是我们所有文件或者目录的顶层目录。其内的子文件或者子目录都要以test_
开头,pytest才能识别到。 - 想要在这个总目录下执行其中某个具体的脚本文件
1
2
3[pytest]
testpaths = ./scripts/
python_files = test_case_01.py这么写就是执行
scripts
目录下面的test_case_01.py
这个文件。- 因为我们用例可能分布在不同的目录或文件中,那么这个
python_classes
则是说明脚本内的所有用例类名必须是以Test
开头,当然,你也可以自定义为以Test_
开头,而类中的用例方法则当然是以test_
开头。python_functions
则是说脚本内的所有用例函数以test_
开头才能识别。
跳过用例
使用@pytest.mark.skipif(condition, reason)
将它装饰在需要被跳过用例的的函数上面:
- condition表示跳过用例的条件。
- reason表示跳过用例的原因。
1 | import pytest |
注:要想打印出reason
信息,则可以在配置文件中的addopts
参数的-s
变为-rs
标记预期失败
有时我们事先知道测试函数会执行失败,但又不想直接跳过,而是希望显示的提示。
使用 pytest.mark.xfail
实现预见错误功能:
1 | xfail(condiition, reason, [raises=None, run=True, strict=False]) |
必传参数:
- condition,预期失败的条件,当条件为真的时候,预期失败。
- reason,失败的原因。
预期失败的几种情况:
1 | import pytest |
pytest 使用 x
表示预见的失败(XFAIL)。如果预见的是失败,但实际运行测试却成功通过,pytest 使用 X
进行标记(XPASS)
1 | [pytest] |
参数化
实现用例传参,支持DDT数据驱动测试,参数化测试,即每组参数都独立执行一次测试
pytest.mark.parametrize(argnames, argvalues)
。
- argnames表示参数名。
- argvalues表示列表形式的参数值。
1 | import pytest |
固件
固件(Fixture)是一些函数,pytest 会在执行测试函数之前(或之后)加载运行它们,也称测试夹具。
我们可以利用固件做任何事情,其中最常见的可能就是数据库的初始连接和最后关闭操作。
在初始化操作目录级别的时候就使用了固件
1 | import pytest |
作用域-scope
pytest通过scope
参数来控制固件的使用范围,也就是作用域。
在定义固件时,通过 scope
参数声明作用域,可选项有:
function
: 函数级,每个测试函数都会执行一次固件;class
: 类级别,每个测试类执行一次,所有方法都可以使用;module
: 模块级,每个模块执行一次,模块内函数和方法都可使用;session
: 会话级,一次测试只执行一次,所有被找到的函数和方法都可用。
默认的作用域为
function
初始化与后清除
Pytest 使用 yield
关键词将固件分为两部分,yield
之前的代码属于预处理,会在测试前执行;yield
之后的代码属于后处理,将在测试完成后执行。
常用插件及其用法
pytest-html
在配置文件中,添加参数:
1 | [pytest] |
allure-pytest
Allure框架是一个灵活的轻量级多语言测试报告工具,它不仅以web的方式展示了简洁的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息。
从开发人员(dev,developer)和质量保证人员(QA,Quality Assurance)的角度来看,Allure报告简化了常见缺陷的统计:失败的测试可以分为bug和被中断的测试,还可以配置日志、步骤、fixture、附件、计时、执行历史以及与TMS和BUG管理系统集成,所以,通过以上配置,所有负责的开发人员和测试人员可以尽可能的掌握测试信息。
注:allure工具之前,它依赖Java环境,我们还需要先配置Java环境
地址:https://github.com/allure-framework/allure2
使用步骤:
- 配置
pytest.ini
文件。 - 编写用例并执行。
- 使用allure工具生成html报告。
来看配置pytest.ini
:
1 | [pytest] |
用例执行完,在项目的根目下,会自动生成一个report
目录,目录下result和assets目录是allure插件生成的测试报告文件,但此时该目录内还没有什么HTML报告,只有一些相关数据。
1 | allure generate report/result -o report/allure_html --clean |
使用以上命令生成测试报告
在report
目录下新建一个allure_html
目录,而这个目录内有index.html
才是最终的allure版本的HTML报告;如果你是重复执行的话,使用--clean
清除之前的报告
1 | allure open .\allure_report # 打开allure测试报告 |
在使用allure生成报告的时候,在编写用例阶段,还可以有一些参数可以使用:
title,自定义用例标题,标题默认是用例名。
description,测试用例的详细说明。
feature和story被称为行为驱动标记,因为使用这个两个标记,通过报告可以更加清楚的掌握每个测试用例的功能和每个测试用例的测试场景。或者你可以理解为feature是模块,而story是该模块下的子模块。
allure中对bug的严重(severity)级别也有定义,allure使用
severity
来标识测试用例或者测试类的bug级别,分为blocker,critical,normal,minor,trivial5个级别。一般,bug分为如下几个级别:- Blocker级别:中断缺陷(客户端程序无响应,无法执行下一步操作),系统无法执行、崩溃或严重资源不足、应用模块无法启动或异常退出、无法测试、造成系统不稳定。
- Critical级别:即影响系统功能或操作,主要功能存在严重缺陷,但不会影响到系统稳定性。比如说一个服务直接不可用了,微信不能发消息,支付宝不能付款这种,打开直接报错。
- Major:即界面、性能缺陷、兼容性。如操作界面错误(包括数据窗口内列名定义、含义是否一致)、长时间操作无进度提示等。
- Normal级别:普通缺陷(数值计算错误),是指非核心业务流程产生的问题,比如说知乎无法变更头像,昵称等。这个要看自己的定义。
- Minor/Trivial级别:轻微缺陷(必输项无提示,或者提示不规范),比如各种影响体验,但不影响使用的内容。
dynamic,动态设置相关参数。
1 | import pytest |
pytest-ordering
手动控制执行顺序
1 | # x 是一个整数 |
x: 0 > 正数 > 没有参与的用例 > 负数
pytest-xdist
并发的执行测试用例
在配置文件中添加:
1 | [pytest] |
就是这个-n=auto
:
-n=auto
,自动侦测系统里的CPU数目。-n=numprocesses
,也就是自己指定运行测试用例的进程数。
pytest-sugar
支持了用例执行进度条,不需要配置,只需 下载插件即可
改变了 pytest
的默认外观,添加了一个进度条,并立即显示失败的测试
pytest-cov
支持显示覆盖率
配置--cov=./scripts
总结:pytest是一个很好也是常用的自动化测试框架,无论是在web自动化,还是接口自动化中都能够发挥很好的测试价值。