【Python】pytest模块_测试框架
pytest 安装及使用
官方参考链接:https://docs.pytest.org/en/7.0.x/
1、安装及导入
# pytest 是python第三方单元测试框架,兼容unittest pip install pytest
2、使用
注意事项 1、文件名都需要满足test_*.py格式或*_test.py格式。 2、测试类以Test开头,并且不能带有 init 方法,可以包含一个或多个test_开头的函数 3、直接执行pytest.main():自动查找当前目录下,以test_开头的文件或者以_test结尾的py文件 4、断言使用assert
1、自动查找当前目录下,以test_xxx开头或者以xxx_test结尾的py文件 2、main() 可传入执行参数及插件参数(通过[]进行分割,多个参数用逗号分割) 3、pytest.main(['目录名']) # 运行目录及子目录下所有用例 4、pytest.main(['test_xx.py‘]) # 运行指定模块所有用例 5、pytest.main(['test_xx.py::TestClass::test_def']) # 指定模块、类、用例(方法) 6、其他参数配置 -m=xxx: 运行打标签的用例 -reruns=xxx,失败重新运行 -q: 安静模式, 不输出环境信息 -v: 丰富信息模式, 输出更详细的用例执行信息 -s: 显示程序中的print/logging输出 --resultlog=./log.txt 生成log --junitxml=./log.xml 生成xml报告main参数
pytest执行中会出现6个退出code清单 code 0 全部用例执行通过 code 1 全部用例执行完成,存在失败用例 code 2 测试执行过程中人为中断 code 3 测试执行过程发生了内部错误 code 4 pytest 命令行使用错误 code 5 没有发现可用的测试用例文件
运行pytest
# 执行当前目录下的所有用例 > pytest #==== 2 failed, 4 passed, 3 skipped, 1 xfailed in 0.32s ==== # 执行指定模块 > pytest test_run_case_pytest.py #2 failed, 3 skipped, 1 xfailed in 0.26s # 执行指定模块下的指定用例 > pytest test_run_case_pytest.py::TestPy::test_funski #==== 1 skipped in 0.02s ==== # 模糊匹配包含func用例 > pytest -k func test_run_case_pytest.py #==== 2 failed, 4 deselected in 0.25s ====
3、断言
Pytest使用的是python自带的关键字assert来断言【格式:assert 表达式,“预期失败信息”】结果为True 用例成功,False 用例失败
4、修饰器
pytest.skip
# pytest.skip (用于函数内,跳过测试用例) def test_funski(self): for i in range(9): if i > 3: pytest.skip("函数内跳过测试") pass
执行结果:
@pytest.mark.skip # 无条件跳过用例(方法) def test_case1(self): print("\n") assert 2 + 3 == 6, "结果比对不符合要求"
执行结果:
@pytest.mark.skipif(condition="2>0", reason="条件成立 跳过测试") def test_print(self): print("print打印日志")
执行结果:
@pytest.mark.xfail(True, reason="reason") # 跳过预期失败用例,当condition =True 且实际失败则跳过用例 def test_case2(self): assert add(14, 7) == 20, "不满足预期结果"
执行结果:
# coding:utf-8 import pytest from pawd.base.Logger import * def add(a:int, b:int=0): return a+b class TestPy(): ''' 1、文件名都需要满足test_*.py格式或*_test.py格式。 2、测试类以Test开头,并且不能带有 init 方法,可以包含一个或多个test_开头的函数 3、直接执行pytest.main():自动查找当前目录下,以test_开头的文件或者以_test结尾的py文件 :return: ''' def test_func(self): raise IOError("E") # raise 指定异常的类型 IOError def test_myfunc(self): # 使用pytest去断言异常的类型 ,异常一致则用例通过,否则用例败 with pytest.raises(SystemError): self.test_func() def test_logs(self): logs.info("logs打印日志") def test_print(self): print("print打印日志") @pytest.mark.skip # 无条件跳过用例 def test_case1(self): print("\n") assert 2 + 3 == 6, "结果比对不符合要求" @pytest.mark.flaky(reruns=5, reruns_delay=2) def test_case2(self): for i in range(9): # assert add(14, i) == 20, "不满足预期结果" try: assert add(14, i) == 20, "不满足预期结果" except: continue else: logs.debug(i) if __name__ == "__main__": ''' 1、自动查找当前目录下,以test_xxx开头或者以xxx_test结尾的py文件 2、main() 可传入执行参数及插件参数(通过[]进行分割,多个参数用逗号分割) 3、pytest.main(['目录名']) # 运行目录及子目录下所有用例 4、pytest.main(['test_xx.py‘]) # 运行指定模块所有用例 5、pytest.main(['test_xx.py::TestClass::test_def']) # 指定模块、类、用例(方法) 6、其他参数配置 -m=xxx: 运行打标签的用例 -reruns=xxx,失败重新运行 -q: 安静模式, 不输出环境信息 -v: 丰富信息模式, 输出更详细的用例执行信息 -s: 显示程序中的print/logging输出 --resultlog=./log.txt 生成log --junitxml=./log.xml 生成xml报告 ''' pytest.main(['-s'])testpy源码
执行结果:
拓展
单元测试
定义:是指检查代码的实现和逻辑,针对的是模块、函数、类等
核心概念:
test case(测试用例):一个testcase的实例就是一个测试用例。测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)
TestSuite(测试套件):多个测试用例集合在一起。
TestLoader(测试运行器):用来加载Testcase到TestSuite中。
test fixture(测试环境数据准备和数据清理或者测试脚手架):测试用例环境的搭建和销毁
TextTestRunner:用来执行测试用例,其中run(test)会执行TestSuite/TestCase中的run(result)方法。
测试目录结构
Log:日志记录和管理功能,针对不同的情况,设置不同的日志级别,方便定位问题;
Report:测试报告生成和管理以及即时通知,测试结果快速响应;
Source:配置文件、静态资源的管理,遵循高内聚低耦合原则;
Common:公共函数、方法以及通用操作的管理,遵循高内聚低耦合原则;
TestCase:测试用例管理功能,一个功能点对应一个或者多个case,尽可能的提高覆盖率;
TestData:测试数据管理功能,数据与脚本分离,降低维护成本,提高可移植性;
TestSuite:测试组件管理功能,针对不同场景不同需求,组装构建不同的测试框架,遵循框架的灵活性和扩展性;
Statistics:测试结果统计管理功能,每次执行测试的结果统计、分析、对比以及反馈,数据驱动,为软件优化和流程改进,提供参考;
Continuous:持续集成环境,即CI环境,包括测试文件提交、扫描编译、执行测试、生成报告及时通知等功能,持续集成是自动化测试的核心!