Sei sulla pagina 1di 25

Introduccion Testing en django BDD

Testing in django

Luis Thur
Universidad Nacional de Cordoba
Basada en la charla de Natalia Bidart (2013) que es basada en la charla de Matias Bordese (2011)

9 de septiembre de 2014

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 1


Introduccion Testing en django BDD

Outline

1 Introduccion

2 Testing en django
Django test case
Django test client

3 BDD

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 2


Introduccion Testing en django BDD

Objetivos del testing

El testing automatizado es una herramienta muy util, que


permite entre otras cosas:
Al momento de escribir nuevo codigo, validar que este
funciona como se espera
Cuando uno refactorea o modifica codigo anterior,
asegurar que los cambios no afectan de forma inesperada
nuestra aplicacion

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 3


Introduccion Testing en django BDD

Testing en django

El testing de una aplicacion web es complejo


Django provee un framework para la ejecucion de tests
que simplifica bastante la tarea
Existen dos maneras principales de escribir tests: doc
tests y unit tests
Nos vamos a concentrar en unit test!

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 4


Introduccion Testing en django BDD

Unit test generales (No es el particular de django)

Se describen mediante metodos de una subclase de


unittest.TestCase
import unittest

class BasicTestCase(unittest.TestCase):

def test_division_no_reminder(self):
self.assertEqual(divmod(10, 2), (5, 0))

def test_division_with_reminder(self):
self.assertEqual(divmod(11, 2), (5, 1))

def test_zero_as_numerator(self):
self.assertEqual(divmod(0, 2), (0, 0))

def test_zero_division_error(self):
self.assertRaises(ZeroDivisionError, divmod, 2, 0)

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 5


Introduccion Testing en django BDD

TestCase

La super clase TestCase provee 3 grupos de metodos


(que uno re-usa cuando hereda de esa clase):
Para correr tests
Para chequear condiciones y reportar fallas
Para obtener informacion acerca del test mismo
(countTestCases, id, shortDescription)

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 6


Introduccion Testing en django BDD

TestCase

setUp()
Se llama inmediatamente antes de correr un test para
preparar el entorno; la implementacion por defecto no
hace nada.
tearDown()
Se llama despues de finalizado cada test, incluso si este
falla; la implementacion por defecto no hace nada. El
defecto de tearDown es que no es llamado si falla el setUp.
addCleanup()
Se usar para encolar funciones de limpieza. Es
garantizado que todas las funciones encoladas se van a
ejecutar, y se llaman en orden LIFO.

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 7


Introduccion Testing en django BDD

TestCase

Los metodos mas usuales para hacer aserciones son:


assertTrue(expr[, msg])
Indica una falla si expr es falso; msg es la explicacion del
error
assertEqual(first, second[, msg])
Chequea que first sea igual a second
assertNotEqual(first, second[, msg])
Chequea que first no sea igual a second
assertRaises(exception, f, args)
Chequea que al llamar f(args) se levanta la excepcion
"exception"
El listado completo en:
http://docs.python.org/2/library/unittest.html

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 8


Introduccion Testing en django BDD

Corriendo tests

Desde Python 2.7, la biblioteca estandar provee un corredor de


tests que permite "descubrir" automaticamente los tests:
$ python -m unittest discover --verbose
test_division_no_reminder (test_basic.BasicTestCase) ... ok
test_division_with_reminder (test_basic.BasicTestCase) ... ok
test_zero_as_numerator (test_basic.BasicTestCase) ... ok
test_zero_division_error (test_basic.BasicTestCase) ... ok
---------------------------------------------------------------
Ran 4 tests in 0.001s
OK

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 9


Introduccion Testing en django BDD

Escribiendo test en django

Para una aplicacion Django, el test runner de Django busca


automaticamente los tests en:
El archivo models.py en el directorio de la aplicacion
El archivo tests.py o modulo python tests en el directorio
de la aplicacion
Al momento de correr los tests, el test runner crea su propia
base de datos, que es destruida tras la corrida exitosa (o no)
de los tests. Cada test corre en una transaccion de la base de
datos que es abortada al finaliza cada test. Django provee una
clase TestCase propia:
from django.test import TestCase
Esta clase extiende a la antesmencionada unittest.TestCase de
Python.

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 10


Introduccion Testing en django BDD

Django TestCase

Django provee un corredor de tests propio. Hace


descubrimiento automatico de tests, pero de manera simple.
Por ello, hay una aplicacion externa que se recomienda usar
para correr los tests (en vez del corredor por defecto), y se
llama:
django-discover-runner

Para usarla, seguir los siguientes pasos:


1. Instalar la dependecia django-discover-runner:
pip install -u django-discover-runner
2. Agregar discover_runner al listado de INSTALLED_APPS
3. Definir el setting nuevo
TEST_RUNNER = discover_runner.DiscoverRunner (en settings.py)

(Los nombres de los test methods DEBEN comenzar con


"test")

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 11


Introduccion Testing en django BDD

Django TestCase

Los metodos mas usuales para hacer aserciones son:


assertContains(response, text, count=None, status code=200)
Verifica el status code del response, y que text aparece (count veces) en el
contenido
assertNotContains(response, text, status code=200)
Verifica el status code del response, y que text no aparece en el contenido
assertFormError(response, form, field, errors)
Verifica un campo de un formulario devuelva el error indicado
assertTemplateUsed(response, template name)
Verifica que el template con el nombre dado se uso en el rendering del response
El nombre es un string de la forma "admin/index.html""
assertTemplateNotUsed(response, template name)
Verifica que el template con el nombre dado no se haya usado en el rendering
del response

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 12


Introduccion Testing en django BDD

Django TestCase

El listado completo de aserciones provistas por el Django


TestCase esta en:
https://docs.djangoproject.com/en/dev/topics/
testing/overview

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 13


Introduccion Testing en django BDD

Corriendo tests en django

Los tests se corren mediante la utilidad manage.py:


$ python manage.py test
Creating test database for alias default...
........
-----------------------------------------------------------
Ran 8 tests in 0.367s
OK
Destroying test database for alias default...

Si solo queremos correr los tests de una aplicacion particular:


manage.py test polls

Se puede ser mas especifico, indicando que archivo de test se


quierecorrer, o incluso que test case se quiere ejecutar:
manage.py test polls.tests.test_models
manage.py test polls.tests.test_models.PollModelTestCase

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 14


Introduccion Testing en django BDD

Test client

Utilidad que actua como browser simple


Al usar el TestCase de Dango, se puede acceder a una
instancia de Test Client (en self.client) automaticamente
Facilita testear vistas e interactuar con la aplicacion web
Permite (por ejemplo):
Simular requests GET y POST
Verificar que para una URL dada se ejecuta la vista
correcta
Verificar que para un pedido dado, se devuelve un template
con determinados valores

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 15


Introduccion Testing en django BDD

Test client - request

A partir de una instancia de cliente se tienen los siguientes


metodos:
get(path, data=)
>>> c = Client()
>>> c.get(/customers/details/, {name: fred, age: 7})
# equivalente al siguiente pedido GET:
# /customers/details/?name=fred&age=7

post(path, data=, content type=MULTIPART CONTENT)


>>> c = Client()
>>> c.post(/login/, {name: fred, passwd: secret})

login(**credentials)
>>> c = Client()
>>> c.login(username=fred, password=secret)

logout()
Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 16
Introduccion Testing en django BDD

Test client - response

Los metodos get() y post() devuelven un objeto Response, que


tiene informacion adicional en los siguientes atributos:
client: el test client que hizo el pedido
content: el texto de la respuesta, como string
context: la instancia de contexto usada para el template
request: los datos del request
status code: el codigo de respuesta HTTP
template: el o los templates usados para renderizar la
respuesta
Tambien se puede consultar el valor de cualquiera de los
headers HTTP de la respuesta (por ej.
response[Content-Type])

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 17


Introduccion Testing en django BDD

Behaviour driven development

BDD especifica que los test de cualquier unidad de software


deberia ser especificado en terminos del COMPORTAMIENTO
deseado de la unidad.

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 18


Introduccion Testing en django BDD

Behaviour driven development

Algunas ventajas que tiene BDD son:


si tenemos una gran bateria de metodos implementados,
desarrollar casos de test se vuelve muy facil.
el caso de test expresa el comportamiento del sistema.
los Scenarios en BDD representan directamente los casos
de uso
se pueden presentar como parte del diseno

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 19


Introduccion Testing en django BDD

Conceptos rapidos

En BDD diferenciamos los siguientes conceptos


Step, es un paso atomico. Un step solo desarrolla una sola
cosa. Por ejemplo, rellenar un campo de un formulario.
Scenario, es un conjunto de step. Representa un
escenario exitoso o excepcional dentro de los casos de
uso.
Feature, es un conjunto de scenarios. Representa un
modulo a testear, por ejemplo. El envido de nuestra
aplicacion.

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 20


Introduccion Testing en django BDD

Vista rapida

La forma general de escribir casos de test es:


Given some initial context
When an event occurs
And other event ocurrs
Then ensure some outcomes

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 21


Introduccion Testing en django BDD

Vista rapida

Un ejemplo visualizando nuestro Truco.


Feature: the envido game from truco application web
Scenario: Player A says Envido and Player B accepts
Given a room
And a player named "A" inside the room
And a player named "B" inside the room
When the player "A" says envido to the player "B"
And the player "B" says "No quiero"
Then the player "A" have 1 point extra.

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 22


Introduccion Testing en django BDD

Vista rapida

Luego se hace un mapeo entre un step de un scenario a un


metodo atomico que haga lo que el step representa.
@step("an event ocurrs")
def step_impl(context):
#The event ocurrs here

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 23


Introduccion Testing en django BDD

Vista rapida

Para Python tenemos la libreria Behave que nos permite


hacer Behaviour Driven Development
Behave es muy usado para QA en la industria
Si queremos testear webapps como la que
desarrollaremos en esta materia, podemos usar Behaving
que combina el poder de Selenium y Behave para testear
mockeando un cliente real.

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 24


Introduccion Testing en django BDD

Final

Questions?

Testing en django - Ingenieria del Software I 2014 - UNC Luis Thur 25

Potrebbero piacerti anche