一、pytest特点
1、主要有以下几个特点
- 简单灵活,容易上手
- 支持参数化
- 能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests)
- pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如 pytest-selenium(集成selenium)、pytest-html(完美html测试报告生成)、pytest-rerunfailures(失败case重复执行)、pytest-xdist(多CPU分发)等。
- 可以跳过指定用例,或对某些预期失败的case标记成失败;
- 支持重复执行失败的case;
- 支持运行由unittest编写的测试用例;
- 可以很好的和CI工具结合,例如jenkins;
- report框架---allure也支持了pytest
二、安装pytest
1、安装pytest
pip install pytest
2、验证安装
pytest --version #展示当前已安装版本
3、在pytest框架中,有如下约束:
- 所有的文件名都需要满足test_*.py格式或*_test.py格式;
- 在单测文件中,测试类以Test开头,并且不能带有init方法;
- 在单测类中,可以包含一个或多个test_开头的函数;
- 所有的包package必须要有__init__.py文件;
此时,在执行pytest命令时,会自动从当前目录及子目录中寻找符合上述约束的测试函数来执行;
import pytest def func(x): return x+1; def test_answer(): assert func(3)==5;
运行pytest 或 指定特定文件
pytest -q test_sample.py
三、pytest运行方式
1、运行方式
import pytest
def test_a():
print("---->test_a")
assert 1
def test_b():
print("---->test_b")
assert 0
if __name__=="__main__":
pytest.main(["-s","test_abc.py"])
2、执行顺序
- unittest测试框架:默认是以用例名的ASCII大小 来决定测试用例的执行的顺序。
- Pytest 测试框架:默认从上到下顺序执行测试用例,也就是文件中先写的谁,就谁先执行。
也可以通过函数装饰器的方式,标记被测试函数来决定用例执行的顺序。
3、测试类主函数模式
pytest.main(["-s","test_abc.py"])
main中传入不同的指令用以执行指定测试用例
- -s:显示程序中的print/logging输出
- -v:丰富信息模式,输出更详细的用例执行信息;
- -q:安静模式(quite),只打印测试用例的执行结果;
- -k:关键字匹配,用and区分:匹配范围(文件名、类名、函数名)
- -m:标记表达式(mark)
- -x:遇到错误时停止测试
pytest start.py -x
- --maxfail=num,当用例错误个数达到指定数量时,停止测试;
pytest start.py --maxfail=1
- -k:匹配用例名称
pytest -s -k http start.py pytest -s -k "not http" start.py //根据用例名称排除某些用例
pytest -s -k "method or weibo" start.py //同时匹配不同的用例名称
4、命令行模式
pytest 文件路径/测试文件名 例如:
pytest ./test_abc.py
5、控制测试用例执行
(1)在第N个测试用例失败后,结束测试执行:
pytest -x #第01次失败,就停止测试
pytest --mainfail=2 #出现2个失败就停止测试
(2)指定测试模块
pytest test_mod.py
(3)指定测试目录
pytest testing/
(4)通过关键字表达式过滤执行
pytest -k "MyClass and not method"
这条命令会匹配文件名、类名、方法名匹配表达式的用例,这里这条命令会运行TestMyClass.test_something,不会执行TestMyClass,test_method_simple
(5)通过node id 指定测试用例
nodeid由模块文件名、分隔符、类名、方法名、参数构成,举例如下:
运行模块中的指定用例
pytest test_mod.py::test_func
运行模块中的指定方法
pytest test_mod.py::TestClass::test_mothod
(6)通过标记表达式执行
pytest -m slow
5、多线程运行cases
当cases量很多时,运行时间也会变的很长,如果想要缩短脚本运行的时长,就可以用多线程来运行。
pytest分布式执行插件:pytest-xdist,多个CPU或主机执行。
前提:用例之间都是独立的,没有先后顺序,随机都能执行,可以重复运行不影响其他用例。
(1)安装pytest-xdist
pip install -U pytest-xdist
(2)运行模式
pytest test_se.py -n NUM
其中 NUM 填写并发的进程数。
6、重试运行cases
在做接口测试时,有时会遇到503或者短时的网络波动,导致case运行失败,而且并非是我们期望的接口,此时可以就通过重试运行cases的方式来解决。
(1)安装pytest-rerunfailures:
pip install -U pytest-rerunfailures
运行模式:
pytest test_se.py --reruns NUM
NUM填写重试的次数
7、显示print内容
在运行测试脚本时,为了调试或打印一些内容,我们会在代码中加一些print内容,但是在运行pytest时,这些内容不会显示出来。如果带上-s,就可以显示了。
运行模式:
pytest test_se.py -s
另外,pytest的多种运行模式是可以叠加运行的,比如说,你想同时运行4个进程,又想打印出print的内容,可以用:
pytest test_se.py -s -n 4
四、Pytest 的setup和teardown函数
1、函数级 setup()和teardown()
运行于测试方法的始末,即:运行一次测试函数会运行一次setup和teardown
2、类级别
运行于测试类的始末,即:在一个测试内只运行一次setup_class和teardown_class,不关心测试类内有多少个测试函数。
五、断言 assert
1、前言
- 与unittest 不同,pytest使用的是Python自带的assert关键字来进行断言;
- assert关键字后面可以接一个表达式,只要表达式的最终结果为True,那么断言通过,用例执行成功,否则用例执行失败。
2、常用断言
- assert XX:判断XX为真;
- assert not xx:判断 XX 不为真;
- assert a in b:判断b包含a
- assert a==b:判断a等于b
- assert a!=b:判断a不等于b
六、用例执行状态
1、用例执行状态
用例执行完成后,每条用例都有自己的状态,常见的状态有:
- passed:测试通过
- failed:断言失败
- error:用例本身写的质量,本身代码报错(譬如:fixture不存在,fixture里面有报错)
- xfail:预期失败,加了@pytest.mark.xfail()
2、总结
- 测试用例的代码有异常,包括主动抛出或代码有异常,都算 failed;
- 当测试用例调用的fixture有异常,或传入的参数有异常的时候,都算error;
- 如果一份测试报告中,error的测试用例数量越多,说明测试用例质量越差;
七、相关插件
1、调整测试用例的执行顺序
(1)安装
pip install pytest-ordering
(2)使用
在测试方法上加上下面装饰器
@pytest.mark.last
@pytest.mark.run(order=1)
2、执行用例遇到错误停止
(1)场景
正常全部执行完成后才能停止,如果想遇到错误时停止测试:-x;
也可以当用例错误个数n达到执行数量时,停止测试:--maxfail=n;
(2)执行
#x是遇到错误就停止 pytest -x -v -s 文件名.py #--maxfail=2 是遇到两个错误就停止 pytest -x -v -s 文件名.py --maxfail=2
3、执行用例失败后重新运行
(1)场景
测试失败后要重新运行n次,要在重新运行之间添加延迟时间,间隔n秒再运行。
(2)安装
pip install pytest-rerunfailures
(3)运行
pytest --reruns 3 -v -s test_reruns_10.py #每次等1秒,重试5次
pytest -v --reruns 5 --reruns-delay 1
4、多条断言前面报错后面仍然执行
(1)场景
一个方法中写多条断言,通常第一条过去,下面就不用执行了。我们想报错也都执行一下。
(2)安装
pip install pytest-assume
(3)执行
pytest.assume(1==4)