2011-08-16 7 views
7

Estoy escribiendo un módulo que implica analizar html para datos y crear un objeto a partir de él. Básicamente, quiero crear un conjunto de casos de prueba donde cada caso es un archivo html emparejado con un archivo de objeto encurtido dorado/esperado.¿Manera correcta de organizar los casos de prueba que involucran un archivo de datos para cada caso de prueba?

Como puedo efectuar cambios en el analizador, me gustaría ejecutar este conjunto de pruebas para asegurar que cada página HTML se analiza para igualar el archivo 'de oro' (esencialmente una suite de regresión)

puedo ver cómo codifique esto como un caso de prueba único, donde cargaría todos los pares de archivos desde algún directorio y luego iteraría a través de ellos. Pero creo que esto terminaría siendo reportado como un solo caso de prueba, pase o no. Pero quiero un informe que diga, por ejemplo, 45/47 páginas analizadas con éxito.

¿Cómo puedo organizar esto?

Respuesta

3

he hecho cosas similares con el marco unittest escribiendo una función que crea y devuelve una prueba clase. Esta función puede tomar los parámetros que desee y personalizar la clase de prueba en consecuencia. También puede personalizar el atributo __doc__ de la (s) función (es) de prueba para obtener mensajes personalizados al ejecutar las pruebas.

Rápidamente sorprendí al siguiente código de ejemplo para ilustrar esto. En lugar de realizar pruebas reales, utiliza el módulo random para suspender algunas pruebas con fines de demostración. Cuando se crean, las clases se insertan en el espacio de nombres global para que una llamada al unittest.main() las recoja. Dependiendo de cómo ejecute sus pruebas, es posible que desee hacer algo diferente con las clases generadas.

import os 
import unittest 

# Generate a test class for an individual file. 
def make_test(filename): 
    class TestClass(unittest.TestCase): 
     def test_file(self): 
      # Do the actual testing here. 
      # parsed = do_my_parsing(filename) 
      # golden = load_golden(filename) 
      # self.assertEquals(parsed, golden, 'Parsing failed.') 

      # Randomly fail some tests. 
      import random 
      if not random.randint(0, 10): 
       self.assertEquals(0, 1, 'Parsing failed.') 

     # Set the docstring so we get nice test messages. 
     test_file.__doc__ = 'Test parsing of %s' % filename 

    return TestClass 

# Create a single file test. 
Test1 = make_test('file1.html') 

# Create several tests from a list. 
for i in range(2, 5): 
    globals()['Test%d' % i] = make_test('file%d.html' % i) 

# Create them from a directory listing. 
for dirname, subdirs, filenames in os.walk('tests'): 
    for f in filenames: 
     globals()['Test%s' % f] = make_test('%s/%s' % (dirname, f)) 

# If this file is being run, run all the tests. 
if __name__ == '__main__': 
    unittest.main() 

Un análisis de la muestra:

$ python tests.py -v 
Test parsing of file1.html ... ok 
Test parsing of file2.html ... ok 
Test parsing of file3.html ... ok 
Test parsing of file4.html ... ok 
Test parsing of tests/file5.html ... ok 
Test parsing of tests/file6.html ... FAIL 
Test parsing of tests/file7.html ... ok 
Test parsing of tests/file8.html ... ok 

====================================================================== 
FAIL: Test parsing of tests/file6.html 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "generic.py", line 16, in test_file 
    self.assertEquals(0, 1, 'Parsing failed.') 
AssertionError: Parsing failed. 

---------------------------------------------------------------------- 
Ran 8 tests in 0.004s 

FAILED (failures=1) 
3

El marco de prueba de nariz es compatible con esto. http://www.somethingaboutorange.com/mrl/projects/nose/

también ver aquí: How to generate dynamic (parametrized) unit tests in python?

Esto es lo que yo haría (no probado):

files = os.listdir("/path/to/dir") 

class SomeTests(unittest.TestCase): 

    def _compare_files(self, file_name): 
     with open('/path/to/dir/%s-golden' % file_name, 'r') as golden: 
      with open('/path/to/dir/%s-trial' % file_name, 'r') as trial:  
       assert golden.read() == trial.read()  


def test_generator(file_name): 
    def test(self): 
     self._compare_files(file_name): 
    return test 

if __name__ == '__main__': 
    for file_name in files: 
     test_name = 'test_%s' % file_name 
     test = test_generator(file_name) 
     setattr(SomeTests, test_name, test) 
    unittest.main() 
+0

Bueno, obviamente no pude hacer eso ... pero cualquier solución decente no debería codificar los números/nombres de archivos/casos de prueba. Debería cargar lo que esté en un directorio, lista de archivos, etc. – Ian

+0

Actualizado para ser útil. – nottombrown

+0

mucho mejor. ¡Gracias! – Ian

Cuestiones relacionadas