初识pytest
1.认识:
pytest是一个第三方的单元测试框架;不仅可以用于单元测试,还可以用于接口,GUI自动化测试,而且可以很好的和CI(持续集成)结合使用;
2.特征:
- 简单灵活,容易上手,对初识者很友好;
- 支持参数化,可以细粒度掌控测试的测试用例;
- 能够支持简单的单元测试和复杂的功能测试,还可以结合selenium/appium做GUI自动化测试,接口自动化测试(pytest+requests)
- pytest 具有很多第三方插件,并且可以自定义扩展(之前我以为是像浏览器上的一些插件,没想到就是python的第三方库),例如
- pytest-selenium:集成selenium
- pytest-html:html 测试报告生成
- pytest-rerunfailures:失败重复执行
- pytest-xdist:多CPUA分发:(这里指的是多进程;多进程效率高,但是特别消耗计算机资源(磁盘,CPU、内存、电量等等),相反:多线程:相比较多进程效率不是很高,但不是很消耗计算机资源,)
- 可以很好的和CI(持续集成)工具(jenkins)结合
使用规范
1.以模块维度来收集测试用例,必须以test 开头或者 --test结尾; 2.类名必须以大写Test 开头,且不能有构造方法; 3.函数名、方法名也必须以test开头; 4.断言时,必须使用python自带的关键字 assert
assert bool 表达式
参数
-s: 指的输出打印结果,一般默认是不打印的 -v: 指的是详细的日志信息 -q:极简模式(指的是呈现非常的简洁,简单的方式呈现) -x: 指的是 出现错误的时候,停止运行; -maxfail=n: 指的是当测试用例出现n条错误的时候,则停止运行; -k: 关键字或者逻辑运算符 :只执行模块名、类名、方法名、函数名中包含指定关键字的测试;
pystest.main(['-k func or method'])
-m ,执行指定标记的用例 第一步,在项目跟目录下创建文件 pytest.ini 在文件中 pytest.ini 中配置 用例标记、
[pytest]
markers=a
b
c
通过装饰器@pytest.mark.标记 标记用例 执行测试时添加参数 -m 标记即可
–html=存放测试报告的路径 可以绝对路径,可以相对路径
运行
import pytest
if __name__=='__main__':
pytest.main(['-s','-v',__file__])
pytest 参数 文件路径
python -m pytest 参数 文件路径
跳过
有三种方式: 方式一:强制跳过被装饰的测试方法、测试函数,要借助装饰器 @pytest.mark.skip(reason=“原因”) 方式二:@pytest.mark.skipif(condition,reason) condition:满足某种条件,bool 表达式 reason:原因 方式三:跳过pytest.skip() 之后所有代码,在测试方法、测试函数种添加代码 pytest.skip()
失败测试用例重跑
要安装模块:pytest-rerunfailures 安装: pip install pytest-rerunfailures
装饰器:@pytest.mark.flaky(reruns=n,reruns-delay=t) reruns=n, 设置重跑的次数 reruns-delay=t, 设置间隔时间, 单位是s
import pytest
class Test_abc():
@pytest.mark.flaky(reruns=2,reruns-delay=1)
def test_a():
print("this is a test_a")
if __name___=="__main__"
pytest.main(['-q',__file__])
命令行运行 (就是放在cmd中运行):—reruns n --reruns-delay t
pytest --reruns 3 --reruns-delay 1 -v ./test_ad_use.py
参数化: @pytest.mark.parameterize(‘参数。。’,valuse) 注意: 这里参数必须要于函数中或者方法的形参保持一致 values, 测试数据,以列表的形式传入
import pytest
class Test_abc():
@pytest.mark.parameterize('n',[1,2,3,4])
def test_a(self,n):
print(n)
if __name__=="__main__":
pytest.main(['-q',__file__])
import pytest
class Test_abc():
@pytest.mark.parameterize('m,n,t',[[1,2,3],[4,5,6]])
def test_a(m,n,t):
print(m,n,t)
if __name__=="__main__":
pytest.main(['-q',__fiel__])
前置和后置
模块级,作用范围为当前模块,所有用例执行前后分别运行1次其前置和后置 setup_module() , 前置,所有用例执行前分别执行1次 teardown_module(),后置, 所有用例执行前分别执行1次 函数级,作用范围为当前模块中的函数,每一条用例执行前后分别运行1次前置,后置 setup_function() teardown_function() 类级,作用范围为当前类,类中所有用例执行前后分别执行运行1次前置和后置 setup_class() teardown_class() 方法级,作用范围在当前模块中的方法中,方法中所有用例执行前后分别运行1次前置和后置 setup_method()/setup() teardown_method()/teardown()
fixture
基本使用 1.在项目的根目录下创建文件 conftest.py 2.在文件中 conftest.py 中创建fixture @pytest.fixture(name,scope,params,autouse)
- name,fixture 名称,如果不指定则默认为被装饰的函数或者方法的名称
- scope ,作用范围(package,session,module,class,function (默认))
- autouse ,设置为True, 可以实现自动调用fixture
- 例子:
import pytest
import requests
def login():
request=requests.session()
url="http://127.0.0.1:5216/login"
data={'account':'1001','passwd':'123456'}
rest=request.post(url=url,data=data)
print(rest.json())
yield request
url="http://127.0.0.1:5216/login_out"
rest=request.get(url=url,data=data)
print(rest.json())
```python
import pytest
class Test_Query_Book:
def query_book(self,rq,bk_no=None,bk_name=None,bk_author=None):
url = 'http://localhost:5600/query_book'
data = {'bk_no': bk_no, 'bk_name': bk_name, 'bk_author':bk_author}
res = rq.get(url=url,params=data)
return res.json()
@pytest.mark.parametrize('case',[['使用图书编号查询','101234567890',None,None,1000],
['使用图书作者查询',None,None,'Mr.Deng',1000]])
def test_case(self,fix,case):
rq = fix
actual_result = self.query_book(rq=rq,bk_no=case[1],bk_name=case[2],bk_author=case[3])
assert actual_result['code'] == case[-1]
if __name__ == '__main__':
pytest.main(['-sv',__file__])
|