python - test - Escribiendo buenas pruebas para aplicaciones Django.
test form django (2)
Nunca he escrito ninguna prueba en mi vida, pero me gustaría comenzar a escribir pruebas para mis proyectos 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.
La aplicación tiene dos vistas (una vista de lista y una vista detallada) 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 mostrarle mi archivo tests.py y preguntar:
¿Tiene sentido?
¿Estoy incluso probando las cosas correctas?
¿Hay mejores prácticas que no estoy siguiendo y me podría indicar?
mi tests.py (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)
Divide tus pruebas en dos tipos completamente separados.
Pruebas de modelos. Ponga estos en su archivo
models.py
con su modelo. Estas pruebas ejercitarán los métodos en tus clases modelo. Puede hacer CRUD simple (Crear, Recuperar, Actualizar, Eliminar) para simplemente probar que su modelo funciona. No pruebes todos los atributos. Prueba los valores predeterminados de los campos y las reglas desave()
si tienes curiosidad.Para su ejemplo, cree una clase de
TestNews
que cree, obtenga, actualice y elimine un elemento deNews
. Asegúrese de probar los resultados de la fecha predeterminada. Esta clase debe ser corta y al punto. Usted puede, si su aplicación lo requiere, probar varios tipos de procesamiento de filtros. El código de prueba de su unidad puede (y debería) proporcionar ejemplos de la forma "correcta" de filtrarNews
.Pruebas de interfaz de usuario. Ponga estos en un archivo
tests.py
separado. Estas pruebas probarán las funciones de vista y las plantillas.Nombra el TestCase con la "condición" que estás creando. "TestNotLoggedIn". "TestLoggedIn". "TestNoValidThis". "TestNotAllowedToDoThat". Su
setUp
hará el inicio de sesión y cualquier otro paso necesario para establecer la condición requerida.Nombra 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".
No soy perfecto en la prueba pero algunos pensamientos:
Básicamente, debes probar cada función, método, clase, lo que sea, que hayas escrito por ti mismo.
Esto implica que no tiene que probar las funciones, clases, etc. que proporciona el marco.
Dicho esto, una comprobación rápida de sus funciones de prueba:
test_detail_status_code
ytest_list_status_code
:
Ok para comprobar si ha configurado el enrutamiento correctamente o no. Aún más importante cuando proporcionas tu propia implementación deget_absolute_url()
.test_list_numer_of_items
:
Está bien si la vista debe devolver un cierto número de elementos. No es necesario si el número no es importante (es decir, arbitrario).test_detail_template
ytest_list_template
:
Ok para verificar si las variables de la plantilla están configuradas correctamente.Todas las demás funciones: No es necesario.
Lo que básicamente están probando aquí es si el ORM funcionó correctamente, si las listas funcionan como se esperaba y si se puede acceder a las propiedades del objeto (o no). Siempre y cuando no cambie, por ejemplo, el métodosave()
de un modelo y / o proporcione su lógica personalizada , no probaría esto. Debes confiar en los desarrolladores de framework que esto funciona correctamente.
Solo deberías tener que probar lo que has escrito.
Las clases modelo son quizás un caso especial. Básicamente, tienes que probarlos, como dije, si proporcionas lógica personalizada. Pero también debes probarlos contra tus requerimientos . Por ejemplo, podría ser que un campo no pueda ser null
(o que tenga que ser un tipo de datos determinado, como un entero). Por lo tanto, debe probar que el almacenamiento de un objeto falla, si tiene un valor null
en este campo.
Esto no prueba al ORM para que siga correctamente su especificación, pero prueba que la especificación aún cumple con sus requisitos. Es posible que cambie el modelo y cambie algunas configuraciones (por casualidad o porque olvidó los requisitos).
Pero no tiene que probar, por ejemplo, métodos como save()
o si puede acceder a una propiedad.
Por supuesto, cuando utiliza un código de terceros con errores ... bueno, las cosas pueden ser diferentes. Pero como Django usa el marco de prueba para verificar que todo funciona, supongo que funciona.
Para resumir:
Prueba contra tus requerimientos, prueba tu propio código.
Este es solo mi punto de vista. Quizás otros tengan mejores propuestas.