pytest 参数集_pytest框架从入门到精通

unittest是python自带的单元测试框架,它封装好了一些校验返回的结果方法和一些用例执行前的初始化操作,使得单元测试易于开展,因为它的易用性,很多同学也拿它来做功能测试和接口测试,只需简单开发一些功能(报告,初始化webdriver,或者http请求方法)便可实现。

但自动化测试中我们常常需要根据不同需求挑选部分测试用例运行,并且我们希望用例克服环境不稳定的局限,即运行失败后自动重新运行一次,如果成功就认为是环境问题导致第一次失败,还有我们经常希望测试用例可以并发执行等等,这些unittest都做不到或者需要大量二次开发才能做到,那么有没有更加强大的框架可以替代unittests呢?

pytest是python里的一个强大框架,它可以用来做单元测试,你也可以用来做功能,接口自动化测试。而且它比unittest支持的功能更多更全面。但是pytest在Getstarted里给出的实例却很简单,很多同学错以为它只是跟unittest一样是个单元测试框架罢了,如果你查询中文互联网,你也只能找到寥寥数篇大致一样的用法,可以说pytest的精髓使用,没有被大家挖掘出来,如此强大的框架不应该被埋没,今天我就带领大家深入pytest使用,共同领略pytest的强大。

1.pytst安装

pytest不属于python的标准库,所以需要安装才能使用, 安装方式如下:

1pip install -U pytest

如果你已经安装有pytest,想查看它的版本号:

1pytest --version

2.你的第一个pytest测试

12345678#直接使用官网用例# content of TesterTalk.pydef func(x):return x + 1def test_answer():assert func(3) == 5#在你的terminial里输入 python -m pytest TesterTalk.py,你将会看到如下信息:

非常简单吧, 如果想运行多个用例该如何做呢?

1234567891011# content of TesterTalk.pyclass TestClass(object):def test_one(self):x = "this"assert 'h' in xdef test_two(self):x = "hello"assert hasattr(x, 'check')#把要测试的case以test_开头就好了。#terminal里输入 pytest TesterTalk.py, 执行结果一个成功一个失败。

注意:

(1).如果你想用pytest寻找整个文件夹下的测试用例,那么文件须以test_开头或者以 test结尾。

(2).测试类以Test开头,并且不能带有 init 方法。

_(3).测试函数以test_开头。

(4).另外,pytest不支持也不打算支持中文路径,如果项目路径中有中文会报错。

好了,pytest的getStarted就结束了, 看了上面的应用方式的确没觉得它哪里强大。 别着急,我们再来想一想,如果你有个测试框架,你希望如何用这个框架做测试?

3.灵活的指定测试用例运行集。

在unittest框架里,你只能通过suite.addTest(),或者defaultTestLoader.Discover()两种方法在查找测试用例,对于你不需要的测试用例,只能用@unittest.skip()

来忽略,但做不到不改动代码变更测试用例集,pytest很好的实现了这一点,它支持如下查找:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475# 1. 运行某个package下的所有用例。pytest test_4. #会运行test_4下面所有的test_*.py 或者*_test.py文件里所有的Test开头的类(这个类不允许有__init__方法)下面的以test_开头的方法。#2. 运行某个文件(module)下的所有用例。pytest testtalk.py #会查找这个文件下所有的Test开头的类(这个类不允许有__init__方法)下面的以test_开头的方法。#3. 运行包含(或不包含)某个关键词的测试类/方法。class TestClass(object):def test_one(self):x = "this"assert 'h' in xdef test_two(self):x = "hello"assert hasattr(x, 'check')#在terminal里输入 pytst -k "TestClass and not two" #会运行 test_one这个function但不会与性test_two.#4.根据node ids运行测试用例。 pytest给每个test assign里一个id。 可以用::隔开。 举例来说:# TesterTalk.pyclass TestClass(object):def test_one(self):x = "this"assert 'h' in xdef test_two(self):x = "hello"assert hasattr(x, 'check')#在terminal里输入 pytest TesterTalk.py::TestClass 会执行TestClass下的所有用例#在terminal里输入 pytest TesterTalk.py::TestClass::test_two, 仅会执行test_two.#5.根据标签(mark)运行,比如有个测试类,你想在regression时候才运行,另外一个测试类你想在releasae的时候才运行。#TesterTalk.py@pytest.mark.releaseclass TestClass1(object):def test_one(self):x = "this"assert 'h' in xdef test_two(self):x = "hello"assert hasattr(x, 'check')@pytest.mark.regressionclass TestClass2(object):def test_one(self):x = "this"assert 'h' in xdef test_two(self):x = "hello"assert hasattr(x, 'check')#你只需在terminal里指定标签就可以了。pytest TesterTalk.py -m releasepytest TesterTalk.py -m regression是不是比unittest方便太多了,所有的测试类,测试方法,你只需要用@pytest.mark.XXX装饰就好了。然后一次更改,多次挑选运行!这样就完了吗? NO, No,No, 你如果想几个标签一起运行怎么办?或者你不想某个标签运行怎么办?Very simple:pytest TesterTalk.py -m “release or regression" #有release或者regression标签的都会运行。pytest TesterTalk.py -m “not regression” # regression标签的不会运行。当然了,unittest里支持的skip方法,pytest也支持,具体用法如下:#TesterTalk.py@pytest.mark.skip('skip')class TestClass1(object):def test_one(self):x = "this"assert 'h' in xdef test_two(self):x = "hello"assert hasattr(x, 'check')#skip装饰器可以放在类前面skip掉整个测试类,也可以防止function前面只skip掉这个function。#对应的还有skipif, 请自己看文档了解。

难道就仅限于此吗? 其实pytest帮我们实现了更多的高级功能,比如:

4.并发运行测试用例集

关注公众号TesterTalk,跟我一起关注测试技术

首先,你得安装个插件:

1pip install pytest-parallel #pytest-parallel比pytst-xdist要更好。

其次,要注意区这个插件仅仅支持python3.6版本及以上,而且如果你想多进程并发,必须跑在Unix或者Mac机器上,windows环境仅仅支持多线程运行。

运行上需要指定参数:

–workers (optional) X。 多进程运行, X是进程数。 默认值1。
–tests-per-worker (optional) X. 多线程运行, X是每个worker运行的最大并发线程数。 默认值1。

举例来说:

1234567891011121314151617181920212223242526# TesterTalk.pyimport pytest@pytest.mark.releaseclass TestClass1(object):def test_one(self):x = "this"assert 'h' in xdef test_two(self):x = "hello"assert hasattr(x, 'check')@pytest.mark.regressionclass TestClass2(object):def test_one(self):x = "this"assert 'h' in xdef test_two(self):x = "hello"assert hasattr(x, 'check')#terminal里输入 pytest TesterTalk.py --workers 2 #指定一个进程并发#terminal里输入 pytest TesterTalk.py --workers 2 --test-per-worker 3 #指定2个进程并发,每个进程最多运行3个线程。

5.测试报告优化

12345678#允许HTML格式报告#首先还是要安装:pip install pytest-htmlUsage:使用很简单带参数 --html=report.html就好。仍然拿我们刚才举例:pytest TesterTalk.py --html=./report.html

生成的结果如下:

有时候,我们需要克服环境问题,让失败的用例rerun,有没有办法呢?

123456789#rerun失败的case#首先还是要安装:pip install pytest-rerunfailuresUsage:--reruns 5 #rerun 5次----reruns 5 --reruns-delay 1 # rerun5次, 但是每次rerun前等待1秒。仍以我们刚才的为例:#terminal里输入 pytest TesterTalk.py --reruns 1 --html=./report.html

生成的结果如下:

可以看到,rerun聚合在了报告里。

我们自动化一般用到持续集成,Jenkins里需要junit XML格式的报告,pytest有没有办法直接生成?

123456无需安装,直接使用:pytest --junitxml=path例如:pytest TesterTalk.py --reruns 1 --html=./report.html --junitxml=./xml_format_report.xml会在本地目录生成xml_format_report.xml

这就结束了吗?还远呢?数据参数化你了解下?

6.数据参数化

pytest有几种数据参数化方式:

pytest.fixture(). 不带参数

123456789101112131415#1.fixture()不带参数:import pytest@pytest.fixture()def initial_browser():from selenium import webdriverreturn webdriver.Chrome()class TestBaidu():def test_open_baidu(self, initial_browser):initial_browser.get("http://www.baidu.com")#在terminal里输入pytest testing/testertalk.py --html=./report.html, 你会看到百度浏览器打开了。说明函数间可以传递值,我们也可以利用这个来做unittest里setup()的事情。

pytest.fixture(), 带parms参数:

params with @pytest.fixture, a list of values for each of which the fixture function will execute and can access a value via request.param.

1234567891011121314#利用fixtures的paramsimport pytest@pytest.fixture(params=[{'username':'TesterTalk',"password":1}, {'username':'Test',"password":1}])def account_provider(request): #request是固定的。return request.param #request.parm也是固定的。def test_login(account_provider):#some operationsprint(account_provider)假设你需要用多个用户名密码测试登录,只需要用fixture()加params就好。#在terminal里输入pytest testing/testertalk.py --html=./report.html

report显示下图,可以看到test_login被执行了2遍,每次执行带入的数据不同:

除了直接用pytest.fixture, 还可以这么用:

pytest.mark.usefixtures()

12345678910111213import pytest@pytest.fixture(params=[{'username':'TesterTalk',"password":1}, {'username':'Test',"password":1}])def account_provider(request):return request.param@pytest.mark.usefixtures("account_provider")def test_login(account_provider):#some operationsprint(account_provider)#在terminal里输入pytest testing/testertalk.py --html=./report.html,report跟上面的演示一样。注意:使用fixture标记函数后,函数将默认接入一个request参数,它将包含使用该fixture函数的信息,这使我们可以更加灵活的根据不同的函数来决定创建不同的对象以及释放函数。 举例来说userfixtures可以用作setup()和teardown()

pytest固然强大,这就结束了吗?还有什么高阶的功能吗?必须的。

7.pytest.mark.parametrize实现数据驱动

1234567891011#直接在测试方法前直到数据源import pytest@pytest.mark.parametrize("account_provider

Original: https://blog.csdn.net/weixin_36250086/article/details/113452389
Author: 鱼鹰谈单片机
Title: pytest 参数集_pytest框架从入门到精通

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/775218/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球