Parametrización de Pytest: las habilidades que no conoce

Tabla de contenido

prefacio

Decora la clase de prueba

producción

ilustrar

Decora la función de prueba

datos individuales

producción

ilustrar

un conjunto de datos

producción

ilustrar

Correspondencia gráfica

datos combinados

producción

ilustrar

marcar caso de uso

producción

ilustrar

diccionarios anidados

producción

aumentar la legibilidad

Usa el parámetro ids

producción

ilustrar

Identificación personalizada para identificación

producción

ilustrar

Resumir

Resumir:


prefacio

El marco de pruebas unitarias unittest utiliza DDT para pruebas basadas en datos, entonces, ¿cómo puede el marco Pytest más potente y flexible no tener el concepto de basado en datos? De hecho, Pytest usa el decorador @pytest.mark.parametrize para implementar pruebas basadas en datos, por lo que hoy simplemente hablaremos sobre cómo realiza las pruebas basadas en datos.

Decora la clase de prueba

"""
------------------------------------
@Time : 2019/7/25 19:18
@Auth : linux超
@File : test_parametrize.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest

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


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


@pytest.mark.parametrize('a, b, expect', data_1)
class TestParametrize(object):

    def test_parametrize_1(self, a, b, expect):
        print('\n测试函数1测试数据为\n{}-{}'.format(a, b))
        assert add(a, b) == expect

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


if __name__ == '__main__':
    pytest.main(['-sv'])

producción

collecting ... collected 4 items

test_parametrize.py::TestParametrize::test_parametrize_1[1-2-3] 
测试函数1测试数据为
1-2
PASSED
test_parametrize.py::TestParametrize::test_parametrize_1[4-5-9] 
测试函数1测试数据为
4-5
PASSED
test_parametrize.py::TestParametrize::test_parametrize_2[1-2-3] 
测试函数2数据为
1-2
PASSED
test_parametrize.py::TestParametrize::test_parametrize_2[4-5-9] 
测试函数2数据为
4-5
PASSED

========================== 4 passed in 0.21 seconds ===========================

Process finished with exit code 0

ilustrar

Cuando el decorador decora la clase de prueba, la recopilación de datos se pasará a todos los métodos de la clase.

Decora la función de prueba

datos individuales

"""
------------------------------------
@Time : 2019/7/25 19:18
@Auth : linux超
@File : test_parametrize.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest

data = [1, 2]


@pytest.mark.parametrize('a', data)
def test_parametrize(a):
    print('\n被加载测试数据为\n{}'.format(a))


if __name__ == '__main__':
    pytest.main(['-s'])

producción

============================= test session starts =============================
platform win32 -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: E:\CnblogCode\pytest_parametrize, inifile:
plugins: rerunfailures-7.0, metadata-1.8.0, html-1.20.0
collected 2 items

test_parametrize.py 
被加载测试数据为
1
.
被加载测试数据为
2
.

========================== 2 passed in 0.16 seconds ===========================

Process finished with exit code 0

ilustrar

Cuando el caso de prueba solo necesita un parámetro, almacenamos la secuencia anidada desordenada de listas de datos, y el primer parámetro del decorador @pytest.mark.parametrize('a', data) también solo necesita una variable para recibir cada uno en el elementos de la lista, el segundo parámetro pasa una lista de datos almacenados, luego el caso de prueba necesita usar una cadena con el mismo nombre para recibir los datos de prueba (a en la instancia) y tantos casos de prueba como elementos haya en la lista. ser generado y ejecutado

un conjunto de datos

"""
------------------------------------
@Time : 2019/7/25 19:18
@Auth : linux超
@File : test_parametrize.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest

data = [
    [1, 2, 3],
    [4, 5, 9]
]  # 列表嵌套列表
# data_tuple = [
#     (1, 2, 3),
#     (4, 5, 9)
# ]  # 列表嵌套元组


@pytest.mark.parametrize('a, b, expect', data)
def test_parametrize_1(a, b, expect):  # 一个参数接收一个数据
    print('\n测试数据为\n{},{},{}'.format(a, b, expect))
    actual = a + b
    assert actual == expect


@pytest.mark.parametrize('value', data)
def test_parametrize_2(value):  # 一个参数接收一组数据
    print('\n测试数据为\n{}'.format(value))
    actual = value[0] + value[1]
    assert actual == value[2]


if __name__ == '__main__':
    pytest.main(['-s'])

producción

============================= test session starts =============================
platform win32 -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: E:\CnblogCode\pytest_parametrize, inifile:
plugins: rerunfailures-7.0, metadata-1.8.0, html-1.20.0
collected 4 items

test_parametrize.py 
测试数据为
1,2,3
.
测试数据为
4,5,9
.
测试数据为
[1, 2, 3]
.
测试数据为
[4, 5, 9]
.

========================== 4 passed in 0.17 seconds ===========================

Process finished with exit code 0

ilustrar

Cuando un caso de prueba requiere múltiples datos, podemos usar una lista de secuencias anidadas (tuplas anidadas y listas anidadas) para almacenar datos de prueba

El decorador @pytest.mark.parametrize() puede recibir datos utilizando una sola variable o múltiples variables. De manera similar, la función de caso de prueba debe ser coherente con ella.

Cuando se usa una sola variable para recibir, cuando los datos de prueba se pasan a la función de prueba, es cada elemento de la lista o una lista pequeña, y cada dato debe obtenerse indexando

Cuando se usan múltiples variables para recibir datos, cada variable recibe cada elemento en una pequeña lista o tupla por separado

Cuántos conjuntos de listas pequeñas o tuplas están anidados en la lista y cuántos casos de prueba se generan

Correspondencia gráfica

datos combinados

"""
------------------------------------
@Time : 2019/7/25 19:18
@Auth : linux超
@File : test_parametrize.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest

data_1 = [1, 2]  
data_2 = [3, 4]  


@pytest.mark.parametrize('a', data_1)
@pytest.mark.parametrize('b', data_2)
def test_parametrize_1(a, b):
    print('\n测试数据为\n{},{}'.format(a, b))


if __name__ == '__main__':
    pytest.main(['-s'])

producción

============================= test session starts =============================
platform win32 -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: E:\CnblogCode\pytest_parametrize, inifile:
plugins: rerunfailures-7.0, metadata-1.8.0, html-1.20.0
collected 4 items

test_parametrize.py 
测试数据为
1,3
.
测试数据为
2,3
.
测试数据为
1,4
.
测试数据为
2,4
.

========================== 4 passed in 0.24 seconds ===========================

Process finished with exit code 0

ilustrar

A través de los resultados de la prueba, no es difícil para nosotros analizar que una función de prueba también puede ser decorada por múltiples decoradores parametrizados al mismo tiempo, luego los datos en múltiples decoradores se combinarán de forma cruzada y se pasarán a la función de prueba para generar n *n pruebas Casos de uso, que también brindan comodidad para nuestro diseño de prueba

marcar caso de uso

Los casos de prueba se pueden marcar directamente y los decoradores parametrizados también se pueden reconocer (marcar casos de prueba como fallidos u omitidos)

Marcado como omitido incondicionalmente (marcado como xfail por falla, pruébelo usted mismo)

"""
------------------------------------
@Time : 2019/7/25 19:18
@Auth : linux超
@File : test_parametrize.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest

data_1 = [
    [1, 2, 3],
    pytest.param(3, 4, 8, marks=pytest.mark.skip)
]


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


@pytest.mark.parametrize('a, b, expect', data_1)
def test_parametrize_1(a, b, expect):
    print('\n测试数据为\n{},{}'.format(a, b))
    assert add(a, b) == expect


if __name__ == '__main__':
    pytest.main(['-vs'])

producción

============================= test session starts =============================
platform win32 -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0 -- C:\Programs\Python\Python37-32\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Windows-7-6.1.7601-SP1', 'Packages': {'pytest': '4.3.1', 'py': '1.8.0', 'pluggy': '0.9.0'}, 'Plugins': {'rerunfailures': '7.0', 'metadata': '1.8.0', 'html': '1.20.0'}, 'JAVA_HOME': 'D:\\JDK'}
rootdir: E:\CnblogCode\pytest_parametrize, inifile:
plugins: rerunfailures-7.0, metadata-1.8.0, html-1.20.0
collecting ... collected 2 items

test_parametrize.py::test_parametrize_1[1-2-3] 
测试数据为
1,2
PASSED
test_parametrize.py::test_parametrize_1[3-4-8] SKIPPED

===================== 1 passed, 1 skipped in 0.17 seconds =====================

Process finished with exit code 0

ilustrar

El resultado muestra que se han recopilado 2 casos de uso, uno aprobado y el otro omitido. Cuando no queremos ejecutar un determinado conjunto de datos de prueba, podemos marcar skip o skipif; cuando esperamos que un determinado conjunto de datos falle, podemos marcarlo como xfail esperar

diccionarios anidados

"""
------------------------------------
@Time : 2019/7/25 19:18
@Auth : linux超
@File : test_parametrize.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest

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


@pytest.mark.parametrize('dic', data_1)
def test_parametrize_1(dic):
    print('\n测试数据为\n{}'.format(dic))


if __name__ == '__main__':
    pytest.main(['-s'])

producción

============================= test session starts =============================
platform win32 -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: E:\CnblogCode\pytest_parametrize, inifile:
plugins: rerunfailures-7.0, metadata-1.8.0, html-1.20.0
collected 2 items

test_parametrize.py 
测试数据为
{'user': 1, 'pwd': 2}
.
测试数据为
{'user': 3, 'pwd': 4}
.

========================== 2 passed in 0.20 seconds ===========================

Process finished with exit code 0

aumentar la legibilidad

Usa el parámetro ids

El decorador parametrizado tiene identificadores de parámetros adicionales, que pueden identificar cada caso de prueba y personalizar la visualización de los resultados de los datos de prueba. Para aumentar la legibilidad, podemos marcar qué datos de prueba se utilizan en cada caso de prueba y agregar algunos ilustrados apropiadamente.

Antes de usarlo, debe saber que el parámetro ids debe ser una lista de cadenas, que debe ser coherente con la longitud de la lista de objetos de datos. Podemos intentar usar ids para ver el efecto.

"""
------------------------------------
@Time : 2019/7/25 19:18
@Auth : linux超
@File : test_parametrize.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest

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


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

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


@pytest.mark.parametrize('a, b, expect', data_1, ids=ids)  
class TestParametrize(object):

    def test_parametrize_1(self, a, b, expect):
        print('\n测试函数1测试数据为\n{}-{}'.format(a, b))
        assert add(a, b) == expect

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


if __name__ == '__main__':
    pytest.main(['-v'])  # -v : 更加详细的输出测试结果

producción

El decorador no pasa la salida del parámetro ids

collecting ... collected 4 items

test_parametrize.py::TestParametrize::test_parametrize_1[1-2-3] PASSED   [ 25%]
test_parametrize.py::TestParametrize::test_parametrize_1[4-5-9] PASSED   [ 50%]
test_parametrize.py::TestParametrize::test_parametrize_2[1-2-3] PASSED   [ 75%]
test_parametrize.py::TestParametrize::test_parametrize_2[4-5-9] PASSED   [100%]

========================== 4 passed in 0.16 seconds ===========================

Process finished with exit code 0

El decorador pasa la salida del parámetro ids

collecting ... collected 4 items

test_parametrize.py::TestParametrize::test_parametrize_1[a:1 + b:2 = expect:3] PASSED [ 25%]
test_parametrize.py::TestParametrize::test_parametrize_1[a:4 + b:5 = expect:9] PASSED [ 50%]
test_parametrize.py::TestParametrize::test_parametrize_2[a:1 + b:2 = expect:3] PASSED [ 75%]
test_parametrize.py::TestParametrize::test_parametrize_2[a:4 + b:5 = expect:9] PASSED [100%]

========================== 4 passed in 0.20 seconds ===========================

Process finished with exit code 0

ilustrar

Usé -v para ejecutar el comando, y los resultados de salida se mostrarán con más detalle. Puede ver que todos los casos de uso en los resultados de datos están claramente marcados por una lista, y a través de esta marca, se puede ver de manera más intuitiva. Cada prueba El nombre de los datos y el contenido de la prueba utilizados en el caso de uso

Identificación personalizada para identificación

Además de usar el parámetro ids para aumentar la legibilidad de la salida, también podemos definir un valor de id al lado del parámetro en la lista de parámetros para identificación, vea el siguiente ejemplo

"""
------------------------------------
@Time : 2019/7/25 19:18
@Auth : linux超
@File : test_parametrize.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest

data_1 = [
    pytest.param(1, 2, 3, id="(a+b):pass"),  # id的值可以自定义, 只要方便理解每个用例是干什么的即可
    pytest.param(4, 5, 10, id="(a+b):fail")
]


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


class TestParametrize(object):

    @pytest.mark.parametrize('a, b, expect', data_1)
    def test_parametrize_1(self, a, b, expect):
        assert add(a, b) == expect


if __name__ == '__main__':
    pytest.main(['-v'])

producción

test_parametrize.py::TestParametrize::test_parametrize_1[(a+b):pass] PASSED [ 50%]
test_parametrize.py::TestParametrize::test_parametrize_1[(a+b):fail] FAILED [100%]

================================== FAILURES ===================================
_______________ TestParametrize.test_parametrize_1[(a+b):fail] ________________

self = <pytest_parametrize.test_parametrize.TestParametrize object at 0x000001D7BFC4C748>
a = 4, b = 5, expect = 10

    @pytest.mark.parametrize('a, b, expect', data_1)
    def test_parametrize_1(self, a, b, expect):
>       assert add(a, b) == expect
E       assert 9 == 10
E         -9
E         +10

test_parametrize.py:28: AssertionError
===================== 1 failed, 1 passed in 0.35 seconds ======================

Process finished with exit code 0

ilustrar

Si usa este método para marcar casos de prueba, debe seguir estrictamente el formato que escribí. La sintaxis es pytest.param(valor, id='algo')

Resumir

Este es el caso de la implementación basada en datos en Pytest

maestro

1. Los decoradores y los casos de prueba usan una sola variable para recibir múltiples conjuntos de datos y múltiples variables para recibir múltiples métodos de acceso a datos

2. Cómo pasar datos y acceder a datos cuando diferentes formularios de datos de prueba (lista de tuplas anidadas, listas, diccionarios, etc.)

3. La diferencia entre el decorador que decora la clase de prueba y la función de prueba: al decorar la clase de prueba, todos los métodos de la clase deben recibir y enviar datos de prueba, de lo contrario, se informará un error.Es más flexible al decorar la función de prueba Si la función no usa datos, no necesita ser decorada

4. Para la legibilidad de los resultados de salida, puede optar por utilizar el parámetro ids y definir el valor del parámetro id en los datos de prueba para identificar el caso de prueba

Aviso

1. El primer parámetro del decorador es una lista de parámetros de cadena "a, b, c" no se puede escribir como "a", "b", "c"

2. ids es una lista de cadenas y su longitud debe ser coherente con la longitud de la lista de datos de prueba

¡Gracias a todos los que leyeron mi artículo con atención! ! !

Personalmente, clasifiqué algunos materiales técnicos que compilé en mi carrera de prueba de software en los últimos años, que incluyen: libros electrónicos, módulos de currículum, varias plantillas de trabajo, libros de entrevistas, proyectos de autoaprendizaje, etc. Bienvenidos a todos a hacer clic en la tarjeta de presentación a continuación para obtenerla gratis, no se la pierdan.

   Grupo de intercambio de aprendizaje de pruebas automatizadas de Python: un conjunto completo de materiales de aprendizaje de reanudación de entrevistas de pruebas automatizadas para obtener Haga clic en el enlace para unirse al chat grupal [intercambio de pruebas automatizadas de Python]: http://qm.qq.com/cgi-bin/qm/ qr?_wv=1027&k=DhOSZDNS -qzT5QKbFQMsfJ7DsrFfKpOF&authKey=eBt%2BF%2FBK81lVLcsLKaFqnvDAVA8IdNsGC7J0YV73w8V%2FJpdbby66r7vJ1rsPIifg&noverify=0&group_code=19 8408628

Supongo que te gusta

Origin blog.csdn.net/MXB_1220/article/details/131755708
Recomendado
Clasificación