Serie Pytest: @pytest.mark.parametrize basado en datos (7)

Introducción

Comparación de parametrización entre unittest y pytest:
una diferencia importante entre pytest y unittest es la parametrización: la biblioteca de terceros ddt utilizada por el marco unittest está parametrizada.

Y el marco pytest:

  • La función de pre/postprocesamiento tiene un parámetro params que se usa especialmente en combinación con la solicitud para pasar parámetros. Parametrize también se puede usar en combinación con la solicitud para pasar parámetros.
  • Para la parametrización del método de prueba, utilice decoradores directamente @pytest.mark.parametrizepara pasar parámetros a los casos de prueba.

Propósito de parametrización

  • La parametrización consiste en extraer los datos durante el proceso de prueba y pasar diferentes datos a través de parámetros para impulsar la ejecución del caso de uso. De hecho, es el concepto de basado en datos.
  • Cuando un caso de prueba solo tiene diferentes datos de prueba y resultados esperados, pero los pasos de operación son los mismos, la parametrización se puede utilizar para mejorar la reutilización del código y reducir la redundancia del código.

Ejemplos de aplicaciones prácticas de parametrización.

Escenarios de desarrollo en la automatización de la interfaz de usuario web, como un cuadro de inicio de sesión:

1. Es necesario probar la situación en la que la cuenta está vacía, la contraseña está vacía, la cuenta y la contraseña están vacías, la cuenta no existe, la contraseña es incorrecta, la cuenta y la contraseña son correctas, etc. La
diferencia entre estos casos de uso radica en los datos de prueba de entrada y los resultados de interacción correspondientes
3. Por lo tanto, podemos escribir solo un caso de prueba de inicio de sesión y luego parametrizar múltiples conjuntos de datos de prueba y resultados esperados, ahorrando una gran cantidad de código.

Parametrización de Pytest

gramática

@pytest.mark.parametrize(args_name,args_values,indirect=False, ids=None,scope=None)

lista de parámetros

  • args_name : nombre del parámetro, utilizado para pasar valores de parámetros a la función
  • args_values : Valores de parámetros: (lista y diccionario de lista, tupla y tupla de diccionario), si hay n valores, entonces el caso de uso se ejecuta n veces.
  • indirecto : el valor predeterminado es Falso, lo que significa que se pasan parámetros. Si se establece en Verdadero, el parámetro pasado se ejecutará como una función en lugar de un parámetro.
  • ids : personalice la identificación de la prueba, la lista de cadenas, la longitud de las identificaciones debe ser consistente con la longitud de la lista de datos de la prueba, identifique cada caso de prueba, personalice la visualización de los resultados de los datos de la prueba para aumentar la legibilidad.
  • alcance : si se especifica, indica el alcance del parámetro.
    Los ámbitos se utilizan para agrupar pruebas por instancias de parámetros.
    También anulará el alcance definido por cualquier función de dispositivo, lo que permitirá establecer el alcance dinámico utilizando el contexto o la configuración de prueba.

Instrucciones

1. Parámetro único

​​@pytest.mark.parametrize()​​El decorador recibe dos parámetros, un parámetro es un parámetro que identifica la función del caso de uso en forma de cadena y el segundo parámetro pasa los datos de prueba en forma de lista o tupla.

import pytest
#待测试数据
def add(a,b):
    return a+b

# 单个参数的情况
@pytest.mark.parametrize("a",[1,2,3,4])
def test_add(a):  # 作为用例参数,接收装饰器传入的数据
    print(" a的值:",a)
    assert add(a,1) == a+1

Resultados de la
Insertar descripción de la imagen aquí

2. Múltiples parámetros

Para múltiples parámetros, ​​@pytest.mark.parametrize()​​el primer parámetro sigue siendo una cadena. Para múltiples parámetros del ejemplo de aplicación, sepárelos con comas. En realidad, es un proceso de desempaquetado.

import pytest

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

@pytest.mark.parametrize("a,b,c",[(1,2,3),(4,5,9),('1','2','12')])
def test_add(a,b,c):
    print(f"\n a,b,c的值:{
      
      a},{
      
      b},{
      
      c}")
    assert add(a,b)==c

Insertar descripción de la imagen aquí
Resultados de la
Insertar descripción de la imagen aquí

3. Parametrización de toda la clase de prueba.

La parametrización de la clase de prueba en realidad también parametriza los métodos de prueba en la clase.
Cuando un decorador @pytest.mark.parametrizedecora una clase de prueba, pasa la recopilación de datos a todos los métodos de casos de prueba de la clase.

import pytest

data= [(1,2,3),(4,5,9)]

@pytest.mark.parametrize("a,b,c",data)
class TestStudy:
    def test_parametrize_one(self,a,b,c):
        print(f"\n 测试函数111  测试数据为 {
      
      a}-{
      
      b}")
        assert a+b ==c

    def test_parametrize_two(self, a, b, c):
        print("\n 测试函数222  测试数据为 {}-{}".format(a,b))
        assert a + b == c

Resultados de la
Insertar descripción de la imagen aquí

4. Superposición y multiplicación de múltiples parámetros.

El producto cartesiano se utiliza cuando se combinan múltiples parámetros .
Producto cartesiano:

  • Una función o una clase se puede decorar con múltiples @pytest.mark.parametrizes
  • De esta forma, el número final de casos de uso generados es n m. Por ejemplo, el código anterior es: hay 3 datos para el parámetro a y 2 datos para el parámetro b, por lo que el número final de casos de uso es 3 2 = 6
  • Cuando hay muchos decoradores parametrizados, el número de casos de uso es igual a n * n * n* n *…
# 笛卡尔积,组合数据
data_1=[1,2,3]
data_2=['a','b']

@pytest.mark.parametrize('a',data_1)
@pytest.mark.parametrize('b',data_2)
def test_parametrize_one(a,b):
    print(f"笛卡尔积 测试数据为:{
      
      a}{
      
      b}")

Parametrizar el resultado de la ejecución y pasarlo en el diccionario.
Insertar descripción de la imagen aquí

# 字典
data_1=(
    {
    
    
        'user':1,
        'pwd':2
    },
    {
    
    
        'user':3,
        'pwd':4
    }
)

@pytest.mark.parametrize('dic',data_1)
def test_parametrize_1(dic):
    print(f"测数据为 \n {
      
      dic}")
    print(f"user:{
      
      dic['user']},pwd:{
      
      dic['pwd']}")

Parametrización de resultados de ejecución
Insertar descripción de la imagen aquí
, datos etiquetados

# 标记参数化
@pytest.mark.parametrize("test_input,expected",[
    ("3+5",8),
    ("2+4",6),
    pytest.param("6 * 9",42,marks=pytest.mark.xfail),
    pytest.param("6 * 6",42,marks=pytest.mark.skip)
])
def test_parametrize_mark(test_input,expected):
    assert  eval(test_input) == expected

Resultados de la
Insertar descripción de la imagen aquí

5. ID de prueba personalizada de ID

  • ​​@pytest.mark.parametrize()​​​El parámetro ids se proporciona para personalizar los resultados de la visualización, principalmente para ver el significado del caso de uso con mayor claridad.

  • La longitud de los identificadores debe ser coherente con la longitud de la lista de datos de prueba, que es la misma que el parámetro de identificadores del dispositivo. Consulte los identificadores del dispositivo.

# 增加可读性
data_1=[(1,2,3),(4,5,9)]

ids = ["a:{} + b:{} = expect:{}".format(a,b,expect) for a,b,expect in data_1]

@pytest.mark.parametrize("a,b,expect",data_1,ids=ids)
class TestParametrize(object):
    def test_parametrize_1(self,a,b,expect):
        print(f"测试函数1测试数据为 {
      
      a}--{
      
      b}")
        assert a + b ==expect

    def test_parametrize_2(self,a,b,expect):
        print("测试函数2测试数据为 {}--{}".format(a,b))
        assert  a + b == expect

Resultados de la
Insertar descripción de la imagen aquí

La solicitud se utiliza en combinación con parametrizar para pasar parámetros al accesorio.

  • Los parámetros del dispositivo en sí se pueden pasar en combinación con la solicitud. Para más detalles, consulte el capítulo de introducción de otros parámetros del dispositivo. Por supuesto, también puede usar parametrize para parametrizar en lugar de params.

  • parámetro indirect = True, el propósito es ejecutar los datos entrantes como una función, no como un parámetro

  • Si el método de prueba está escrito en una clase, los @pytest.mark.parametrizenombres de los parámetros deben @pytest.fixtureser coherentes con los nombres de las funciones.

Escenarios de aplicación:

  • Para mejorar la reutilización, cuando escribimos casos de prueba, usaremos diferentes dispositivos, como: la operación de inicio de sesión más común, la condición previa de la mayoría de los casos de uso es iniciar sesión.
  • Suponiendo que diferentes casos de uso quieran iniciar sesión en diferentes cuentas de prueba, entonces la cuenta no puede codificarse al iniciar sesión en el dispositivo. La operación de inicio de sesión debe completarse pasando parámetros.

1. Parámetro único

@pytest.fixture()
def test_demo(request):
    name = request.param
    yield name
    print(f"==测试数据是:{
      
      name}==")


data=["ceshi","qianduan"]
ids=[f"test_name is:{
      
      name}" for name in data]

@pytest.mark.parametrize("test_demo",data,ids=ids,indirect=True)
def test_name(test_demo):
    print(f"测试用例的数据是:{
      
      test_demo}")


Insertar descripción de la imagen aquí
Puntos de conocimiento de los resultados de la ejecución :

  • El parámetro indirect=True se agrega para ejecutar test_demo como una función en lugar de un parámetro y pasar datos a la función como un parámetro.
  • def test_name(test_demo), test_demo aquí está el valor devuelto al obtener el dispositivo

2. Múltiples parámetros

@pytest.fixture()
def logins(request):
    param = request.param
    yield param
    print(f"账号是:{
      
      param['username']},密码是:{
      
      param['pwd']}")

data =[
    {
    
    "username":"张三","pwd":"123456"},
    {
    
    "username":"李四","pwd":"12345"}
]

@pytest.mark.parametrize("logins",data,indirect=True)
def test_name_pwd(logins):
    print(f"账号是:{
      
      logins['username']},密码是:{
      
      logins['pwd']}")

Resultados de la ejecución
Insertar descripción de la imagen aquí
Si es necesario pasar varios parámetros, es necesario pasarlos a través de un diccionario.

3. Múltiples accesorios (solo agregue un decorador) y múltiples parámetros (decoradores superpuestos)

# 多个fixture
@pytest.fixture()
def login_user(request):
    user = request.param
    yield user
    print("账号:%s" % user)

@pytest.fixture()
def login_pwd(request):
    pwd = request.param
    yield pwd
    print("密码:%s" % pwd)

data =[
    {
    
    "username":"张三","pwd":"123456"},
    {
    
    "username":"李四","pwd":"12345"}
]

@pytest.mark.parametrize("login_user,login_pwd",data,indirect=True)
def test_more_fixture(login_user,login_pwd):
    print("fixture返回的内容:",login_user,login_pwd)

Resultados de la
Insertar descripción de la imagen aquí

@pytest.fixture(scope="function")
def login_user(request):
    user = request.param
    yield user
    print("账号:%s" % user)

@pytest.fixture(scope="function")
def login_pwd(request):
    pwd = request.param
    yield pwd
    print("密码:%s" % pwd)

name= ["张三","李四"]
pwd = ["123456","12345"]

@pytest.mark.parametrize("login_user",name,indirect=True)
@pytest.mark.parametrize("login_pwd",pwd,indirect=True)
def test_more_fixture(login_user,login_pwd):
    print("fixture返回的内容:",login_user,login_pwd)

Resultados de la
Insertar descripción de la imagen aquí

[Artículo de referencia] Notas de prueba de Little Pineapple

Supongo que te gusta

Origin blog.csdn.net/m0_62091240/article/details/132839957
Recomendado
Clasificación