2009-06-11 10 views
21

En pruebas de unidad I necesidad de cargar accesorios, como a continuación:¿Cómo cargar los accesorios solo una vez en las pruebas de django unit?

class TestQuestionBankViews(TestCase): 

     # Load fixtures 
     fixtures = ['qbank'] 

     def setUp(self):       
      login = self.client.login(email="[email protected]",password="welcome")   


     def test_starting_an_exam_view(self):    
      candidate = Candidate.objects.get(email="[email protected]") 
      .......etc 


     def test_review_view(self): 
      self.assertTrue(True)    
      ......... 

     def test_review_view2(self): 
      self.assertTrue(True) 
      ......... 

Problema:

Estos accesorios están cargando para cada prueba, es decir, antes test_review_view, test_review_view2, etc ., ya que Django vacía la base de datos después de cada prueba.

Este comportamiento está provocando que las pruebas tarden mucho tiempo en completarse.

¿Cómo puedo evitar la carga de este dispositivo redundante?

¿Hay alguna manera de cargar dispositivos en setUp y lavarlos cuando termine la clase de prueba, en lugar de enjuagarlos entre cada prueba?

+0

oh ......... Creo que puedo resolver esto utilizando el accesorio intial_data y heredando "unittest.Testcase" en lugar de "test.TestCase"? ¿Algún otro pensamiento? –

Respuesta

3

Me encontré con el mismo problema. En general, no hay una manera realmente buena de hacer eso usando el corredor de prueba de django. Usted podría estar interesado en esto thread

Dicho esto, si todas las cajas de prueba utilizan el mismo dispositivo, y no modifican los datos de ninguna manera, entonces el uso de initial_data funcionaría.

+0

Gracias por el puntero, & Sí (no pensé en esto antes) podemos usar intial_data solo si cada caso de prueba no modifica la base de datos –

+0

decidí usar unittest.TestCase con intial_data. ¿Alguna idea sobre cómo obtener todas las comodidades proporcionadas por django.test.TestCase? –

1

Tuve un problema similar una vez y terminé escribiendo mi propio corredor de prueba. En mi caso initial_data no era el lugar correcto ya que initial_data se cargaría durante syncdb, algo que no quería. Anulé los métodos setup_ y teardown_test_environment para cargar mi dispositivo personalizado antes de que se ejecutara el conjunto de pruebas y para eliminarlo una vez hecho.

16

Usando django-nose y un poco de código, puede hacer exactamente lo que usted solicitó. Con django-nose, puede tener funciones de configuración y desmontaje por paquete, por módulo y por clase. Eso le permite cargar sus dispositivos en una de las funciones de configuración superiores e inhabilitar el reinicio de django.test.TestCase de los dispositivos entre las pruebas.

Aquí es un archivo de prueba de ejemplo:

from django.test import TestCase 
from django.core import management 

    def setup(): 
     management.call_command('loaddata', 'MyFixture.json', verbosity=0) 

    def teardown(): 
     management.call_command('flush', verbosity=0, interactive=False) 

    class MyTestCase(TestCase): 

     def _fixture_setup(self): 
      pass 

     def test_something(self): 
      self.assertEqual(1, 1) 

en cuenta que la instalación y el desmontaje están fuera de la clase. La configuración se ejecutará antes de todas las clases de prueba en este archivo, y el desmontaje se ejecutará después de todas las clases de prueba.

Dentro de la clase, verá el método def _fixture_setup (auto). Esto anula la función que restablece la base de datos entre cada prueba.

Tenga en cuenta que si sus pruebas escriben algo en la base de datos, esto podría invalidar sus pruebas. Por lo tanto, cualquier otra prueba que necesite dispositivos recargados para cada prueba debe colocarse en un archivo de prueba diferente.

+0

+1 para una solución funcional que en realidad deja espacio para un enfoque diferente de usar initial_data.json/yaml. (Utilizo un comando de administración personalizado y un script que llama a Django ORM para crear mis datos iniciales. Esto me permite integrarlo perfectamente.) Esta debería ser la respuesta aceptada, ¡me ayudó mucho! – hangtwenty

+1

¡Gran solución! Una cosa que descubrí es bastante útil. Si no coloca el método def _fixture_setup (self) y permite que el Django TestCase se cierre como de costumbre, cualquier cambio en la base de datos realizado dentro de un caso de prueba no afectará al siguiente. Esto se debe a que al inicio de un caso de prueba, se inicia una transacción de base de datos, y durante la fase de corte, el caso de prueba realizará una reversión de db para restablecer el estado de la base de datos. ¡Ignorar el def _fixture_setup() te dará las apuestas de ambos mundos! – LeeMobile

9

O uso setUpModule:

def setUpModule(): 
    print 'Module setup...' 

def tearDownModule(): 
    print 'Module teardown...' 

class Test(unittest.TestCase): 
    def setUp(self): 
     print 'Class setup...' 

    def tearDown(self): 
     print 'Class teardown...' 

    def test_one(self): 
     print 'One' 

    def test_two(self): 
     print 'Two' 

impresiones:

Creating test database for alias 'default'... 
Module setup... 
Class setup... 
One 
Class teardown... 
Class setup... 
Two 
Class teardown... 
Module teardown... 
+1

Esto solo funciona si cada prueba en el módulo usa ese mismo accesorio. En otras palabras, te obliga a poner pruebas en un módulo dado por el dispositivo que usan, en lugar de lo que prueban. –

0

django-nariz ofrece una solución a este problema readymade: simplemente subclase django_nose.FastFixtureTestCase.

Además, django-nose admite el agrupamiento de accesorios, lo que puede acelerar aún más tus pruebas cargando solo cada conjunto único de accesorios una vez por prueba. Después de haber subclasificado FastFixtureTestCase donde corresponda, ejecute el corredor de prueba django-nose utilizando la opción --with-fixture-bundling.

Consulte django-nose on pypi para obtener más información.

4

Si no desea instalar un nuevo paquete solo para este fin, puede combinar Tom Wainwright's solution y mhost's solution.

En su testfile, añadir estas funciones fuera de las clases:

from django.core.management import call_command 

def setUpModule(): 
    call_command(
     'loaddata', 
     'path_to_fixture.json', 
     verbosity=0 
    ) 

def tearDownModule(): 
    call_command('flush', interactive=False, verbosity=0) 

Si no quieren tener estos accesorios cargados en la base de datos de todos los casos de prueba, split the test into multiple files mediante la creación de un nuevo directorio en el aplicación llamada tests, añadir un archivo vacío __init__.py para contar Python que se trata de un paquete, y añadir los archivos de prueba con nombres de archivo que comienzan con test, ya que el corredor buscará archivos que coincidan con el patrón test*.py

3

por lo que vale la pena , y dado que no hay una respuesta aceptada, Django 1.8 ahora ofrece esta funcionalidad lista para usar, siempre que esté utilizando un back-end de base de datos que admita transacciones.

También agrega el método TestCase.setUpTestData() para la creación manual de datos de prueba una vez por clase de TestCase.

Ver the Django 1.8 release notes.

Cuestiones relacionadas