¿Diferencia entre el marco de pruebas Pytest y Unittest?

Cómo distinguir entre los dos es muy simple. Como marco de prueba oficial, unittest es más básico en términos de prueba y puede usarse nuevamente para el desarrollo secundario. Al mismo tiempo, el formato de uso será más complicado; mientras que el Pytest framework es un framework de terceros, lo cual es conveniente. El punto es que es más flexible de usar y puede tener buena compatibilidad con los casos de prueba originales de estilo unittest. Al mismo tiempo, tiene más extensiones. Y los escenarios de uso se pueden agregar mediante complementos extendidos, como algunas pruebas concurrentes;

instalación de pytest

instalación de pipas :

pip install pytest

La instalación de prueba fue exitosa:

pytest --help
 
py.test --help

Verifique la versión instalada:

pytest --version

Ejemplo de prueba

Reglas de escritura de Pytest:

  • Los archivos de prueba comienzan con test_ (terminan con _test)
  • La clase probada comienza con Prueba;
  • Los métodos de prueba comienzan con test_
  • Afirmar usando afirmación básica

prueba_ejemplo.py

def count_num(a: list) -> int:
    return len(a)
 
 
def test_count():
    assert count_num([1, 2, 3]) != 3

Ejecute la prueba:

pytest test_example.py

Resultados de:

C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest>pytest test_example.py -v
================================================================= test session starts =================================================================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- d:\coding\python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collected 1 item                                                                                                                                       
 
test_example.py::test_count FAILED                                                                                                               [100%]
 
====================================================================== FAILURES =======================================================================
_____________________________________________________________________ test_count ______________________________________________________________________
 
    def test_count():
>       assert count_num([1, 2, 3]) != 3
E       assert 3 != 3
E        +  where 3 = count_num([1, 2, 3])
 
test_example.py:11: AssertionError
=============================================================== short test summary info ===============================================================
FAILED test_example.py::test_count - assert 3 != 3
================================================================== 1 failed in 0.16s ==================================================================

Observación:

  • .significa que la prueba pasó, F significa que la prueba falló;
  • -v muestra información de prueba detallada, -h muestra información de ayuda detallada para los comandos de pytest;

marca

De forma predeterminada, pytest buscará archivos de prueba que comiencen con test_ (que terminen con _test) en el directorio actual y ejecutará todas las funciones y métodos que comiencen con test_ (que terminen con _test) en el archivo;
  1. Para especificar el caso de prueba a ejecutar, puede pasar :: marca de visualización (nombre de archivo:: nombre de clase:: nombre de método) (nombre de archivo:: nombre de función)
pytest test_example3.py::test_odd
  1. Especifique algunos casos de prueba para ejecutar, puede usar -k coincidencia difusa
pytest -k example
  1. Omita el caso de prueba especificado mediante la expresión condicional pytest.mark.skip() o pytest.makr.skipif()
import pytest
 
test_flag = False
 
@pytest.mark.skip()
def test_odd():
    num = random.randint(0, 100)
    assert num % 2 == 1
 
 
@pytest.mark.skipif(test_flag is False, reason="test_flag is False")
def test_even():
    num = random.randint(0, 1000)
    assert num % 2 == 0
  1. Las excepciones que pueden generar los casos de prueba son detectadas por pytest.raises()
def test_zero():
    num = 0
    with pytest.raises(ZeroDivisionError) as e:
        num = 1/0
    exc_msg = e.value.args[0]
    print(exc_msg)
    assert num == 0
  1. Sepa de antemano que el caso de prueba fallará, pero no desea omitirlo, debe mostrar un mensaje rápido, use pytest.mark.xfail()
@pytest.mark.xfail()
def test_sum():
    random_list = [random.randint(0, 100)  for x in range(10)]
    num = sum(random_list)
    assert num < 20
  1. Se realizan múltiples conjuntos de pruebas de datos en el caso de prueba, y cada conjunto de parámetros se puede ejecutar de forma independiente una vez (puede evitar detener la prueba después de que falla la ejecución interna de un único conjunto de pruebas de datos en el caso de prueba)
@pytest.mark.parametrize('num,num2', [(1,2),(3,4)])
def test_many_odd(num: int, num2: int):
    assert num % 2 == 1
    assert num2 % 2 == 0

Firmware_ _

El firmware son algunas funciones de preprocesamiento. Pytest cargará y ejecutará estos firmwares antes (o después) de ejecutar las funciones de prueba. Los escenarios de aplicación comunes incluyen la conexión y el apagado de la base de datos (conexión y apagado del dispositivo).

fácil de usar

import pytest
 
 
@pytest.fixture()
def postcode():
    return "hello"
 
 
def test_count(postcode):
    assert postcode == "hello"
Según la explicación oficial, al ejecutar una función de prueba, primero detectará los parámetros de la función en ejecución, buscará dispositivos con el mismo nombre que los parámetros y, una vez que pytest los encuentre, ejecutará estos dispositivos y obtendrá los valores de retorno. ​​de estos dispositivos (si los hay) y los devuelve. El valor se pasa como argumento a la función de prueba;

preprocesamiento y posprocesamiento

A continuación, verifique más a fondo la declaración oficial:

import pytest
 
 
@pytest.fixture()
def connect_db():
    print("Connect Database in .......")
    yield
    print("Close Database out .......")
 
 
def read_database(key: str):
    p_info = {
        "name": "zhangsan",
        "address": "China Guangzhou",
        "age": 99
    }
    return p_info[key]
 
 
def test_count(connect_db):
    assert read_database("name") == "zhangsan"

Ejecute el resultado de la función de prueba:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 1 item
 
test_example.py::test_count Connect Database in .......
PASSED                                       [100%]Close Database out .......
 
 
============================== 1 passed in 0.07s ==============================

Observación:

  • En primer lugar, se verifica la explicación oficial a partir de los resultados: antes de ejecutar la función de prueba, pytest buscará el firmware con el mismo nombre para cargar y ejecutar;
  • Hay rendimiento en el firmware connect_db. Aquí, pytest juzgará que el código antes de la palabra clave rendimiento está preprocesado de forma predeterminada y se ejecutará antes de la prueba. El código después de rendimiento es posprocesamiento y se ejecutará después de la prueba;

El alcance
tiene una comprensión general de la función del firmware desde el frente y extrae algo de trabajo repetitivo para facilitar la reutilización. Al mismo tiempo, para controlar el firmware más finamente en el marco de pytest, el alcance se utiliza para especificar el alcance de uso del firmware (por ejemplo, en este La función de prueba en el módulo se puede ejecutar una vez y no es necesario ejecutar la función en el módulo repetidamente) Un ejemplo más específico es la conexión a la base de datos. La operación de esta conexión puede llevar mucho tiempo. Solo necesito ejecutar la función de prueba en este módulo solo una vez, no es necesario ejecutarla cada vez.

La definición de firmware es declarar la función a través del parámetro scop, los más utilizados son:

función: nivel de función, cada función de prueba se ejecutará una vez;
clase: nivel de clase, cada clase de prueba se ejecutará una vez y se pueden usar todos los métodos;
módulo: nivel de módulo, cada módulo se ejecutará una vez y las funciones y métodos dentro el módulo se puede utilizar Uso;
sesión: nivel de sesión, una prueba solo se ejecuta una vez y todas las funciones y métodos encontrados están disponibles.

import pytest
 
 
@pytest.fixture(scope="function")
def func_scope():
    print("func_scope")
 
 
@pytest.fixture(scope="module")
def mod_scope():
    print("mod_scope")
 
 
@pytest.fixture(scope="session")
def sess_scope():
    print("session_scope")
 
 
def test_scope(sess_scope, mod_scope, func_scope):
    pass
 
 
def test_scope2(sess_scope, mod_scope, func_scope):
    pass

Resultados de:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 2 items
 
test_example2.py::test_scope session_scope
mod_scope
func_scope
PASSED                                      [ 50%]
test_example2.py::test_scope2 func_scope
PASSED                                     [100%]
 
============================== 2 passed in 0.07s ==============================

Se puede ver desde aquí que el firmware del módulo y el alcance de la sesión solo se ejecuta una vez, lo que puede verificar la introducción de uso oficial.

ejecución automática

Algunas personas pueden decir, ¿por qué esto es tan problemático? El preprocesamiento se puede ejecutar automáticamente definiendo directamente setUp en el marco unittest, y el mismo marco pytest también tiene una ejecución automática similar; el firmware en el marco pytest generalmente controla la operación automática a través de parámetros uso automático.
import pytest
 
 
@pytest.fixture(scope='session', autouse=True)
def connect_db():
   print("Connect Database in .......")
   yield
   print("Close Database out .......")
 
 
def test1():
   print("test1")
 
 
def test2():
   print("test")

Resultados de:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 2 items
 
test_example.py::test1 Connect Database in .......
PASSED                                            [ 50%]test1
 
test_example.py::test2 PASSED                                            [100%]test
Close Database out .......
 
 
============================== 2 passed in 0.07s ==============================

Se puede ver en los resultados que el firmware connect_db se ejecuta automáticamente antes y después de que se ejecute la función de prueba;

parametrizar

Anteriormente se mencionó brevemente que @pytest.mark.parametrize pasó la prueba parametrizada y, al pasar parámetros sobre el firmware, debe pasar la solicitud de firmware incorporada en el marco de pytest y obtener los parámetros a través de request.param

import pytest
 
 
@pytest.fixture(params=[
    ('redis', '6379'),
    ('elasticsearch', '9200')
])
def param(request):
    return request.param
 
 
@pytest.fixture(autouse=True)
def db(param):
    print('\nSucceed to connect %s:%s' % param)
 
    yield
 
    print('\nSucceed to close %s:%s' % param)
 
 
def test_api():
    assert 1 == 1

Resultados de:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 2 items
 
test_example.py::test_api[param0] 
Succeed to connect redis:6379
PASSED                                 [ 50%]
Succeed to close redis:6379
 
test_example.py::test_api[param1] 
Succeed to connect elasticsearch:9200
PASSED                                 [100%]
Succeed to close elasticsearch:9200
 
 
============================== 2 passed in 0.07s ==============================

Aquí, se simula la conexión entre redis y elasticsearch, se carga el firmware para ejecutar automáticamente la conexión, luego se ejecuta la función de prueba y luego se desconecta.

Resumir

Para el desarrollo, ¿por qué necesita aprender a realizar pruebas automatizadas? Es muy importante ahorrar algo de tiempo de trabajo repetitivo a través de pruebas automatizadas. Al mismo tiempo, es muy importante para optimizar la estructura del código, mejorar la cobertura del código y la posterior refactorización del proyecto. Al mismo tiempo, comprender las diferencias básicas entre pytest y unittest le ayudará a elegir la herramienta de prueba que más le convenga en diferentes escenarios empresariales.
Este artículo solo presenta brevemente el uso básico de pytest. Si está interesado, puede ir al documento oficial. El documento oficial también menciona el uso de firmware integrado, escenarios de prueba comunes, etc.

Finalmente me gustaría agradecer a todos los que han leído atentamente mi artículo, la reciprocidad siempre es necesaria, aunque no es algo muy valioso, puedes quitártelo si lo necesitas:

inserte la descripción de la imagen aquí

Subprograma de entrevista de prueba de software

¡El banco de preguntas de pruebas de software superado por millones de personas! ! ! ¡Quién es quién lo sabe! ! ! El miniprograma de cuestionarios más completo de toda la red, puedes usar tu teléfono móvil para hacer los cuestionarios, en el metro o en el autobús, ¡enróllalo!

Se cubren las siguientes secciones de preguntas de la entrevista:

1. Teoría básica de pruebas de software, 2. web, aplicaciones, pruebas de función de interfaz, 3. red, 4. base de datos, 5. linux

6. web, aplicación, automatización de interfaz, 7. pruebas de rendimiento, 8. conceptos básicos de programación, 9. preguntas de la entrevista de horas, 10. preguntas de prueba abiertas, 11. pruebas de seguridad, 12. conceptos básicos de informática

Estos materiales deberían ser el almacén de preparación más completo y completo para los amigos [de pruebas de software]. Este almacén también ha acompañado a decenas de miles de ingenieros de pruebas en el viaje más difícil. ¡Espero que pueda ayudarlo a usted también! 

Supongo que te gusta

Origin blog.csdn.net/qq_48811377/article/details/132340873
Recomendado
Clasificación