Hablar sobre cómo mejorar la estabilidad y la mantenibilidad de las pruebas automatizadas

Tabla de contenido

Prefacio:

Decorador y mecanismo de reintento de error

¿Qué son los decoradores?

Escriba un decorador de reintento en caso de error

Implementación del mecanismo de reintento de error en pytest

Jerarquía de casos de prueba en Allure

¿Por qué utilizar un mecanismo en capas?

Decorador de Allure @step


Prefacio:

La estabilidad y la mantenibilidad de las pruebas automatizadas son los factores clave para garantizar la eficacia y la continuidad del trabajo de prueba. La estabilidad se refiere a la confiabilidad y consistencia de las pruebas, mientras que la mantenibilidad se refiere a la legibilidad, escalabilidad y mantenibilidad de los scripts de prueba.

Decorador y mecanismo de reintento de error

Cuando se trata de estabilidad, lo que tengo que decir es el mecanismo de "reintento de error". En las pruebas automatizadas, dado que el entorno es generalmente un entorno de prueba, a menudo hay varias convulsiones que afectan los resultados de la prueba. La estabilidad trae desafíos. Después de todo, nadie quiere que sus scripts tengan varios problemas desconocidos durante todo el día y, a menudo, este tipo de convulsiones ambientales (generalmente la velocidad de respuesta de la página frontal y la velocidad de respuesta de la interfaz de fondo) traen El impacto es temporal. puede fallar en el último segundo, pero puede ejecutarlo nuevamente en el próximo segundo. En este caso, si tiene un mecanismo de reintento de error, al menos puede dejar que su script esté sano y salvo, hablemos de cómo hacerlo. en detalle.

¿Qué son los decoradores?

Debido a que nuestro enfoque se basa en los decoradores, antes de hacerlo, presentemos brevemente a los decoradores.

Decorador, en la forma de agregar una declaración como @xxx sobre el método (o clase), si hemos implementado un decorador llamado reintentar, entonces queremos usarlo así:

@retry
def test_login():
    print("test")
    error = 1/0

Si reintentar implementa un error y vuelve a intentarlo (hablaré sobre cómo implementarlo más adelante), entonces, si se usa de esta manera, el caso test_login se ejecutará nuevamente cuando ocurra un error.

Es increíble, echemos un vistazo al código que implementa el reintento:

def retry(func):
    def warp():
        for time in range(3):
            try:
                func()
            except:
                pass
    return warp

En cuanto al resultado, se ejecuta el siguiente código:

@retry
def test_login():
    print("test")
    error = 1/0

test_login()

y ejecutar:

retry(test_login)()

Es equivalente. De esto podemos ver que el decorador es en realidad una función en esencia. Esta función recibe otras funciones (o clases) como parámetros. Al llamar o modificar esta función (o clase), la función original para modificar la funcionalidad de esa funcion

Hay otro punto de conocimiento aquí. ¿Alguna vez has pensado en cómo la función warp() dentro de reintentar hace que se ejecute el parámetro func? Es la función warp la que ejecuta el retorno de la función reintentar, y warp no acepta el parámetro func.

Este es el concepto de cierre en python. El cierre se refiere a una función con su propio contexto en tiempo de ejecución, como la función warp aquí. Cuando se ejecuta, viene con la función func que le pasó la función de nivel superior reintentar, así que puede Func se procesa y se genera en tiempo de ejecución.

Después de comprender los decoradores y los cierres, es fácil implementar el mecanismo de reintento de error para los casos de prueba a continuación.

Escriba un decorador de reintento en caso de error

Ahora, intentemos escribir un decorador de reintento de error para casos de prueba, el código es el siguiente:

def retry(times=3,wait_time=10):
    def warp_func(func):
        def fild_retry(*args,**kwargs):
            for t in range(times):
                try:
                    func(*args,**kwargs)
                    return 
                except:
                    time.sleep(wait_time)
        return fild_retry
    return warp_func

Este decorador puede implementar un mecanismo de reintento para el caso de prueba pasando el número de reintentos (veces) y el tiempo de espera de reintento (wait_time).

Implementación del mecanismo de reintento de error en pytest

En el marco de prueba pytest, se implementó la estrategia de reintento de error. Primero debemos instalar dicho complemento y ejecutar el siguiente comando en cmd para instalar:

pip install pytest-rerunfailures

Si necesita aplicar este mecanismo a todos los casos de uso, utilice el siguiente comando al ejecutar (repeticiones es el número de reintentos):

pytest --reruns 5

para ejecutar su caso de uso;

Si desea agregar el tiempo de espera para el reintento de error, utilice el siguiente comando (reruns-delay es el tiempo de espera):

pytest --reruns 5 --reruns-delay 1

para ejecutar su caso de uso;

Si desea aplicar la estrategia de reintento solo a algunos casos de prueba, puede usar el decorador:

@pytest.mark.flaky(reruns=5, reruns_delay=2)

Por ejemplo:

@pytest.mark.flaky(reruns=5, reruns_delay=2)
def test_example():
    import random
    assert random.choice([True, False])

Para una introducción más detallada, consulte la documentación oficial  .

Jerarquía de casos de prueba en Allure

Acabamos de implementar el mecanismo de reintento de error del caso de uso, pero esto solo resuelve la estabilidad del script en un entorno inestable; si desea que el script sea más fácil de mantener, además del caso de uso del modo po tradicional y la separación de elementos , También podemos introducir un mecanismo de estratificación de casos de prueba.

¿Por qué utilizar un mecanismo en capas?

El modo po tradicional solo realiza la separación de casos de uso y elementos, lo que garantiza la mantenibilidad de los casos de uso en un cierto nivel. Al menos, no hay necesidad de preocuparse por cambiar elementos para que los casos de uso no sean válidos en todas partes; pero esto no es suficiente. Por ejemplo, ahora hay tres casos, todos incluyen los siguientes pasos: iniciar sesión, abrir el banco de trabajo e ingresar al centro personal; luego, si no hay capas, estos tres casos de uso escribirán los tres pasos. Si un día la página cambia y uno de los pasos debe cambiarse, luego debe ir a cada caso de uso para actualizar ese paso.

Y si consideramos los casos de uso como bloques de construcción, y los tres pasos de iniciar sesión, abrir el banco de trabajo e ingresar al centro personal son solo bloques de construcción, entonces cuando escribimos casos de uso, solo necesitamos construir los bloques de construcción cuando use este paso; si un día, se cambian los pasos de uno de los bloques de construcción, solo necesita cambiar el contenido de este bloque de construcción, en lugar de cambiarlo en cada caso de uso que usa este bloque de construcción.

Esto mejora en gran medida la reutilización y la capacidad de mantenimiento de los casos de uso, razón por la cual se adopta el mecanismo de capas. A continuación, presentaré el mecanismo de capas en Allure para analizar cómo implementarlo.

Decorador de Allure @step

​En allure, podemos completar el mecanismo de capas a través del decorador @step. Específicamente, cuando decora un método con @step, cuando ejecuta este método en el caso de uso, el método decorado se mostrará en el informe; y @step admite la estructura anidada, lo que significa que puede construir sus pasos como bloques de construcción, y todos se mostrarán en el informe uno por uno.

Lo siguiente usa directamente el ejemplo oficial de allure como ejemplo:

import allure
import pytest

from .steps import imported_step


@allure.step
def passing_step():
    pass


@allure.step
def step_with_nested_steps():
    nested_step()


@allure.step
def nested_step():
    nested_step_with_arguments(1, 'abc')


@allure.step
def nested_step_with_arguments(arg1, arg2):
    pass


def test_with_imported_step():
    passing_step()
    imported_step()


def test_with_nested_steps():
    passing_step()
    step_with_nested_steps()

Después de ejecutar este caso, el informe se ve así:

imagen

Como puede ver,

test_with_nested_steps consta de dos métodos: pass_step() y step_with_nested_steps();

Y step_with_nested_steps() se compone de nested_step();

nested_step() consta de nested_step_with_arguments(1, 'abc');

De esta forma, los casos de prueba se forman como bloques de construcción; y en el informe, la estructura anidada de pasos también está claramente marcada.

​De esta manera, podemos componer casos de prueba a través de un método de decoración @step tras otro; al mismo tiempo, el informe también admitirá visualización jerárquica; completando así nuestro mecanismo jerárquico.

Para obtener más detalles sobre @step, consulte la documentación oficial.

  Como alguien que ha estado aquí, también espero que todos eviten algunos desvíos.

Aquí compartiré contigo algunas necesidades del camino a seguir en las pruebas automatizadas, con la esperanza de ayudarte.

(materiales relacionados con pruebas de software, materiales relacionados con pruebas automatizadas, preguntas y respuestas técnicas, etc.)

¡Creo que puede hacerte progresar mejor!

Haga clic en la pequeña tarjeta de abajo

 

Supongo que te gusta

Origin blog.csdn.net/Free355/article/details/131764958
Recomendado
Clasificación