The pytest framework makes it easy to write small, readable tests, and can scale to support complex functional testing for applications and libraries. 这段话很好地阐述了Pytest的设计思想与强大的特性。之前阐述了Pytest测试框架搜索规则Pytest测试框架执行方式,本文章详细地阐述下Pytest测试框架中参数化特性。

参数化本质详解

参数化的应用场景简单的描述就是针对一个被测的对象,当存在相同的测试步骤不同的测试数据时,可以使用参数化的设计思想,从而能够达到使用少量的代码达到测试覆盖率的最大化。在企业里面这样的应用场景可以说是非常多的,比如测试支付的服务,那么支付类型有很多,但是它符合相同测试步骤不同测试数据的维度,还有如商品搜索也是如此。

了解了应用场景后再来理解它的核心本质,参数化核心本质具体就是测试的数据存储在列表中,对列表中的对象进⾏循环,然后把列表循环的对象赋值给具体的对象。

Pytest参数化实战

在Pytest测试框架中参数化主要是通过parametrize来进行实现的,下面先以一个两个数相加为案例来演示下这部分的案例使用,案例以及测试代码如下:

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# author:无涯

import  pytest

def add(a,b):
  return a+b

def  data():
  return [
    [1,4,5],
    ['wuya','Share','wuyaShare'],
    [1.0,4.0,5.0],
    [1,4.0,5.0],
    [[1,2,3],[4,5,6],[1,2,3,4,5,6]]
  ]

@pytest.mark.parametrize('x,y,result',data())
def test_add(x,y,result):
  assert add(a=x, b=y) == result

在如上的案例代码中,把测试数据分离到data的函数里面,这样在测试函数执行的时候,根据循环,把对应的值依次赋值给x、y、result,通过debug的模式就可以看到这部分,如下图所示的是第二次循环赋值的过程,具体如下。

Pytest测试实战|参数化_测试开发

其实只要是理解了参数化的本质思想,这些就是很好理解的。

在Pytest参数化中,可以使用多种不同的数据结构,如列表、元组、字典等数据类型,依然适用于上面的代码,把测试数据使用字典的形式来进行存储,改造后的代码如下:

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# author:无涯

import  pytest

def add(a,b):
  return a+b

def  data():
  return [
    {'x':1,'y':4,'result':5},
    {'x':'wuya','y':'Share','result':'wuyaShare'},
    {'x':1.0,'y':4.0,'result':5.0},
    {'x':1,'y':4.0,'result':5.0},
    {'x':[1,2,3],'y':[4,5,6],'result':[1,2,3,4,5,6]}
  ]

@pytest.mark.parametrize('data',data())
def test_add(data):
  assert add(a=data['x'], b=data['y']) == data['result']

if __name__ == '__main__':
  pytest.main(["-s","-v","test_add.py"])

使用测试数据驱动的思想,一般都会把数据分离到文件中,文件的形式当然可以选中多种不同的数据类型,一般建议使用JSON文件或者是YAML文件,这里以JSON文件为案例演示下把测试数据分离到JSON文件的案例实战应用。分离到JSON文件里面的数据如下所示。

Pytest测试实战|参数化_软件测试_02

编写函数读取JSON文件里面的内容,完善后的代码如下所示。

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# author:无涯


import  pytest
import  json


def add(a,b):
  return a+b


def  data():
  return json.load(open('data.json'))


@pytest.mark.parametrize('data',data())
def test_add(data):
  assert add(a=data['x'], b=data['y']) == data['result']


if __name__ == '__main__':
  pytest.main(["-s","-v","test_add.py"])

执行后显示的结果信息如下。

Pytest测试实战|参数化_pytest_03

Pytest框架中参数化的特性是非常强大的,使用该特性可以在企业级里面再进行到某一个模块或者验证某一个功能的时候,当它的条件符合参数化的应用场景,完全可以使用参数化的设计思想来实现这部分,这样的优势是显而易见的,能够减少编写重复的代码,从而达到测试覆盖率场景最大化的覆盖。同时也可以使用Pytest参数化特性,可以实现PostMan接口测试用例智能化转为Pyhton测试代码。感谢您的阅读,后续持续更新不同技术栈文章。