pytest 重试_【pytest】01 基础用法

python的单元测试主要采用两种测试框架,unittest是python内置的标准类库,pytest是第三方库,它兼容unittest。本章主要讲解Pytest框架的基础用法。

unittest

unittest提供了test cases、test suites、test fixtures、test runner相关的组件

编写规范

  • 测试模块代码必须先import unittest

  • 测试类必须继承unittest.TestCase

  • 测试方法必须以'test_'开头

  • 模块名称和类名没有特殊要求

注:在python中一个.py文件就是一个模块

框架结构

import unittestclass FrameworkUnittest(unittest.TestCase):    @classmethod    def setUpClass(cls) -> None:        print("setUpClass")    def setUp(self) -> None:        print("setUp")    def test_method_1(self):        print("test_method_1")    def test_method_2(self):        print("test_method_2")    def tearDown(self) -> None:        print("tearDown")    @classmethod    def tearDownClass(cls) -> None:        print("tearDownClass")

输出结果:

setUpClasssetUptest_method_1tearDownsetUptest_method_2tearDowntearDownClass
  • setupClass\teardownClass在类开始\结束运行一次

  • setUp\teardown在每个方法的开始\结束运行一次

测试套件

多个测试用例的集合就是测试套件,unittest通过测试套件管理多个测试用例 unittest.TestSuite(...)

加载测试用例的方法:

  • addTest 方法

  • TestLoader().loadTestsFromTestCase(类名) 按类加载测试用例

  • defaultTestLoader.discover(路径,匹配规则) 按路径和匹配规则加载测试用例,可以一次调用多个脚本

测试用例的执行

  • 在__main__方法中调用 unittest.main()

  • 加入测试套件中使用

    suite=unittest.TestSuite()suite.addTest(TestMethod("test_01"))suite.addTest(TestMethod("test_02"))unittest.TextTestRunner().run(suite)

pytest

测试用例的识别和运行

  • 测试文件:test_*.py    *_test.py    注意:test.py文件无法被识别

  • 测试用例识别:

    • Test*类包含的所有test_*的方法(测试类不能带有__init__方法)

    • 不在类中的test_*的方法

    • 兼容unittest的测试用例

终端执行

pytest [options] [file_or_dir....]
  • pytest/py.test 不输入任何参数的时候,pytest在当前目录下搜索所有符合要求的文件中的测试用例并执行

  • pytest options 参数列表

    • --collect-only 只收集测试用例不执行

    • -k EXPRESSION 只执行匹配表达式的测试用例,该表达式是python的可执行表达式,例如"类名 and not 方法名",跳过某个类下的方法不执行

    • -m MARKEXPR 只执行标签匹配表达式的测试用例,例如"mark1 and not mark2" ,只执行带mark1标签的测试用例

    • --markers 展示所有的标签

    • -x 一旦执行到测试用例报错就停止执行

    • --maxfail=[num] 当运行错误达到num时就停止运行

    • -v / --verbose 打印详细运行日志信息

    • -s 控制台输出打印结果,即print信息

  • pytest [options] file_or_dir

    • 文件名.py 运行单独一个模块

    • 文件名.py::类名[::方法名] 运行模块中某个类[或类中某个方法]

这里只列举了部分参数,可以在命令行中通过pytest -h命令查询更多的参数用法

执行顺序

默认情况下,pytest是根据文件中的编写的测试用例从上到下依次执行,可以通过插件pytest-ordering自定义执行顺序,还可以在conftest.py文件中重写pytest的pytest_collection_modifyitems方法,该方法用来收集所有的测试用例,可以在这个方法中对测试用例的顺序进行调整

框架结构

  • 模块级 (setup_module/teardown_module)模块的开始和结束运行一次,优先级最高

  • 函数级 (setup_function/teardown_function)函数(不在类中的方法)的开始和结束运行一次

  • 类级 (setup_class/teardown_class)在类的开始和结束运行一次

  • 方法级 在方法(在类中的方法)的开始和结束运行一次

    • setup_method/teardown_method

    • setup/teardown

配置文件

默认情况下,pytest没有配置文件,采用pytest的默认配置,如果想要修改pytest的配置,可以在项目目录下新建一个pytest.ini/tox.ini/setup.cfg文件,可以实现部分功能的自定义,但是在配置文件的第一行必须是[pytest]

通过在命令行中执行命令pytest -h可以看到pytest提供哪些配置项,这里只对部分参数进行解释:

markers (linelist)

用于指定自定义标签,如果不指定运行时对于自定义标签会报错。可以多行指定多个标签

testpaths

当在命令行执行时没有提供路径时,默认的搜索路径

在命令行中输入下面的命令:

D:\projects\pythonProjects\web-ui-automator-netease>pytest --collect-only

执行结果:

...collected 31 items                                                                                                                                                                         ...

从结果中可以看出,默认情况下,pytest在当前目录下搜索出所有符合要求的测试用例,除了当前目录下以test_*开头的文件,还包括huyp和testcese目录下以test_*开头的文件,如果将pytest的默认路径改为项目中的testcase目录下,这样可以每次执行用例时,就会执行testcase目录下的文件。

[pytest]testpaths = testcase

再次执行命令,结果如下:

...collected 29 items                                                                                                                                                                     ...

从结果中可以看出,不提供路径时,pytest在testcase目录下收集到了29个测试用例。

python_files

默认情况下,pytest只能识别以test_*.py或者*_test.py文件,如果想自定义文件名可以指定python_files参数,例如只想识别以search开头的文件,配置如下:

[pytest]testpaths = testcasepython_files = search_*

执行命令pytest --collect-only,结果如下:

...collected 16 items                                                                                                                                                                           ...

python_classes

默认情况下,pytest只能识别以Test开头的类,如果想自定义类名可以指定python_classes参数,例如只想识别以Search开头的类,配置如下:

[pytest]testpaths = testcasepython_files = search_*python_classes = Search*

执行命令pytest --collect-only,结果如下:

...collected 16 items                                                                                                                                                                           ...

python_functions

默认情况下,pytest只能识别以test_开头的方法,如果想自定义方法名可以指定python_functions参数,例如只想识别以search开头的方法,配置如下:

[pytest]testpaths = testcasepython_files = search_*python_classes = Search*python_functions = search_*

执行命令pytest --collect-only,结果如下:

...collected 4 items                                                                                                                                                                      ...

addopts

默认情况下,如果我们想收集用例,需要跟上面执行的命令一样,添加--collect-only参数,如果我们希望默认情况下,输入pytest就能只进行收集的功能可以将改参数加入到配置中,如下:

[pytest]testpaths = testcaseaddopts = --collect-only

在命令行中只输入pytest,执行结果如下

...collected 29 items                                                                                                                                                                           ...=================== 29 tests collected in 0.25s ==================

从结果中可以看出,只进行了收集,并没有执行

pytest 插件

  • pytest-sugar 美化输出结果

  • pytest-rerunfailures 错误重试

  • pytest-xdist 多任务

  • pytest-assume 软断言

  • pytest-html html的测试结果报告

  • pytest-ordering 自定义测试用例执行顺序

场景:美化用例执行输出结果

  • 安装插件

    pip install pytest-sugar

  • 执行用例

    pytest -v

    执行结果如下图,修改原有的样式,增加了进度条,个人认为并不好看,不推荐

    da63f2185b682cd74ad3f547b601cdf9.png

场景:用例失败后,间隔一段时间后,重新运行

  • 安装插件  

    pip install pytest-rerunfailures

  • 失败后重新运行3次  

    pytest -v test_index.py --reruns 3

  • 失败后延迟1s秒后再重新运行  

    pytest -v test_index.py --reruns 3 --reruns-delay 1

场景:并行执行多个用例

前提:用例之间独立,没有先后顺序,可以独立执行

  • 安装插件

    pip install pytest-xdist

  • 执行测试用例 -n 指定并行数量,也可直接这是为auto,由pytest根据CPU数量自动计算

    pip -v -s testcase/test_play.py -n 3

    执行结果:

    12ad7c1da9379762255628ed0c7984ef.png

    从结果中可以看出,gw0 gw1和gw3启动了3个chrome浏览器并行执行了6个测试用例

场景:方法中有多个断言,任意断言失败,后面的断言继续执行

  • 安装插件

    pip install pytest-assume

  • 修改assert断言

    # 断言# assert self.driver.find_element_by_xpath('//*[@]').text == categories_label + "_no"# assert self.driver.title == categories_label + "歌单 - 歌单 - 网易云音乐_no"pytest.assume(self.driver.find_element_by_xpath('//*[@]').text == categories_label + "_no")pytest.assume(self.driver.title == categories_label + "歌单 - 歌单 - 网易云音乐_no")

    执行结果:

    pytest_assume.plugin.FailedAssumption: 2 Failed Assumptions:testcase\test_index.py:55: AssumptionFailure>>      pytest.assume(self.driver.find_element_by_xpath('//*[@]').text == categories_label + "_no")AssertionError: assert Falsetestcase\test_index.py:56: AssumptionFailure>>      pytest.assume(self.driver.title == categories_label + "歌单 - 歌单 - 网易云音乐_no")AssertionError: assert False

    结果中可以看到,两个断言都进行了判断,如果采用pytest默认的assert断言,一个断言判断失败后,程序就会结束,不会去判断下面的断言是否正确

场景:生成html测试报告

  • 安装插件

    pip install pytest-html

  • 执行测试用例,生成测试报告 --html指定生成的html报告的存放位置,默认生成的报告的css样式文档是独立存放的,添加--self-contained-html参数可以将css样式添加到html文件中

    pytest -v --html=report.html --self-contained-html

    报告的样式如下图,个人认为样式很不好看,不推荐。推荐整合allure展示测试报告。

cc6ddfc66e070e851bfbd8e1b19fbc29.png

自定义测试用例执行顺序

  • 安装插件

    pip install pytest-ordering

  • 在测试用例方法上新增标签@pytest.mark.run(order=n) n越小越先执行

    @pytest.mark.run(order=1)@allure.severity(allure.severity_level.MINOR)@allure.story("搜索页类别搜索")@pytest.mark.parametrize(("search_type", "search_name", "data_type"),                         yaml.safe_load(open("testcase/search_data.yml", mode='r', encoding='utf-8')))def test_search_3(self, search_type, search_name, data_type):    self.driver.get("https://music.163.com/#/search")    self.driver.switch_to.frame(self.driver.find_element_by_name("contentFrame"))    search_element = self.driver.find_element_by_id('m-search-input')    search_element.clear()    search_element.send_keys(search_name)    self.driver.find_element_by_xpath('//*[@]').click()    self.driver.find_element_by_xpath(f'//*[@]').click()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值