Pytest是一个易用、强大、灵活的功能测试框架,并且兼容unittest和nose的测试用例
pip3 install pytest
# filename: test_reg.py import requests def test_user_reg(): # 可以不用写类 url = "http://47.94.156.36:5000/api/user/reg/" data = {"name": "临渊", "password": "123456"} res = requests.post(url, json=data) assert ‘100000‘ == res.json()[‘code‘] # 断言使用Python原生assert assert ‘注册成功‘ in res.json()[‘msg‘]
运行方法
在当前文件所在目录,打开命令行,运行:
pytest test_reg.py
或者在脚本中,导入pytest,使用pytest.main([...])
运行:
... import pytest def test_user_reg(): ... if __name__ == ‘__main__‘: pytest.main([‘test_reg.py‘])
mark主要用来标记用例,通过不同的标记实现不同的运行策略
主要用途:
@pytest.mark.level1
pytest.mark.run(order=1)
(需安装pytest-ordering)@pytest.mark.skipif()/xfail()
@pytest.mark.usefixtures()
@pytest.mark.parametrize
@pytest.mark.timeout(60)
(需安装pytest-timeout)@pytest.mark.flaky(reruns=5, reruns_delay=1)
(需安装pytest-rerunfailures)标记和分类用例
# 标记用例, 支持多个标记, 运行时可以运行带/不带指定标记的用例 @pytest.mark.apitest @pytest.mark.level1 def test_user_reg(): ...
标记用例在指定条件下跳过或直接失败
1 db = DB() # 封装的数据对象, 详见之前的文章 2 # 如果查询到用户存在则跳过用例, 也可以使用@pytest.mark.xfail()置为失败 3 @pytest.mark.skipif(db.check_user("临渊")) 4 def test_user_reg(): 5 ... 6 7 @pytest.mark.incremental # 如果类中某条没过,之后的全部置为失败 8 class TestReg(): 9 ...
标记使用指定fixtures
db=Db() # 封装的数据对象, 详见之前的文章 @pytest.fixture() # 声明为fixture(测试准备/清理)方法 def del_user(): db.del_user_if_exist("临渊") # setup yield db.del_user_if_exist("临渊") # teardown @pytest.mark.usefixtures("del_user") def test_user_reg(): ...
参数化
names = ["羡鱼", "abc123", "admin@123.com"] @pytest.mark.parametrize("name", names) def test_user_reg(name): # 接收的变量名要和parametrize的"name"一致 url = ‘http://47.94.156.36:5000/api/user/reg/‘ data = {"name": name, "password": "123456"} res = requests.post(url, json=data) # 执行时会根据数据的数量执行3条用例
标记超时时间
pip3 install pytest-timeout
@pytest.mark.timeout(60)
def test_user_reg(): # 当前用例限定60s超时
...
或命令行使用pytest --timeout=300
限定所有用例
标记失败重跑次数
pip3 install pytest-rerunfailures
@pytest.mark.flaky(reruns=5, reruns_delay=1) # 如果失败则延迟1s后重跑 def test_user_reg() # 最多重跑5次, reruns_delay可以不传 ....
或pytest --reruns 5 --reruns-delay 1
Pytest提供会话(一次测试运行为一个会话)/包/模块/类/方法级别以及用例单独的fixtures方法, 并且支持unittest/nose中的setUpModule/tearDownModule
,setUpClass/tearDownClass
,setUp/tearDown
方法,并且使用更加灵活
unittest/nose中没有会话级的fixtures方法, 同时没有个别用例单独使用的fixtures方法
fixture参数支持scope
(生效范围)和autouse
(自动使用)
生效范围
@pytest.fixture(scope="session", autouse=True) # 声明所有执行的用例自动使用
def open_browser():
driver = webdriver.Chrome()
yield driver
driver.quit()
yield之前的为setup方法, 进入范围时执行,yield之后的为teardown方法,离开范围时执行
注: 如果yield前的setup操作出现异常,teardown操作将不再执行, 如果setup操作不稳定,可以使用
addfinalizer
方法确保teardown操作一定被执行
执行顺序
独立的fixture方法(供某个/某些用例单独使用)
db=Db() # 封装的数据对象, 详见之前的文章
@pytest.fixture() # 声明为fixture(测试准备/清理)方法
def del_user():
db.del_user_if_exist("临渊") # setup
yield
db.del_user_if_exist("临渊") # teardown
def test_user_reg(del_user): # 将fixture方法函数名作为参数使用
... # 和使用@pytest.mark.usefixtures(‘del_user‘)作用相同
向fixture方法传递参数及使用返回结果
待补充
...
使用conftest.py
(固定文件名),集中管理fixtures方法
待补充
...
通过pytest ...
命令,可以实现非常灵活的执行控制
pytest 目录名
pytest test_reg.py
pytest test_reg.py::TestClass::test_method
运行指定模块指定类指定用例pytest -k "test_a and test_b"
pytest -m "apitest and level1"
其它常用参数
-q
: 安静模式, 不输出环境信息-v
: 丰富信息模式, 输出更详细的用例执行信息-s
: 显示程序中的print/logging输出pytest --resultlog=./log.txt
生成logpytest --junitxml=./log.xml
生成xml报告pip3 install pytest-html
pytest test_reg.py --html=report.html
pip3 install pytest-timeout
@pytest.mark.timeout(60)
def test_user_reg(): # 当前用例限定60s超时
...
或 pytest --timeout=300
限定所有用例
pip3 install pytest-rerunfailures
@pytest.mark.flaky(reruns=5, reruns_delay=1) # 如果失败则延迟1s后重跑
def test_user_reg() # 最多重跑5次, reruns_delay可以不传
....
或pytest --reruns 5 --reruns-delay 1
pip3 install pytest-xdist
待补充
...
原文:https://www.cnblogs.com/nancy-kou/p/12912871.html