这篇文章上次修改于 588 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

安装

  • pip install pytest

规范

  • 测试用例 test__ 或者 _test 开头
  • 测试类 使用 Test 开头
  • 文件使用 test 开头

pytest用例执行机制,测试用例执行场景,批量执行,指定特定的测试用例执行

  • 标记测试用例 mark

    @pytest.mark.testcase
    def test_make():
    		assert 2 == 2
  • 查看测试用例名称

    关键字:--collect-only
    语法:pytest -q -s --collect-only 用例目录/用例
  • 执行指定测试用例

    1. pytest test_mod.py   执行指定测试用例
    2. pytest testing_dir/  执行指定测试目录下的测试用例
  • 测试用例错误达到number个数停止执行用例 –maxfail=number

    1. pytest -x pytest_base/base_debug.py 遇见第一个报错停止执行测试用例
    2. pytest --maxfail=2 pytest_base/base_debug.py 遇见第2个报错停止执行测试用例
  • 测试用例关键字执行

    pyest -k 关键字
    注意事项:python关键字不可以出现在 pytest -k 中
  • 测试执行报告

    1. -r: 可以在执行结束后,打印出简短的测试结果结果报告,在执行很多测试用例时,可以清晰的了解结果
    2. -r后面紧跟一个参数,时过滤
    3. 参数:f(失败)  E(错误)  p(通过) A(所有)  s(跳过)
    4. 参数:x(跳过执行,标记为xfailed的)  X(跳过执行,标记为Xpassed的)
    5. 参数:a(除了测试通过的,其他所有的)  P(测试通过,并且有输出信息)
    pytest -q -s -r 测试用例     其他参数动手自行练习一下
  • 用例错误信息诊断

    pytest -pdb 如果测试用例执行fail, 那么将会打印出python诊断器详细的信息
    在执行测试用例时启动pdb诊断器
    pytest --trace -q -r 用例路径
  • 分析测试用例的时间

    pytest --durations=n  查看执行最慢的n个测试用例

fixture

定义

公共方法参数化fixture 在测试用例中,比如查询订单,需要用户token, 可以将生成的token参数化,代码复用,减少冗余代码, 可以理解成公共方法的封装

  • fixture参数 fixture(scope=“function”, params=None, autouse=False, ids=None, name=None)

  • scope参数:scope = “function”, scope = “module”, scope=“class”, scope=“package”

  • fixture: 作为形参使用,对应的fixture就是函数的返回值

    @pytest.fixture
      def func():
          sum = 3 + 2
          return sum
    
      def test_one(func):
          assert func == 5
    
      def test_two(func):
          assert func == 6
      
        当test_one和test_two测试用例接收 func 函数时, fixture的作用是实例化函数,
    然后返回 func 的值
  • fixture 使用参数介绍

    1. fixture为session级别是可以跨.py模块调用的,也就是当我们有多个.py文件的用例的时候,如果多个用例只需调用一次fixture,那就可以设置为scope="session",并且写到conftest.py文件里。
    
    2. module 在当前模块.py脚本里面所有用例开始前只执行一次
    
    3. package 会作用于包内的每一个测试用例, 且只被调用一次
    
    4. function  每个测试用例都会调用一次
    
    5. class  如果一个class 中有多个测试用例, 在类中只调用一次
    
    
    举个例子:在不同的测试用例目录下,有活动查询,活动下单,订单查询用例,都需要带token参数, 那么我们在conftest里封装获取token的方法,定义成:scope="session", 那么所有测试用例执行时的token值是相同的,这就是只执行一次。
    
    如果定义成scope=class, 那么每个测试类都会执行一次,什么意思呢,比如我有3个测试用例类,那么token封装的方法就会执行3次,生成3个不同的token值。
  • fixture 使用规则

    1. 如果想在多个测试模块中共用一个fixture, 可以把 fixture 移动到conftest.py中,测试模块不需要手动导入,pytest会自动导入。
     
    2. fixture 自动导入的顺序: 测试类 > 测试模块 > conftest.py > 第三方插件
      
     
  • fixture 参数化

    1. params是列表形式,参数列表用 request.param 遍历参数
       @pytest.fixture(params=[(username, passwd)], ids=["A", "B", "C用户登录", "D", "E"])
           def func1(request):
           x = request.param
           sum = x + x
           return sum
    
    2. params是列表形式, 当参数是字典,request.param遍历参数
      order = [
          {
              "addr": "黄金书",
              "city": "shenzhen"
          },
          {
              "addr": "福田",
              "city": "深圳"
          }
      ]
      @pytest.fixture(params=order)
      def func4(request):
          infor = request.param
          addr = infor["addr"]
          city = infor
          yiled addr
          
    
    3. 同理,当参数是元组,或是其他数据类型,记住,首先params接收的是列表,然后处理列表里面的数据类型
  • fixture 的清理操作

    比如在连接数据库时,操作完数据库之后,需要关闭数据库
    将fixture函数中的 return 换成 yield, 则yield后面的代码就是我们需要清理的操作, 也可以用with

    fixture 和 usefixtures的区别

    1. 如果fixture有返回值,那么usefixture就无法获取到返回值,这个是装饰器usefixture与用例直接传fixture参数的区别。
    
    例子:
    创建conftest.py 文件
    import pytest
    from pathlib import Path
    import os
    # 区分 userfixture 和 fixture
    
    #无返回值
    @pytest.fixture(scope="session")
    def create_userfixture_dir():
        path = "userfixture"
        os.mkdir(path, 770)
    #无返回值
    @pytest.fixture(scope="session")
    def create_fixture_dir():
        path = "fixture"
        os.mkdir(path, 770)
    #无返回值
    @pytest.fixture(scope="function")
    def add_sum_one():
        sum = 5 + 5
    
    #有返回值
    @pytest.fixture(scope="function")
    def add_sum_two():
        sum = 5 + 5
        return sum
    
    
    usefixtures_fixture_diff.py 文件
    import pytest
    #调用时,生成userfixture目录
    @pytest.mark.usefixtures('create_userfixture_dir')
    def test_usefixture():
        pass
    #调用时,生成fixture目录
    def test_fixture(create_fixture_dir):
        pass
      
    # 说明userfixture 和 fixture都可以调用无返回值的函数  
      
    # 这是个错误的测试用例,因为 usefixtures 不能接受返回值
    @pytest.mark.usefixtures("add_sum_two")
    def test_add_sum_tow():
        assert add_sum_two == 10
    
    # fixture能接受函数返回值,所以断言成功
    def test_add_sum_two_fixture(add_sum_two):
        assert add_sum_two == 10
        
    userfixture使用场景:如活动在购物车结算失败,清空购物车信息,创建目录等。
    fixture使用场景:如活动下单需要token, 定义生成token的方法,将值返回给方法函数,用于下单。

@pytest.mark.parametrize 测试用例参数化

  • parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None):

  • argvalues 有n个参数,pytest.mark.parametrize会依次取参进行测试

    例子:
    @pytest.mark.parametrize('test_input, expected', [('3 + 5', 8)])
    def test_data2(test_input, expected):
        print(test_input, expected)
        assert eval(test_input) == expected

测试用例标记

  • @pytest.mark.skip(reason=None) 无条件跳过测试用例

    skip 源码 def skip(self,reason=None)
    
    例子:
    @pytest.mark.skip(reason="无条件跳过")
    def test_one():
        assert 3 == 4 
  • pytest.mark.skipif(condition, reason=None) 有条件跳过测试用例

    skipif 源码 def skipif(self,condition, reason=None):
    当条件成立,才不执行测试用例,条件不成立,则执行测试用例
    
    例子:
    num = 4
    @pytest.mark.skipif(num == 4, reason="有条件跳过")
    def test_two():
        assert  4 == 4
  • @pytest.mark.xfail(condition=None, reason=None, raises=None, run=True, strict=False)

    xfail 源码  def xfail(self,condition=None, reason=None, raises=None, run=True, strict=False):
    
    例子1@pytest.mark.xfail(reason="期待为xfail")
    def test_xfail():
         assert 8 == 9
    期待测试用例为xfail, 当断言失败,用例标记为xfail,满足期待,当断言成功,测试用例标记为xpassed, 与预期相反
    
    例子2@pytest.mark.xfail(reason="期待为xfail", strict=True)
    def test_xfail_strict():
         assert 8 == 9
    当strcit参数为true时,测试用例不符合预期结果,将用例标记为fail

pytest第三方插件

  • pytest-rerunfailures

    • 插件官网

    • 安装: pip install pytest-rerunfailures

    • 功能介绍:当测试用例执行失败时,我们可以指定该测试用例的最大执行次数,如果在最大执行次数内执行通过,用例将不再执行

      1. 命令:pytes --return 5 测试用例
      2. 可以用 flaky 来进行标记
      	 - @pytest.mark.flaky(reruns= ,reruns_de1lay=None)
      
      例子: return_fail.py
      import pytest
      @pytest.mark.flaky(reruns=10,reruns_delay=1)
      def test_example():
          import random
          num = random.randint(1, 10)
          assert num == 5
    • pytest 有许多有用的插件,不再举例说明,根据自己需求,用到时查询相关资料

      • pytest-xdist: 并发执行测试用例
      • pytest-assume: 多重断言校验
      • pytest-ordering:设定测试用例执行顺序
      • pytest-sugar: 显示测试用例执行进度条