前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Pytest的基本应用(一)

Pytest的基本应用(一)

作者头像
无涯WuYa
发布2019-09-04 14:33:14
2.3K0
发布2019-09-04 14:33:14
举报

在Python的编程语言中,单元测试框架主要是pytest,unittest,和nose,其中应用最广泛的是unittest和pytest测试框架,unittest测试框架是内置的模块,安装完Python的解释器后,就可以直接导入使用,但是使用它的时候必须是继承TestCase类,才可以调用里面的方法,但是缺陷也是很明显的,它只能应用于面向对象的编程方式,无法应用于函数式的编程方式,Python语言它的优势的是可以是面向对象的编程方式,也可以是函数式的编程方式。pytest就显得自由,它把每一个以test_开头或者是_test结尾的都看成是一个测试对象,同时它的断言是Python的原生断言assert,这样使用起来更加的自由,只要编写的不管是模块还是类,符合它的要求,都是可以执行的。但是前提是需要安装pytest,它是属于第三方的库,安装的命令为:

pip install pytest

在这里先写一个函数的测试代码,来说明pytest的应用,创建f.py的模块,在里面编写以test开头的测试代码,然后在该目录下执行pytest,发现测试代码并没有执行,见如下截图:

为什么测试代码没有执行了?这是因为在pytest中,它会首先寻找以test_开头或者以_test结尾的测试模块,然后执行模块里面以test_开头或者是以_test结尾的测试代码,这里依据这个要去,编写测试模块,如下:

再次执行pytest,就会看到模块里面的测试代码都已执行,见如下的截图信息:

当然也查看详细的信息,使用到的命令为:pytest -v 就会显示出详细的执行信息,如下图所示:

在详细的信息中,会显示出执行了那个模块中的那个具体的测试用例,再完善下模块中的测试用例,执行多少个,在详细的信息中它都会显示出来,见完善后执行的截图信息,如下图所示:

在一个项目文件中,或者说是一个测试的包下面,会有很多的测试模块文件,但是并不是所有的测试模块文件需要执行,只是想执行某一个模块文件,那么就只需要在执行的时候指定这个文件就可以了,执行的命令为:pytest -v test_xunit_002.py,见执行后的结果截图信息:

见如上的截图信息,就只显示了test_xunit_002.py模块的测试代码,并没有执行另外一个模块的测试用例。

下面继续看Pytest中对测试用例执行结果的显示,如果是正确的显示passwd,也会使用.来表示,如果是错误的,也就是执行失败的,使用F来表示,也就是FAILED,完善test_xunit_0002.py模块的代码,见源码:

代码语言:javascript
复制
#!/usr/bin/env python
# -*-coding:utf-8 -*-


def test_001():
    assert  1==1


def test_002():
    assert  2==3 

见执行后正确的和错误的信息的表示,见如下的截图信息:

在执行结果中会显示出错误的详细信息,以及成功的个数和失败的个数。

在pytest框架中,如果没有指定目录,它默认是会搜索一个项目下所有可执行的测试模块以及测试模块里面的测试用例来进行的,并不在乎测试用例是在哪个package那个模块的,这样的一个过程成为“测试搜索”,只要符合它的规则的它都是会被执行的。在这里,增加几个包,在包里面增加几个测试模块,见目录结构的设计:

再次使用pytest -v来进行执行,来看“测试搜索”的过程,见执行的截图,如下图所示 :

依据如上的结果信息,pytest测试搜索的规则为:

  1. 测试文件最好是test开头或者是test为结尾
  2. 测试函数或者测试类方法应该当是test开头或者是test为结尾
  3. 测试类应当命名为Test<SomeThing>

下来依据案例继续看执行单个测试用例的文件,主要分为这么几个场景,第一个场景是执行某一个模块下的某一个测试用例,第二个场景是执行某个模块下某一分类的测试用例,先来看第一个场景,指定模块下具体的测试用例,见执行的命令:

如果某一个测试用例名称是唯一的,或者说是某一些分类,那么就可以使用命令行的-k,以及--collect-ony,-k允许使用表达式指定希望运行的测试用例,或者多个前缀或者是后缀的测试用例名称相同,--collect-only主要的应用于筛选,见模块的源码:

代码语言:javascript
复制
#!/usr/bin/env python
# -*-coding:utf-8 -*-
import  pytest

def test_001():
    pass

def test_login_001():
    pass

def test_login_002():
    pass

def test_logout_001():
    pass

def test_logout_002():
    pass

当然也可以显示出执行的详细的信息:

-m是可以很快速到找到测试类别的分组,比如登录模块是一部分的测试用例,退出是一部分的测试用例,这里我们还是以开放平台为案例,也就是说在一个测试模块中 ,有很多的测试用例,但是只是想执行openapi的测试用例,见案例代码:

代码语言:javascript
复制
#!/usr/bin/env python
# -*-coding:utf-8 -*-


import  pytest

def test_001():
    pass

def test_login_001():
    pass

def test_login_002():
    pass

def test_logout_001():
    pass

def test_logout_002():
    pass

@pytest.mark.openapi
def test_open_api_001():
    pass

@pytest.mark.openapi
def test_open_api_002():
    pass

这里实现只是单纯的执行openapi的测试用例,其它的测试模块就不再执行了,执行的命令是:pytest -m openapi,见执行后的结果截图:

见执行的详细信息:

在实际的测试场景中,一般性的我们希望不管测试用例执行失败也好成功也好,都希望测试用例能够正常的执行,但是也有一种场景是执行的时候遇到测试用例执行失败,就立刻停止,这里会使用到的命令是-x,见案例代码:

代码语言:javascript
复制
#!/usr/bin/env python
# -*-coding:utf-8 -*-


def test_001():
    assert 1==1

def test_002():
    assert 1+1==1

def test_003():
    assert 2+2==4

我们希望测试用例执行失败,就立刻停止,执行的命令为:pytest -x

执行到第二个测试用例,由于断言失败,所以测试用例再没有继续执行。这是符合我们的预期结果的。当然也可以指定最大失败的次数,它的命令为:--maxfail=参数,参数也就是指的是最大的失败次数。继续执行,执行的命令为:pytest --mailfail=参数

上面指的是最大失败的次数是0,所以也就等于不管是否失败,都执行所有的测试用例。这个需求相对来说使用的还是比较少,一般的来说我们都还是希望所有的测试用例执行,到最后再说具体结果的事,失败的当然再具体定位和分析,然后得出比较客观的结论报告。--tb=no是关闭错误信息,--tb=short是输出assert错误的信息,--tb=line是一行输出所有的所有,具体依据如下的截图信息来看这三个的区别和它的应用场景,第一个场景是有错误,但是不显示错误的信息,执行的命令是:pytest --tb=no

第二个场景是有错误就只输出assert的这一行的信息,执行的命令为:pytest --tb=short

第三场景是显示错误信息,并且显示在一行的内容,执行的命令为:pytest --tb=line,如下图所示:

--lf命令值的是执行测试用例失败后,希望能够定位到该测试用例并且重新执行,它的好处是能够很快速的找到失败的测试用例见案例的源码:

代码语言:javascript
复制
#!/usr/bin/env python
# -*-coding:utf-8 -*-


def test_001():
    assert 1==1

def test_002():
    assert 1+1==1

def test_003():
    assert 2+2==4

中间的测试用例断言它是存在问题,但是我们希望能够很快速的定位到,执行的命令为:pytest --lf,见输出结果截图:

显示出第二个测试用例失败,很快速的定位到了,并且显示出了断言的失败信息。

--ff是执行完剩余的测试用例,是一个很奇怪的解释,是不是意味着执行终止了,然后由它负责执行完剩余的测试用例了,是否和-x命令冲突了,执行的命令为:pytest --ff

-v就是很简单了,打印出很详细的信息,-q与-v是相反的,就是打印出简单的信息,见执行的命令:

如上可以看到打印的信息确实很简单的,但是有个好处是失败的测试用例它还是显示出了很详细的信息的。这点我觉得特别的好。

--duration是统计出那些测试用例执行速度慢,这点在接口测试特别的好用,可以看到那个接口请求响应慢,默认是0,耗时从长到短依次排序显示,见案例的源码,同样的网络环境测试那个网站访问速度快。

代码语言:javascript
复制
#!/usr/bin/env python
# -*-coding:utf-8 -*-

import  requests


def test_get_page_baidu(url='http://www.baidu.com/'):
    r=requests.get(url=url)
    assert r.status_code==200

def test_get_page_taobao(url='http://www.taobao.com/'):
    r=requests.get(url=url)
    assert r.status_code==200

def test_get_page_qq(url='http://www.qq.com/'):
    r=requests.get(url=url)
    assert r.status_code==200

执行的命令为:pytest --duration=0,见执行后的命令信息:

真的是没有对比就没有伤害,有了对比伤害也就出来了,百度的耗时是最长是,淘宝是耗时是最短的。结果是那么的让人不可思议的。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python自动化测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档