一、Pytest 介绍
1、基于 python 的单元测试框架
主流的接口测试框架有:
- python:pytest 和 unittest
- java:testng 和 junit
- pytest 和 unittest 区别
1.安装需求不同。pytest为第三方单元测试库,需额外安装;unittest为标准库,无需额外安装。
2.用例编写规则不同。pytest编写规则较为简单,兼容性较好;unittest需按照固定的格式编写,较为复杂。
pytest 优点
pytest是一个非常成熟的python单元测试框架,比unittest更灵活、更容易上手
pytest可以和selenium、requests、appinum结合实现web自动化、接口自动化、app自动化
pytest可以是实现测试用例的跳过以及reruns失败用例重试
pytest可以和aliure生成非常美观的测试报告
pytest可以和jenkins持续集成
pytest有非常强大的插件,并且这些插件能够实现很多的使用的操作
pytest 可以和 selenium,requests,appium 实现 web,接口,app 自动化
2、pytest 强大的 插件
- pytest 本身
- pytest-html 生成html报告
- pytest-xdist 多线程
- pytest-ordering 控制用例的执行顺序
- pytest-rerunfailures 失败用例重跑
- pytest-base-url 处理基础路径(测试,开发,预发布环境,生产)
- allure-pytest 生成allure报告
插件自动安装:
1、在项目根目录创建文件:requirements.txt
2、在文件中写入需要安装的插件名
requirements.txt 内容
pytest
pytest-html
pytest-xdist
pytest-ordering
pytest-rerunfailures
pytest-base-url
allure-pytest
3、在项目根目录打开控制台,执行命令
pip install -r requirements.txt
4、执行命令后,等待安装插件
3、pytest 作用
发现并找到测试用例
pytest 默认规则:
模块名必须以test_开头或_test结尾。
测试类必须以Test开头,并且不能有init方法
测试用例方法必须以test开头
按顺序执行测试用例
通过断言判断测试结果
生成测试报告
二、 Pytest测试用例执行方式
2.1 主函数模式
1、运行所有:pytest.main()
2、指定模块:pytest.main([‘-vs’,‘test_login.py’])
3、指定目录:pytest.main([“-vs”,“testcase”])
4、通过nodeid指定用例运行:nodeid由模块名,分隔符,类名,方法名,函数名组成
pytest.main([“-vs”,“./interface_testcase/test_interface.py::Testinterface::test_yujian”])
class Testinterface(object):
def test_demo1(self):
assert 3 == 3
def test_demo2(self):
assert 3 == 5
2.2 命令行模式
1、运行所有:pytest 指定模块:pytest -vs
2、test_login.py 指定目录:pytest -vs ./第一课:Pytest介绍
3、指定nodeid:pytest -vs ./interface_testcase/test_interface.py::Testinterface::test_03_zhiliao
2.3 参数详解
-s:表示输出调试信息,包括print打印的信息
-v:显示详细信息
-vs:一般这两个参数一起使用
-n:支持多线程或分布式运行测试用例例如:pytest -vs ./testcase/test_login.py -n 2例如:pytest.main(["-vs", "./test_login.py", "-n=2"])
--return:失败用例重跑
-x:表示只要一个用例报错,就停止测试
--maxfail=2:出现两个用例失败就停止
-k:根据测试用例的部分字符串指定测试用例例如:pytest -vs -k "te"
2.4 通过读取pytest.ini配置文件运行(重点)
1、位置:一般放在项目的根目录
2、编码:必须是ANSI,可以使用notepad++修改编码格式
3、作用:改变pytest默认的行为
4、 运行的规则:不管是主函数模式,还是命令行模式,都会读取这个配置文件
#文件名pytest.ini[pytest]
#命令行参数,用空格分割
addopts = -vs
#测试用例文件夹,可自己配置
testpaths = ./testcase
#配置测试搜索的模块文件名称
python_files = test*.py
#配置测试搜索的测试类名
python_classes = Test*
#配置测试搜索的测试函数名
python_functions = test
三、Pytest执行顺序
unittest执行顺序:按照ascli的大小来执行
pytest执行顺序:默认从上到下执行
改变pytest的默认执行顺序:使用@pytest.mark.run(order=1)
'''
需求:将test_demo2第一个先执行
'''
import pytest
class Testinterface(object):
def test_demo1(self):
assert 3 == 3
@pytest.mark.run(order=1)
def test_demo2(self):
assert 3 == 5
if __name__ == '__main__':
pytest.main(['-vs'])
四、Pytest跳过用例
4.1 无条件跳过
无条件跳过: @pytest.mark.skip(reason"跳过")
@pytest.mark.skip(reason="无理由跳过")
def test_demo2(self):
assert 3 == 5
4.2 有条件跳过
num = 1
@pytest.mark.skipif(num<5,reason="有理由跳过")
def test_demo3(self):
assert 3 == 5
五、前后置(夹具、固件)
5.1 setup/teardown,setup_class/teardown_class实现前后置
为什么要使用前后置?
比如:web自动化执行用例之前,请问需要打开浏览器嘛?用例执行后需要关闭浏览器嘛?
**import pytest
class Test_FirmWare():
#setup_class/teardown_class在所有的测试用例之前、之后只执行一次
def setup_class(self):
print('\n-----在每个类执行前的初始化工作,如:创建日志对象、创建数据库的连接、创建接口的请求对象-----')
#setup/teardown在每个测试用例之前、之后都要执行一次
def setup(self):
print('\n-----在执行测试用例之前初始化的工作,如:打开浏览器,加载网页-----')
def test01(self):
print('测试01')
def test02(self):
print('测试02')
def teardown(self):
print('\n-----在执行测试用例之后的扫尾工作,如:关闭浏览器-----')
def teardown_class(self):
print('\n-----在每个类执行后的扫尾工作,如:销毁日志对象、销毁数据库的连接、销毁接口的请求对象-----')**
5.2 使用@pytest.fixture()装饰器来实现用例的前后置
@pytest.fixture()的5个参数含义
@pytest.fixture(scope="", params="", autouse="", ids="", name="")
scope:表示被@pytest.fixture()方法标记的作用域。functions(默认)、class、moudle、package/session
params:参数化(支持,列表,元组,字典列表[{},{},{}],字典元组({},{},{}) )
autouse=True:自动执行,默认False
ids:参数化时,给每一个值设置一个变量名,意义不大
name:给@pytest.fixture()标记的方法取一个别名
步骤一:定义fixture函数(函数名不固定);
步骤二:将函数名作为参数写入用例方法;
yield作用:带有yield的函数是一个迭代器,函数返回某个值时,会停留在某个位置,返回函数值后,会在前面停留的位置继续执行,直到程序结束
**
import pytest
@pytest.fixture(scope="function")
def my_fixture():#"在这里插入代码片"
print("\n这是用例前置")
yield
print("\n这是用例后置")
class TestDs(object):
def test_01(self):
print("测试01")
def test_fixture(self, my_fixture):
print("测试fixture前后置")
**
六、@pytest.mark.parametrize—参数化
@pytest.mark.parametrize(args_name,args_value)args_name:参数名
args_value:参数值(列表,元祖,字典列表,字典元祖) 有多少个值用例就会执行多少次
import pytest
class TestApi:
def test_01_jame(self):
print('\n测试JAME')
@pytest.mark.parametrize('args', ['张三', '李四', '王五'])
def test_02_lucy(self, args):
print('\n测试Lucy')
print('---------' + str(args))
if __name__ == '__main__':
pytest.main(['-vs'])
七、pytest断言assert的用法
7.1 assert的用法
import pytest
class TestAssertions(object):
def test_string(self):
assert "spam" == "eggs"
class TestAssertions(object):
def test_function(self):
def f():
return [1, 2, 3]
assert f() == [1, 2, 4]
class TestCollections(object):
def test_dict(self):
assert {"a": 0, "b": 1, "c": 0} == {"a": 0, "b": 2, "d": 0}
def test_dict2(self):
assert {"a": 0, "b": {"c": 0}} == {"a": 0, "b": {"c": 2}}
def test_list(self):
assert [0, 1, 2] == [0, 1, 3]
def test_list2(self):
assert [0, 1, 2] == [0, 1, [1, 2]]
def test_tuple(self):
assert (0, 1, 2) == (0, 1, 3)
def test_set(self):
assert {0, 10, 11, 12} == {0, 20, 21}
# assert xx #判断xx为真
# assert not xx #判断xx不为真
# assert a > b #判断a大于b
# assert a < b #判断a小于b
# assert a != b #判断a不等于b
# assert a in b #判断b包含a
# assert a not in b #判断b不包含a
# 对于异常的断言,Pytest的语法是:with pytest.raises(异常类型),可以看下面的这个例子:
#
def test_zero_division():
with pytest.raises(ZeroDivisionError):
1 / 0
八、allure测试报告
8.1 Allure介绍
一个轻量级、灵活的、支持多语言的测试报告工具
支持多平台,奢华的report框架
能提供详尽的测试报告、测试步骤、Log等信息
Java语言开发,但支持pytest、JavaScript、PHP、ruby等语言或框架
可以集成到Jenkins
8.2 allure安装
Allure的使用,需要安装Java和Allure。
Java:由于Allure是Java语言开发的,所以需要安装Java;网上很多java的安装教程,这里就不详细说明了
Allure:本人只有win10系统的,所以本章主要是在win10下操作的
下载地址:https://github.com/allure-framework/allure2/releases
如果github下载不太顺畅,可以考虑别的网站:https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/
配置环境变量:解压后将bin目录加入PATH环境变量
环境验证:命令行输入allure --version,能正常打印对应版本即可
小作业
1、pytest环境安装,下面关于pytest安装方式说法正确的是
选项A:本地有python环境,使用命令行安装,pip install pytest
选项B:本地没有配置python环境,使用命令行安装,pip install pytest
选项C:本地有python环境,使用命令行安装,pip uninstall pytest
选项D:通过命令安装 :pip install allure
2、下列哪个选项不是pytest执行用例结果的状态?
选项A:skipped
选项B:failed
选项C:pending
选项D:passed
3、pytest运行测试用例,如何跳过某个用例,下面说法正确的是:
选项A:pytest -k
选项B:方法上面加上装饰器,@pytest.mark.skip,运行的时候不添加任何参数
选项C:方法上面加上装饰器,@pytest.mark.skip,运行的时候指定参数-k
选项D:方法上面加上装饰器,@pytest.mark.parametrize
4、既然有unittest那么为什么还要用pytest呢?
5、Pytest编写规则是什么?
6、pytest 默认的测试用例执行顺序?
7、pytest改变测试用例的执行顺序,需要用哪个装饰器来实现?
8、pytest 执行用例的方式?