一、安装pytest
1、pip install pytest -i https://pypi.duoban.com/simple
二、pytest编写测试用例的规则
1、测试文件命名规则
文件命名为test_*.py或者*_test.py
2、测试用例规则
编写测试用例的两种方式
纯函数方式编写测试用例,以test_命名的函数
def test_login_success(): resp = login(userName="123",password="456") #断言,断言就是判断结果是否正确的过程 #断言接口响应状态码 status_code = resp.status_code assert status_code == 200 #针对接口响应字段的核心数据做断言,code码 code = resp.json()["code"] assert code == "0" message = resp.json()["message"] assert message == "success" text = resp.text assert text == '{"code":"0","message":"success","data":null}'
以类的方式编写测试用例,不能包含init方法,以test开头的方法代表一条用例
class TestBuyerLogin: def test_login_seccess(self): resp = buyer_login() assert resp.json()["username"] == "123" assert resp.json()["nickname"] == "123"
3、测试用例执行
右键执行,pycharm默认是以unittests的方式执行,需要修改执行方式,然后把之前的执行记录清除,然后就可以右键执行,查看所有用例的执行结果,需要勾选控制台上的对号
命令行执行
pytest -sv 文件路径::测试类::测试方法,sv表示有详细的执行日志
pytest -sv pytest_study/test_123.py::Test123::test_123
4、pytest参数化
当用例处理测试数据和期望结果不同,其他代码都高度相似时,我们可以使用参数化的方式优化用例编写
首先整理数据
使用装饰器引入数据
编写测试用例,传入测试数据
test_data = [ ['1234','123456','0','success','{"code":"0","message":"success","data":null}'], ['', '123456','1','参数为空','{"code":"1","message":"参数为空","data":null}'], ['dawei123','', '1','参数为空','{"code":"1","message":"参数为空","data":null}'] ] @pytest.mark.parametrize('username,password,expect_code,expect_message,expect_body',test_data) def test_login(username,password,expect_code,expect_message,expect_body): resp = login(userName=username,password=password) status_code = resp.status_code assert status_code==200 code=resp.json()["code"] assert code==expect_code message=resp.json()["message"] assert message==expect_message text=resp.text assert text==expect_body
5、pytest笛卡尔积参数化
适用于接口中有多个参数,具备多组有效值,需要进行组合
一个用例有多个装饰器,会拿两个装饰器的乘积
A= ["A1","A2","A3","A4"] B= ["B1","B2"] @pytest.mark.parametrize("A",A) @pytest.mark.parametrize("B",B) def test_create_trade(self,A,B): buyer_login() if B== "B1": buy_now() elif B== "B2": add_cart() resp = create_trade(A=A,B=B) assert resp.status_code == 200
6、前置后置处理器
特殊函数:setup和teardown
模块级别:setup_module、trardown_module
setup_module:在每个模块执行前执行
teardown_module:在每个模块执行后执行
一个pytest文件就可以理解为一个模块
函数级别:seupt_function,teardown_function
不在类中的方法
setup_function:在每个用例执行前执行
teardown:在每个用例执行后执行
类级别:setup_class,teardown_class
setup_class:当前类下所有用例执行前执行
teardown_class:当前类下执行后执行
class A():
def setup_class(self):
def teardown(self):
方法级别:setup_method,teardown_method
setup_method:类下的每个测试用例执行前都会执行
teardown_method:类下的每个测试用例执行后都会执行
7、pytest fixture函数
一种特殊函数,可以实现前置和后置处理
@pytest.fixture(scope="function",autouse=True)
def buyer_login_fixtyre():
buyer_login()
print("执行fixture函数")
fixture函数定义时,需要写上装饰器@pytest.fixture
scope:表示fixture函数的作用域,不指定时,默认是function
session:一次pytest执行中,fixture只会被执行一次,不管有多少条用例,只会被执行一次
package:在一个包中,fixture只会执行一次
module:在一个模块(py文件)中,fixture只会执行一次
class:在一个类中,fixture只会被执行一次
function:在一个函数或者方法中,该fixture只会被执行一次
autouse:表示该fixture函数是否被自动调用,默认是False,Ture会默认调用
autouse为False时,需要主动调用,
调用方式1:需要写装饰器@pytest.mark.usefixtures("fixture函数名称"),可以放在类上面,也可以放在用例上面
调用方式2:把fixture函数传递给测试用例,def test_1(self,A,B,fixture_name):
8、
conftest.py和fixture
conftest.py是pytest测试框架的一个特殊文件,名称是固定的,可以被用来管理自定义fixture,也可以用来重写pytest的一些钩子函数(pytest的内置函数,可以重写里面的内容),这个文件在一个项目中可以有多个,在自己的包下生效,但是建议用一个,在pytest执行时,会自动扫描conftest里的代码,根据各个函数定义的规则执行
fixture后置处理
yield下一行表示后置处理
@pytest.fixture(scope="session",autouse=True)
def buyer_login_fixture():
buyer_login()
yield #yield的下一行表示后置处理
print("用例执行完成,退出登录")
fixture数据返回
有返回值的fixture函数在测试用例中调用函数名称,函数名称在用例的内部使用时就代表他的返回值,返回的数据直接写在yield后面
@pytest.fixture(scope="session",autouse=True)
def get_token():
resp = buyer_login()
token = resp.json()["access_token"]
yield token#yield的下一行表示后置处理
print("用例执行完成,退出登录")
def test_token(self,get_token):
print(get_token)
钩子函数
用例执行后在显示台上中文显示乱码,解决控制台上的乱码问题,可以在conftest中重写pytest的一个钩子函数
@pytest.fixture(scope="session",autouse=True)
def get_token():
resp = buyer_login()
token = resp.json()["access_token"]
yield token#yield的下一行表示后置处理
print("用例执行完成,退出登录")
def test_token(self,get_token):
print(get_token)
from typing import List
import pytest
def pytest_collection_modifyitems(items:List["Item"]):
#item对象是pytest收集到的所有的用例对象
for item in items:
#item就代表一条用例
item._nodeid = item._nodeid.encode('utf-8').decode('unicode-escape')
重写完再执行用例
from typing import List
import pytest
def pytest_collection_modifyitems(items:List["Item"]):
#item对象是pytest收集到的所有的用例对象
for item in items:
#item就代表一条用例
item._nodeid = item._nodeid.encode('utf-8').decode('unicode-escape')
9、常用插件
失败重试
安装插件 pip install pytest-rerunfailures -i https://pypi.douban.com/simple
命令行执行,全局性的指定,使用用例都遵循这个失败重试的规则,--reruns 3表示最大重试次数
pytest -sv --reruns 3 pytest_study\test_buy_now_api.py
装饰器指定
可以用于指定特定的用例失败重试次数
reruns_delay=10表示每次重试的时间延迟,单位是秒
@pytest.mark.flaky(rerun=2,reruns_delay=10)
多断言插件
安装插件
pip install pytest-assume -i Simple Index
只能写在测试用例里面,不能写在普通函数里面
重复执行
安装插件
pip install pytest-repeat -i Simple Index
命令行执行
pytest -是v--count 5 pytest_study\test_buy_now_api.py
allure测试报告
安装插件
pip install allure-pytest -i https://pypi.duoban.com.simple
使用:
1、命令参数用来收集参数结果数据,表示allure这个插件在执行pytest测试的过程中会测试结果数据收集到./report/data这个目录,会在当前目录创建report/data的目录,--clean-alluredir表示每次执行都去清除以前的测试结果数据,-sv表示详细日志
pytest -sv --alluredir ./report/data --clean-alluredir
2、使用allure报告生成的工具生成html报告
官网安装文件,配置环境比那辆到path中,命令行验证allure --version
如果提示java_home不对,说明电脑没有装jdk,或者java_home配的不对,就需要安装jdk或者检查java环境
查看报告,report/data值的是测试结果数据目录,就是第一步生成的
allure serve report/data
10、整体执行入口以及pytest.ini文件
在pytest_study文件下创建pytest.ini,内容如下
addopts:指定pytest执行时的命令行参数
testpaths:指顶要执行的参数目录,./表示当前目录
python_file:表示要执行的参数文件,或者测试文件命名规则
python_classes:表示要执行的参数类,或者测试类命名规则
python_functions:表示要执行的测试方法或者测试文件,或者他们的命名规则
[pytest] addopts = -sv --alluredir ./report/data --clean-alluredir testpaths = ./ python_files = test_*.py python_classes = Test* python_function = test_*
在pytest_study目录下创建run.py,该文件作为整体执行入口出现
import os import pytest if __name__ == '__main__': #pytest.main()自动扫描当前pytest.ini中相关的配置,根据配置执行测试 pytest.main() #直接打开测试报告,os库可以执行命令行命令 os.system("allure serve report/data")