2010-02-02 8 views
27

Nunca he escrito ninguna prueba en mi vida, pero me gustaría comenzar a escribir pruebas para mis proyectos de Django. He leído algunos artículos sobre pruebas y decidí intentar escribir algunas pruebas para una aplicación Django extremadamente simple o un comienzo.Escribiendo buenas pruebas para las aplicaciones de Django

La aplicación tiene dos vistas (una vista de lista, y una vista de detalle) y un modelo con cuatro campos:

class News(models.Model): 
    title = models.CharField(max_length=250) 
    content = models.TextField() 
    pub_date = models.DateTimeField(default=datetime.datetime.now) 
    slug = models.SlugField(unique=True) 

me gustaría que le muestre mi archivo tests.py y pregunte:

¿Tiene sentido?

¿Estoy probando incluso las cosas correctas?

¿Hay mejores prácticas que no sigo, y podría indicarme?

mi tests.py (que contiene 11 pruebas):

# -*- coding: utf-8 -*- 
from django.test import TestCase 
from django.test.client import Client 
from django.core.urlresolvers import reverse 
import datetime 
from someproject.myapp.models import News 

class viewTest(TestCase): 
    def setUp(self): 
     self.test_title = u'Test title: bąrekść' 
     self.test_content = u'This is a content 156' 
     self.test_slug = u'test-title-bareksc' 
     self.test_pub_date = datetime.datetime.today() 

     self.test_item = News.objects.create(
      title=self.test_title, 
      content=self.test_content, 
      slug=self.test_slug, 
      pub_date=self.test_pub_date, 
     ) 

     client = Client() 
     self.response_detail = client.get(self.test_item.get_absolute_url()) 
     self.response_index = client.get(reverse('the-list-view')) 

    def test_detail_status_code(self): 
     """ 
     HTTP status code for the detail view 
     """ 
     self.failUnlessEqual(self.response_detail.status_code, 200) 

    def test_list_status_code(self): 
     """ 
     HTTP status code for the list view 
     """ 
     self.failUnlessEqual(self.response_index.status_code, 200) 

    def test_list_numer_of_items(self): 
     self.failUnlessEqual(len(self.response_index.context['object_list']), 1)  

    def test_detail_title(self): 
     self.failUnlessEqual(self.response_detail.context['object'].title, self.test_title)  

    def test_list_title(self): 
     self.failUnlessEqual(self.response_index.context['object_list'][0].title, self.test_title) 

    def test_detail_content(self): 
     self.failUnlessEqual(self.response_detail.context['object'].content, self.test_content)  

    def test_list_content(self): 
     self.failUnlessEqual(self.response_index.context['object_list'][0].content, self.test_content) 

    def test_detail_slug(self): 
     self.failUnlessEqual(self.response_detail.context['object'].slug, self.test_slug)  

    def test_list_slug(self): 
     self.failUnlessEqual(self.response_index.context['object_list'][0].slug, self.test_slug) 

    def test_detail_template(self): 
     self.assertContains(self.response_detail, self.test_title) 
     self.assertContains(self.response_detail, self.test_content) 

    def test_list_template(self):  
     self.assertContains(self.response_index, self.test_title) 

Respuesta

18

no soy perfecto en la prueba, pero algunas ideas:

Básicamente, usted debe probar cada función, método de clase , lo que sea, que haya escrito usted mismo.

Esto implica que no es necesario probar las funciones, clases, etc. que proporciona el marco.

Dicho esto, una revisión rápida de sus funciones de comprobación:

  • test_detail_status_code y test_list_status_code:
    OK para comprobar si se ha configurado el enrutamiento correctamente o no. Aún más importante cuando proporciona su propia implementación de get_absolute_url().

  • test_list_numer_of_items:
    bien aunque un cierto número de elementos debe ser devuelto por la vista. No es necesario si el número no es importante (es decir, arbitrario).

  • test_detail_template y test_list_template:
    OK para comprobar si las variables de plantilla se establecen correctamente.

  • Todas las demás funciones: No es necesario.
    Lo que básicamente está probando aquí es si el ORM funcionó correctamente, si las listas funcionan como se espera y si se puede acceder a las propiedades del objeto (o no). Siempre y cuando no cambien p. Ej. el método save() de un modelo y/o proporcionan su lógica personalizada, no probaría esto. Debes confiar en los desarrolladores de frameworks para que esto funcione correctamente.

Sólo debe tener para probar lo que tiene (más) por escrito.

Las clases de modelo son tal vez un caso especial. Básicamente, tienes que probarlos, como dije, si proporcionas una lógica personalizada. Pero también debe probarlos según sus requisitos. P.ej. podría ser que un campo no está permitido a null (o que tiene que ser un cierto tipo de datos, como un entero). Por lo tanto, debe probar que el almacenamiento de un objeto falla, si tiene un valor de null en este campo.
Esto hace no pruebe el ORM para seguir correctamente su especificación pero pruebe que la especificación todavía cumple sus requisitos. Puede ser que cambie el modelo y cambie algunas configuraciones (por casualidad o porque se olvidó de los requisitos).
Pero no tiene que probar, p. métodos como save() o bien puede acceder a una propiedad.

Por supuesto, cuando utiliza código de error de terceros ... bueno, las cosas pueden ser diferentes. Pero como Django usa el marco de prueba para verificar que todo funcione, supongo que está funcionando.

Para resumir:
prueba contra sus requisitos, prueba de su propio código.

Este es solo mi punto de vista. Quizás otros tengan mejores propuestas.

5

Divida sus pruebas en dos tipos completamente independientes.

  • Pruebas de modelo. Ponlas en tu archivo models.py con tu modelo. Estas pruebas ejercerán los métodos en sus clases modelo. Puede hacer CRUD simple (Crear, Recuperar, Actualizar, Eliminar) para simplemente probar que su modelo funciona. No pruebes cada atributo. Pruebe los valores predeterminados del campo y las reglas save() si tiene curiosidad. Para su ejemplo, cree una clase TestNews que crea, obtiene, actualiza y elimina un elemento News. Asegúrese de probar los resultados de fecha predeterminados. Esta clase debe ser breve y al grano. Puede, si su aplicación lo requiere, probar varios tipos de procesamiento de filtros. El código de su unidad de prueba puede (y debe) proporcionar ejemplos de la forma "correcta" de filtrar News.

  • UI Tests. Coloque estos en un archivo separado tests.py. Estas pruebas probarán las funciones y las plantillas de vista.

    • Nombre la TestCase con la "condición" que está creando. "TestNotLoggedIn". "TestLoggedIn". "TestNoValidThis". "TestNotAllowedToDoThat". Su setUp hará el inicio de sesión y cualquier otro paso requerido para establecer la condición requerida.

    • Nombre cada método de prueba con la acción y el resultado. "test_get_noquery_should_list", "test_post_should_validate_with_errors", "test_get_query_should_detail".

Cuestiones relacionadas