当前位置: 首页>编程语言>正文

pytest骨架 pytest框架设计

单元测试框架,大家较为熟悉的有 Unittest、Nose(unittest 的扩展)。Pytest 倒是名不见经传,但是自从用了之后,就爱不释手,就像它自己描述的一样:simple powerful testing with Python。简单好用的参数化以及多种运行模式,让测试脚本简单清晰,调试运行更加方便。

pytest骨架 pytest框架设计,pytest骨架 pytest框架设计_开发语言,第1张

一、参数化

比如我们在做自动化测试,当传入不同的参数时,期望返回的status code为200。如果用 Unittest做这块参数化比较复杂,而 pytest 会简单很多。在pytest中有pytest.mark.parametrize装饰器,轻松解决问题。我们就拿sogo的搜索作为例子。

用例说明:

步骤一、打开搜狗搜索(http://www.sogou.com/)

步骤二、输入tesla后点放大镜搜索

期望:返回正常

如果用接口来做的话,就相当于在query参数后面传tesla即可,验证状态码为200

如果用接口来做的话,就相当于在query参数后面传tesla即可,验证状态码为200

Import requests
Session = requests.session()
url = 'https://www.sogou.com/web?'
para = {'query': 'tesla'}
r = session.get(url, params=para, verify=False, allow_redirects=False)
assert r.status_code == 200

事实上,如果仅仅传一个搜索词就认为这个接口正常,那么很可能就出大篓子。所以我们可能需要传n个搜索词做验证。也就是说,para中的query后面的内容我们需要传多个不同的搜索词。比如说我们想搜索VR,BITCOIN等多个词的话,需要怎么做呢?

这个时候就是使用pytest中有pytest.mark.parametrize装饰器,如下代码第8行,通过在方法外面加一个装饰器就可以了。

Import pytest
Import requests
Session = requests.session()
url = https://www.sogou.com/web?'
search= ['tesla','VR','BITCOIN']
@pytest.mark.parametrize('test_input',search)
def test_status_code(test_input):
para = {'query':test_input}
r= session.get(url,params=para, verify=False, allow_redirects=False)
assert r.status_code == 200

此时有可能有同学提出疑问,对于多个参数我们用for循环也是可以做的,为何要用这个方法。原因是用pytest的参数化,传入的一个参数就是一个case,上面的例子我们传入了三个参数,那么形成的就是三个cases,哪个参数传入导致出错了,我们一目了然。那么要怎么做呢?我们在cmd里面运行脚本,假设脚本文件名为test_sogo_search.py,位置放在C盘下:

C:\>pytest test_sogo_search.py --html=./result/Report.html

在pytest的报告中你看到的是这样的

pytest骨架 pytest框架设计,pytest骨架 pytest框架设计_单元测试_02,第2张

通过这样的报告,就能很清晰的知道哪个搜索词的验证结果是正确,哪个搜索词验证的结果是错误的。比起用for循环来说,是要清晰很多了。另外还有运行的时长,也是能给到额外的信息。

二、运行模式

Pytest的多种运行模式,让测试和调试变得更加得心应手,下面介绍5种用的比较多的模式。在介绍之前需要提醒一句,运行pytest时会找test开头的文件以及以test开头的方法或者class,不然就会提示找不到可以运行的case了。

pytest骨架 pytest框架设计,pytest骨架 pytest框架设计_测试工具_03,第3张

1、运行后产生结果报告(htmlReport)

运行模式:

pytest test_case.py --html=./result/test_caseReport.html

效果:

pytest骨架 pytest框架设计,pytest骨架 pytest框架设计_开发语言_04,第4张

当运行出错时,在report里能直观的看到错误原因,上图中,预期希望的status_code是302,但是实际是 200,所以就报错了。看着报告定位问题就变的非常容易。且测试结果不用整理,直接提交报告即可。

2、运行指定的Case

代码块(test_case.py)

class TestClassOne(object):
def test_one(self):
x = "this"
assert 'h' in x
def test_two(self):
x = "hello"
assert hasattr(x, 'check')
class TestClassTwo(object):
def test_one(self):
x = "this"
assert 'h' in x
def test_two(self):
x = "hello"
assert hasattr(x, 'check')

运行模式:

模式 1:$ pytest test_case.py

模式 2:$ pytest test_case.py::TestClassTwo

模式 3:$ pytest test_case.py::TestClassTwo::test_one

说明:

模式 1:直接执行整个test_case文件中在所有case

模式 2:运行test_case文件中TestClassTwo这个class下的两个cases

模式 3:运行test_case文件中TestClassTwo这个class下的test_one

效果:

当我们写了较多的cases时,如果每次调式都要运行一遍,无疑是很浪费时间的,通过这样的简单方式我们就可以方便的指定任何一个case来运行了。

注意:

定义class时,需要以T开头,不然pytest是不会去运行该class的。

3、多进程运行cases

pip install pytest-xdist

运行模式:

$ pytest tes_case.py -n NUM

效果:

当case达到一定量的时候,运行时间会变的很长,如果想缩短脚本运行的时间,那就可以用它来做。NUM填写你想并发的进程数。速度嗖嗖嗖~不信你试试!

4、重试运行cases

pip install pytest-rerunfailures

运行模式:

$pytest tes_case.py --reruns NUM

效果:

在做接口测试时,有时候会遇到 503 或者短时的网络波动,导致case会运行失败,而其实并非是我们想要的结果,此时可以通过重新运行case的方式,再次执行。重试多少次,跟你填写的NUM有关。

5、显示print内容

运行模式:

$pytest tes_case.py -s

效果:

在运行测试脚本时,为了调试或者想打印一些内容,我们会在代码中加一些print内容,但是在运行pytest时,这些内容不会被显示出来。如果带上-s的运行模式,就可以看到print的内容会显示出来。

另外Pytest的多种运行模式是可以叠加执行的,比如说,你想同时运行 4个进程又想打印出print的内容,可以用$pytest test_case.py -s -n 4

三、总结

pytest的安装简单,学习资料丰富,框架切换成本低,有兴趣就一起来学习pytest吧!


https://www.xamrdz.com/lan/5em1938593.html

相关文章: