Comprensión profunda de cómo funciona el complemento pytest-repeat

Como se mencionó en el artículo anterior, pytest_repeat¿cómo se implementa la función específica del complemento? Creo que después de comprender el complemento en detalle, otros complementos de terceros podrán comprender rápidamente su mecanismo operativo interno. 

pytest_repeatCómo implementar casos de uso recurrentes sin utilizar complementos

La forma más estúpida, por supuesto, es ejecutarlo varias veces, pero obviamente esto no es lo que necesitamos. En el artículo de revisión de decoradores , revisamos los puntos de conocimiento relacionados con los decoradores, sabiendo que los decoradores pueden agregar funciones dinámicamente o modificar el comportamiento de las funciones sin modificar el código original. Obviamente, aquí podemos usar decoradores para lograr funciones repetidas.

def repeat(nums: int = 2):
  
    def wrapper(func):
        @functools.wraps(func)
        def decorator(*args, **kwargs):
            for i in range(nums):
                func(*args, **kwargs)
        return decorator
    return wrapper

Este código es fácil de entender: define un decorador con parámetros personalizados, que indican la cantidad de veces que se ejecuta la función dentro del decorador. De esta manera, el uso del decorador en el caso de uso @repeat()puede lograr el propósito de ejecutar el caso de uso repetidamente. Pero el resultado estadístico sigue siendo 1 caso de uso. ¿Los estudiantes que lo han usado pytest_repeatsaben que sus resultados estadísticos son casos de uso múltiples? Cómo hacerlo, descúbrelo a través del código fuente.

pytest_repeatCómo lograr una ejecución repetida

Acceso directo al código fuente

Interpretación del código fuente

def pytest_addoption(parser):
    parser.addoption(
        '--count',
        action='/pytest-dev/pytest-repeat/blob/v0.9.1/store',
        default=1,
        type=int,
        help='Number of times to repeat each test')
    parser.addoption(
        '--repeat-scope',
        action='/pytest-dev/pytest-repeat/blob/v0.9.1/store',
        default='function',
        type=str,
        choices=('function', 'class', 'module', 'session'),
        help='Scope for repeating tests')

Este código define dos opciones de línea de comando:

  • --count: Se utiliza para especificar el número de veces que se repetirá cada caso de prueba. action=storeIndica almacenar el valor en el argumento de la línea de comando.
  • --repeat-scope: Se utiliza para especificar el alcance de los casos de prueba repetidos; puede elegir function, o . El valor predeterminado es . Indica almacenar el valor en el argumento de la línea de comando.classmodulesessionfunctionaction=store

Ambas opciones se parser.addoptionagregan al analizador de línea de comandos de pytest mediante el método.

Al ejecutar pytest y especificar --countparámetros --repeat-scope, pytest-repeatel complemento tomará esos parámetros y generará automáticamente múltiples instancias de ejecución repetidas para el caso de prueba.

Por ejemplo, si ejecuta el siguiente comando:

pytest --count=2 --repeat-scope=function

pytest-repeatEl caso de prueba se ejecutará automáticamente dos veces cuando se ejecute el caso de prueba test_my_function.


action=storees argparseun argumento en el módulo que especifica cómo se maneja el valor de la opción durante el análisis de la línea de comandos. Específicamente, action=storesignifica almacenar el valor de la opción en un argumento de línea de comando.

Cuando se utiliza parser.addoptionel método para agregar opciones al analizador de línea de comandos, al especificar action=store, el valor de la opción se almacenará en el resultado analizado, que se puede obtener a través del atributo correspondiente.

Por ejemplo, cuando se ejecuta el comando pytest, los valores de --countlas --repeat-scopeopciones especificadas se almacenan en los argumentos de la línea de comandos. Puede request.config.getoptionacceder a estos valores almacenados utilizando el método, por ejemplo:

def test_example(request):
    count = request.config.getoption('--count') 
    # count = request.config.option.count 这样也能获取
    repeat_scope = request.config.getoption('--repeat-scope')
    # repeat_scope = request.config.option.repeat_scope
    # 使用获取到的值进行后续操作

En el código de muestra anterior, los valores de y request.config.getoptionse obtienen de los parámetros de la línea de comando usando el método y se almacenan en las variables y respectivamente.--count--repeat-scopecountrepeat_scope

Resumen: action=storees argparseun parámetro en el módulo que especifica almacenar el valor de la opción en el argumento de la línea de comandos. En pytest, request.config.getoptionlos valores de las opciones almacenados en los argumentos de la línea de comandos se pueden obtener mediante el método.


def pytest_configure(config):
    config.addinivalue_line(
        'markers',
        'repeat(n): run the given test function `n` times.')

Esta función se llama durante la fase de configuración de pytest config.addinivalue_line()para agregar indicadores personalizados 'repeat(n)'a la lista de indicadores de pytest llamando a . 'repeat(n)'Se pueden utilizar banderas para especificar el número de veces que se debe repetir una función de prueba.


@pytest.fixture
def __pytest_repeat_step_number(request):
    marker = request.node.get_closest_marker("repeat")
    count = marker and marker.args[0] or request.config.option.count
    if count > 1:
        try:
            return request.param
        except AttributeError:
            if issubclass(request.cls, TestCase):
                warnings.warn(
                    "Repeating unittest class tests not supported")
            else:
                raise UnexpectedError(
                    "This call couldn't work with pytest-repeat. "
                    "Please consider raising an issue with your usage.")

Esta función de dispositivo se utiliza para obtener el número de paso de repetición actual. Primero verifica si la función de prueba está 'repeat'decorada con una etiqueta y obtiene el recuento de repeticiones de la etiqueta. Si no está marcado, los argumentos de la línea de comandos se utilizan --countcomo valores predeterminados.


@pytest.hookimpl(trylast=True)
def pytest_generate_tests(metafunc):
    count = metafunc.config.option.count
    m = metafunc.definition.get_closest_marker('repeat')
    if m is not None:
        count = int(m.args[0])
    if count > 1:
        metafunc.fixturenames.append("__pytest_repeat_step_number")
        def make_progress_id(i, n=count):
            return '{0}-{1}'.format(i + 1, n)
        scope = metafunc.config.option.repeat_scope
        metafunc.parametrize(
            '__pytest_repeat_step_number',
            range(count),
            indirect=True,
            ids=make_progress_id,
            scope=scope
        )

Esta pytest_generate_testsfunción de enlace se llamará después de que pytest haya recopilado todas las funciones de prueba y está configurada trylast=Truepara garantizar que se ejecute después de que otras funciones de enlace hayan terminado de ejecutarse.

  1. Primero, el código obtiene metafunc.config.option.countel valor de , que representa la cantidad de veces que se repite el caso de prueba.
  2. Luego, el código llama metafunc.definition.get_closest_marker('repeat')para saber si el caso de prueba tiene un repeatmarcador marcado como .
  3. Si hay repeatun marcador de, obtenga el número de ejecuciones repetidas del marcador y asígnelo a countla variable.
  4. A continuación, el código metafunc.fixturenames.append("__pytest_repeat_step_number")agrega un __pytest_repeat_step_numbernombre de dispositivo a metafuncla lista de dispositivos agregando un dispositivo llamado .
  5. Posteriormente, se define una función auxiliar make_progress_idpara generar identificadores de progreso para casos de prueba.
  6. Dependiendo del metafunc.config.option.repeat_scopevalor de , se determina el alcance de la ejecución repetida.
  7. Finalmente, metafunc.parametrizelos casos de prueba se generan dinámicamente llamando a . Toma range(count)como parámetro el número de pasos a generar para repetir, y indirect=Truelos conjuntos se llamarán indirectamente cuando se cargue el aparato. Al mismo tiempo, la función y el alcance de generación del identificador de progreso definidos previamente se utilizan para establecer otras opciones de parametrización.

Se puede ver que finalmente se logra mediante parametrización, por lo que las ejecuciones repetidas pueden considerarse como casos de uso múltiples.

por fin

Creo que todavía tienes muchas preguntas después de verme, ¿ fixturequé es? mark¿Qué es? ¿Cuáles son los parámetros request? ¿Cuál es la función del gancho? parametrize¿Qué es la parametrización? Estas preguntas se pueden mantener por ahora. En este contenido, hablamos principalmente sobre pytest_repeatla lógica de implementación específica y luego llevamos a muchos puntos de conocimiento. No se preocupe, los eliminaremos uno por uno más adelante.

Finalmente: el video tutorial completo de prueba de software a continuación se ha ordenado y subido, y los amigos que lo necesiten pueden obtenerlo ellos mismos [Garantizado 100% gratis]

Documentación de la entrevista de prueba de software

Debemos estudiar para encontrar un trabajo bien remunerado. Las siguientes preguntas de la entrevista son los últimos materiales de entrevista de empresas de Internet de primer nivel como Ali, Tencent y Byte, y algunos jefes de Byte han dado respuestas autorizadas. Termine este conjunto Los materiales de la entrevista Creemos que todos pueden encontrar un trabajo satisfactorio.

Supongo que te gusta

Origin blog.csdn.net/wx17343624830/article/details/132668577
Recomendado
Clasificación