2011-02-07 17 views
15

Pregunta primero, luego una explicación si estás interesado.generar pruebas de py.test en python

En el contexto de py.test, ¿cómo puedo generar un gran conjunto de funciones de prueba a partir de un pequeño conjunto de plantillas de funciones de prueba?

Algo así como:

models = [model1,model2,model3] 
data_sets = [data1,data2,data3] 

def generate_test_learn_parameter_function(model,data): 
    def this_test(model,data): 
     param = model.learn_parameters(data) 
     assert((param - model.param) < 0.1) 
    return this_test 

for model,data in zip(models,data_sets): 
    # how can py.test can see the results of this function? 
    generate_test_learn_parameter_function(model,data) 

Explicación:

estoy tratando de entrar en la unidad de pruebas. Codigo para 'ciencia', porque estoy escribiendo código que creo que es matemáticamente complicado pero no tan malo desde el punto de vista de la programación, es decir, tengo cinco funciones para probar. El hecho de que vengo de 'ciencia' significa que soy bastante nuevo para las pruebas unitarias, pero me he convencido de que es lo que se debe hacer.

El código que estoy escribiendo toma una estructura de modelo, algunos datos y aprende los parámetros del modelo. Así que mi unidad de prueba consiste en un conjunto de estructuras de modelos y conjuntos de datos pregenerados, y luego un conjunto de aproximadamente 5 tareas de aprendizaje automático para completar en cada estructura + datos.

Así que si doy la clave para esto, necesito una prueba por modelo por tarea. Cada vez que se me ocurre un nuevo modelo, necesito copiar y pegar las 5 tareas, cambiando la estructura en escabeche + datos a los que estoy apuntando. Esto me parece una mala práctica. Idealmente, lo que me gustaría es 5 funciones de plantilla que definan cada una de mis 5 tareas y luego escupir las funciones de prueba para obtener una lista de las estructuras que especifico.

La búsqueda en Google me lleva a a) fábricas ob) cierres, los cuales atormentan mi cerebro y me sugieren que debe haber una manera más fácil, ya que este problema debe ser enfrentado regularmente por programadores adecuados. Entonces, ¿está ahí?


EDITAR: Así que aquí está cómo resolver este problema.

def pytest_generate_tests(metafunc): 
    if "model" in metafunc.funcargnames: 
     models = [model1,model2,model3] 
     for model in models: 
      metafunc.addcall(funcargs=dict(model=model)) 

def test_awesome(model): 
    assert model == "awesome" 

¡Esto aplicará la prueba test_awesome a cada modelo en mi lista de modelos! Gracias @dfichter!

(NOTA: afirmar que siempre pasa, por cierto)

+0

Por lo general, es una mala idea para generar dinámicamente código de prueba como esa. Porque entonces tiene que escribir pruebas para el código de prueba, etc. 'copie y pegue las 5 tareas' Creo que esto muestra que en lugar de generar código nuevo o copiar y pegar, puede encontrar aspectos comunes que sus funciones pueden probar sin saber exactamente qué estoy probando – Falmarri

+2

Por el momento estoy escribiendo pruebas que se ven como def test_learn: para modelo en modelos: assert (error

+1

@Falmarri: http://en.wikipedia.org/wiki/Copy_and_paste_programming Por favor evítelo a toda costa. – lpapp

Respuesta

15

buenos instintos. py.test es compatible exactamente con lo que está hablando con su gancho pytest_generate_tests(). Lo explican here.

+0

Esto es asombroso. Voy a editar mi pregunta para agregar lo que hice al final, en caso de que alguien venga aquí buscando cosas similares ... –

+0

dfichter, ¿podría dar un ejemplo en línea al OP? – lpapp

+0

Esto es ahora un enlace roto –

4

También puede hacerlo utilizando parametrized fixtures. Mientras que los ganchos, es una API para construir complementos para Py.test, los dispositivos parametrizados son una forma generalizada de crear un dispositivo que genera múltiples valores y genera casos de prueba adicionales para ellos.

Los complementos están destinados a ser algunas características de todo el proyecto (o todo el paquete), no características específicas de casos de prueba y los dispositivos parametrizados son exactamente lo que se necesita para parametrizar algún recurso para caso (s) de prueba.

Así que su solución podría ser reescrita como que:

@pytest.fixture(params=[model1, model2, model3]) 
def model(request): 
    return request.param 

def test_awesome(model): 
    assert model == "awesome" 
Cuestiones relacionadas