El Blog de Trespams

Blog personal sobre tecnologia, gestió de projectes i coses que se me passen pel cap

Testejar app Django

Una de les coses que me fan més peresa quan he de crear una nova aplicació Django és tenir que configurar una aplicació per poder-ne fer els tests quan sols estàs fent un mòdul que serà reutilitzable per a altres aplicacions.

Una vegada s'ha fet l'aplicació el que voldria és poder-ho testejar sense tenir que configurar tot un projecte i no acabava de trobar-ho del tot fins que vaig veure la manera en que ho feia Brutasse a django-password-reset.

L'aproximació de Brutasse és tenir una projecte Django dins la mateixa applicació que s'està creant, de manera que aquesta es pot testejar sense tenir que crear el projecte sencer i controlant a la mateixa vegada els settings que estam fent servir. És a dir, just el que estava cercant.

Aquests darrers dies he estat treballant un poc en una branca de django-mailer2 i l'he refactoritzat per seguir la seva idea a l'hora de fer els unit tests.

Una vegada creat el [paquet python] (http://guide.python-distribute.org/index.html) el que es fa es crear un arxiu que serà l'executable que iniciarà els tests. runtests.py per no ser massa originals

Creant l'executable

Aquí el que fem és configurar l'aplicació com se fos una execució desatesa de Django, és a dir, configuram els settings, el path i després ja sols ens queda fer l'execució dels unittests

# !/usr/bin/env python # encoding: utf-8 #
# ----------------------------------------------------------------------------
import os
import sys

parent = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, parent)
os.environ['DJANGO_SETTINGS_MODULE'] = 'django_mailer.testapp.settings'
from django.test.simple import DjangoTestSuiteRunner


def runtests(*test_args):
test_args = test_args or ['testapp']
parent = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, parent)
runner = DjangoTestSuiteRunner(verbosity=1, interactive=True, failfast=False)
failures = runner.run_tests(test_args)
sys.exit(failures)


if __name__ == '__main__':
runtests()

Fixem-nos ja de pas que faríem el mateix si hem creat una aplicació Django que no volem que s'executi com a servei web. Per exemple una importació de dades, o una exportació. Hi ha diverses maneres d'aconseguir-ho i aquesta és una de les més simples.

Una vegada hem establit la variable d'entorn de la nostra aplicació (la que contindrà els tests) ja tenim tota la potència del framework Django al nostre abast.

L'apliació testejadora

Per no fer-nos massa enfora de la convenció de Django, posam l'aplicació que realment executarà els tests dins el directori del mòdul que hem desenvolupat, en el nostre exemple django_mailer.

Podríem posar-li test, però la veritat és que no m'agrada això de tenir un projecte test i dintre un mòdul test. Sovint fa difícil saber on tens els errors, així que un nou explícit ja va bé.

Dins testapp trobam el que seria un projecte Django bàsic, sols que a més hi hem postat un settins que són molt reduïts,

EMAIL_PORT = 1025 
ROOT_URLCONF = 'django_mailer.apptest.urls'
SECRET_KEY = 'yo secret yo'
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'django_mailer.sqlite', }, }
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django_mailer', 'django_mailer.testapp' )

Bàsicament hi ha els paràmetres de configuració que necesistarem per a executar l'aplicació que estam creant, configuració de base de dades i la configuració dels INSTALLED_APPS on hi ha la pròpia aplicació de test i l'aplicació que estam testejant, de manera que ho tinguem tot dins el Python path.

A partir d'aquí tot va com a la documentació de Django, és a dir, cream un mòdul anomenat test i utilitzam el mòdul TestCase de Django i tota la resta d'artilleria.

El que hem aconseguit, però, és fer més senzill el manteniment de l'aplicació ja que queda tot autocontingut. Al tenir uns settings mínims també podem estar raonablement segurs que l'aplicació que cream funcioni bé per ella mateixa sense altres interferències, i com no, ens queda documentat el que necessitam per a fer-la anar.

No estic convençut de poder-ho considerar encara una "millor pràctica", però ho trob útil i potser a algú dels qui em llegiu també us pot solucionar un problema, així que ja em contareu.

blog comments powered by Disqus