zoukankan      html  css  js  c++  java
  • Python之pytest 基础

    pytest是一个非常成熟的全功能的Python测试框架,主要特点有以下几点:1、简单灵活,容易上手;2、支持参数化;3、能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests);4、pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如pytest-selenium(集成selenium)、pytest-html(完美html测试报告生成)、pytest-rerunfailures(失败case重复执行)、pytest-xdist(多CPU分发)等;5、测试用例的skip和xfail处理;6、可以很好的和jenkins集成;(二)安装

      pip install -U pytest 

      pip install -U pytest-html

      pip install -U pytest-rerunfailures

    此外还有很多很好的第三方插件,请到http://plugincompat.herokuapp.com/ 和 https://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search 查找

    (三)例子

    这里列几个pytest-document中的例子

    1、默认执行当前目录下的所有以test_为前缀(test_*.py)或以_test为后缀(*_test.py)的文件中以test_为前缀的函数

    复制代码
    import pytest
    
    # content of test_sample.py
    def func(x):
        return x + 1
    def test_answer():
        assert func(3) == 5
    复制代码

    运行 py.test  或 指定特定文件 py.test -q test_sample.py

    2、使用类来组成多个用例的

    复制代码
    import pytest
    
    # content of test_class.py
    class TestClass:
        def test_one(self):
    
            x = "this"
        assert 'h' in x
        def test_two(self):
            x = "hello"
            assert hasattr(x, 'check')
    复制代码

    3、在python中调用pytest: python test_class.py

    复制代码
    import pytest
    
    # content of test_class.py
    class TestClass:
        def test_one(self):
            print 'one'
            x = "this"
            assert 'h' in x
        def test_two(self):
            print 'two'
            x = "hello"
            assert hasattr(x, 'check')
    if __name__ == '__main__':
        pytest.main("-q --html=a.html")
    复制代码

    4、来个支持参数化的例子,参数化使用pytest.mark.parametrize的参数,第一个为变量的元组,第二个是变量赋值的元组列表,具体下面的章节会仔细介绍

    # content of test_time.py
    import pytest
    from datetime import datetime, timedelta
    
    testdata = [
    (datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
    (datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
    ]
    
    @pytest.mark.parametrize("a,b,expected", testdata)
    def test_timedistance_v0(a, b, expected):
        diff = a - b
        assert diff == expected
        
    @pytest.mark.parametrize("a,b,expected", testdata, ids=["forward", "backward"])
    def test_timedistance_v1(a, b, expected):
    
        diff = a - b
        assert diff == expected
        
    def idfn(val):
        if isinstance(val, (datetime,)):
        # note this wouldn't show any hours/minutes/seconds
            return val.strftime('%Y%m%d')
    @pytest.mark.parametrize("a,b,expected", testdata, ids=idfn)
    def test_timedistance_v2(a, b, expected):
        diff = a - b
        assert diff == expected

    使用和调用

    • python -m pytest调用:
      • python -m pytest [...] 效果和py.test [...] 一样
    • 获取版本,选项名,环境变量
      • py.test --version 看版本
      • py.test --fixtures 查看内置参数
      • py.test -h | --help 命令行和配置文件帮助
    • 失败后停止
      • 首次失败后停止执行:py.test -x
      • py.test --maxfail=2 两次失败之后停止执行
    • 执行选择用例
      • py.test test_mod.py,执行模块中的用例
      • py.test somepath,执行路径中用例
      • py.test -k stringexpr,执行字符串表达式中的用例,比如"MyClass?and not method",选择TestMyClass.test_something,排除了TestMyClass.test_method_simple。
      • py.test --pyargs pkg,导入pkg,使用其文件系统位置来查找和执行用例。执行pypkg目录下的所有用例。
    • 调试输出:
      • py.test --showlocals 在traceback中显示本地变量
      • py.test --showlocals 在traceback中显示本地变量(快捷方式)
      • py.test --tb=long 默认的traceback信息格式化形式
      • py.test --tb=native 标准库格式化形式
      • py.test --tb=short 更短的格式
      • py.test --tb=line 每个错误一行
    • 失败时调用PDB (Python Debugger):

    Python带有一个内置的Python调试器称为PDB。pytest可以在命令行选项指定调用:

    py.test --pdb

    这将每次失败时调用Python调试器。通常,您可能只希望这样做的第一个失败的测试,以 了解某些故障情况: py.test-X - PDB#下降到PDB上的第一次失败,然后结束测试阶段 py.test - PDB - maxfail=3#下降到PDB前三失败



    几个pytest documentation中的例子:

    
    

    例子1:

    
    
    import pytest
    
    # content of test_sample.py
    def func(x):
        return x + 1
    def test_answer():
        assert func(3) == 5
    
    
    

    命令行切换到文件所谓目录,执行测试(也可以直接在IDE中运行):


    image.png

    这个测试返回一个失败报告,因为func(3)不返回5。

    
    

    例子2:
    当需要编写多个测试样例的时候,我们可以将其放到一个测试类当中,如:

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

    运行以上例子:


    image.png

    从测试结果中可以看到,该测试共执行了两个测试样例,一个失败一个成功。同样,我们也看到失败样例的详细信息,和执行过程中的中间结果。-q即-quiet,作用是减少冗长,具体就是不再展示pytest的版本信息。

    
    

    如何编写pytest测试样例

    
    

    通过上面2个实例,我们发现编写pytest测试样例非常简单,只需要按照下面的规则:

    
    
    • 测试文件以test_开头(以_test结尾也可以)
    • 测试类以Test开头,并且不能带有 init 方法
    • 测试函数以test_开头
    • 断言使用基本的assert即可
    
    

    运行模式

    
    

       Pytest的多种运行模式,让测试和调试变得更加得心应手,下面介绍5种常用的模式。在介绍之前需要提醒一句,运行pytest时会找当前目录及其子目录中的所有test_*.py 或 *_test.py格式的文件以及以test开头的方法或者class,不然就会提示找不到可以运行的case了。

    
    

    1.运行后生成测试报告(htmlReport)

    
    

    安装pytest-html:

    
    
    pip install -U pytest-html
    
    
    

    运行模式:

    
    
    pytest --html=report.html
    
    
    

    报告效果:


    image.png

    在以上报告中可以清晰的看到测试结果和错误原因,定位问题很容易。

    
    

    2.运行指定的case

    
    

      当我们写了较多的cases时,如果每次都要全部运行一遍,无疑是很浪费时间的,通过指定case来运行就很方便了。

    
    

    例子代码:

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

    运行模式:

    
    

    模式1:直接运行test_se.py文件中的所有cases:

    
    
    pytest test_se.py
    
    
    

    模式2:运行test_se.py文件中的TestClassOne这个class下的两个cases:

    
    
    pytest test_se.py::TestClassOne
    
    
    

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

    
    
    pytest test_se.py::TestClassTwo::test_one
    
    
    

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

    
    

    3.多进程运行cases

    
    

      当cases量很多时,运行时间也会变的很长,如果想缩短脚本运行的时长,就可以用多进程来运行。

    
    

    安装pytest-xdist:

    
    
    pip install -U pytest-xdist
    
    
    

    运行模式:

    
    
    pytest test_se.py -n NUM
    
    
    

    其中NUM填写并发的进程数。

    
    

    4.重试运行cases

    
    

      在做接口测试时,有事会遇到503或短时的网络波动,导致case运行失败,而这并非是我们期望的结果,此时可以就可以通过重试运行cases的方式来解决。

    
    

    安装pytest-rerunfailures:

    
    
    pip install -U pytest-rerunfailures
    
    
    

    运行模式:

    
    
    pytest test_se.py --reruns NUM
    
    
    

    NUM填写重试的次数。

    
    

    5.显示print内容

    
    

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

    
    

    运行模式:

    
    
    pytest test_se.py -s
    
    
    

      另外,pytest的多种运行模式是可以叠加执行的,比如说,你想同时运行4个进程,又想打印出print的内容。可以用:

    
    
    pytest test_se.py -s -n 4
    
    
    

    学习网站:
    pytest documentation
    好用的Pytest单元测试框架(《51测试天地》四十九(下)- 44)
    Pytest学习笔记
    pytest单元测试框架

     

    兼容unittest与nose

    
    

    如果之前你的单测全部是基于unittest或者nose来编写的。
    不用担心,执行pytest命令同样可以正常运行这些用例并得到结果。
    因此无需担心迁移单测框架从而带来额外的人工成本。

    
    

    常用插件

    
    

    在之前的内容中,我们提到了pytest的一个优点是有大量的插件支持,例如:

    
    
      • pytest-django: 针对Django框架的单测框架
      • pytest-twisted: 针对twisted框架的单测框架
      • pytest-cov: 产生覆盖率报告
      • pytest-instafail: 发送错误时报告错误信息
      • pytest-bdd 测试驱动开发工具
      • pytest-konira 测试驱动开发工具
      • pytest-timeout: 支持超时功能
      • pytest-pep8: 支持PEP8检查
      • pytest-flakes: 结合pyflakes进行代码检查
    
    
  • 相关阅读:
    Click: 命令行工具神器
    Pipenv: Python包管理神器
    如何让你的Python程序支持多语言
    Volatile变量
    简单排查java应用CPU飙高的线程问题
    java中的clone
    接口限流
    HTTP协议详解
    [转]nginx 源码学习笔记(十五)—— ngx_master_process_cycle 多进程(一)
    nginx slab内存管理
  • 原文地址:https://www.cnblogs.com/klb561/p/10272719.html
Copyright © 2011-2022 走看看