es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Pytest: usa un generador para mark.parametrize.

Tengo una base de datos mongo con una colección muy grande en la que necesito realizar pruebas con Pytest. Estoy intentando hacerlo por la ruta habitual usando el decorador mark.parametrize, pero con el objeto Cursor de pymongo.cursor:

def get_all_data():
    return db["collection"].find({}) # consulta para recuperar todos los documentos de la colección

@pytest.mark.parametrize("doc", get_all_data())
def test_1(doc):
    assert doc["val"] == 1
    ....

El problema con este código es que Pytest en la etapa de recolección antes de ejecutar las pruebas convierte automáticamente el generador en una lista. No quiero esto por 2 razones:
1. Es muy lento debido a que la colección es muy grande.
2. Desbordamiento de pila: de todas maneras, no hay suficiente RAM para cargar todos estos datos.

Esto significa que no puedo usar mark.parametrize, sin embargo, ¿cómo puedo seguir usando un generador para ejecutar pruebas de 1 en 1 sin cargar todo inmediatamente en la memoria? ¿Es posible con Pytest?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Sí, es posible utilizar un generador para ejecutar pruebas una por una con Pytest y no cargar todo inmediatamente en memoria. Una forma de hacer esto es utilizando la función de fixture “indirect” de pytest.

    Aquí hay un ejemplo de código:

    import pytest
    from pymongo import MongoClient
    
    @pytest.fixture(scope="function")
    def get_doc(request):
        collection = MongoClient()["database"]["collection"]
        cursor = collection.find({}) # consulta para recuperar todos los documentos de la colección
        index = request.param # obtener el índice del generador
        return cursor[index]
    
    @pytest.mark.parametrize("index", range(100), indirect=True)
    def test_doc(get_doc):
        assert get_doc["val"] == 1
    

    En este fragmento de código, hemos definido una función de fixture llamada get_doc que toma un objeto “request” que contiene información sobre la prueba actual. La función de fixture “get_doc” abre una conexión con MongoDB, recupera un objeto “cursor” que contiene todos los documentos de la colección, y devuelve un solo documento basado en el índice que se pasa a través de request.param.

    También hemos utilizado el decorador pytest.mark.parametrize para especificar que queremos parametrizar la prueba con 100 índices generados por la función range. Al pasar indirect=True a mark.parametrize, le decimos a Pytest que utilice la función de fixture “get_doc” para generar los parámetros de la prueba.

    Utilizando este enfoque, podemos ejecutar pruebas una por una sin cargar todo en memoria de una sola vez. Cada prueba se ejecuta con una consulta separada a MongoDB y sólo recupera un documento de la colección. Este enfoque debería ser mucho más rápido y menos exigente en cuanto a memoria que cargar todos los documentos en memoria de una sola vez.

Comments are closed.