Tabla de contenido
Identificación personalizada para identificación
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