tdd em django sem desculpas versao fisl

128

Upload: adriano-petrich

Post on 18-Dec-2014

1.686 views

Category:

Technology


0 download

DESCRIPTION

Palestra apresentada no fisl11 sobre TDD em django

TRANSCRIPT

Page 1: TDD em django sem desculpas versao fisl
Page 2: TDD em django sem desculpas versao fisl

Código sem testes écódigo já quebradoquando foi planejado

-- Jacob Kaplan-Moss

um dos criadores do django

Page 3: TDD em django sem desculpas versao fisl

Estamos em 2010

Page 4: TDD em django sem desculpas versao fisl

2010 > 1960

Page 5: TDD em django sem desculpas versao fisl

2010 > 1999

Page 6: TDD em django sem desculpas versao fisl

Alguma buzzword "ágil"você tem que estarusando

Page 7: TDD em django sem desculpas versao fisl

Buzzwords sãoquintessenciaisBuzzwords trazem sinergia viral e oempowerment das melhores práticas para acauda longa

Page 8: TDD em django sem desculpas versao fisl

3 anos atrásequipe: >40 pessoas numa mesma sala

escopo: Webapp em Tomcat

buzzwords: Bodyshop típico: PMI, cmms.. (<1999)

Page 9: TDD em django sem desculpas versao fisl

2.5 anos atrásequipe: 5 pessoas espalhadas pelo mundo

escopo: Modificações no nível de uma distro

buzzwords: Scrum, cultura de testes, sprints,entregas semanais

Page 10: TDD em django sem desculpas versao fisl

5 > 40

Page 11: TDD em django sem desculpas versao fisl

Metodologias ágeis:Extreme Programing(XP)

Scrum

Kanban

Feature Driven Develelopment (FDD)

Page 12: TDD em django sem desculpas versao fisl

Práticas ágeis:Test Driven Development (TDD)

Behavior Driven Development (BDD)

Code refactoring

Continuous Integration

Pair Programming

Planning poker

Page 13: TDD em django sem desculpas versao fisl

TDDSustentável

Fácil

Não depende da gerência

Page 14: TDD em django sem desculpas versao fisl

TDD não é díficil.Díficil é não fazerquando voceacostuma

Page 15: TDD em django sem desculpas versao fisl

Então, chega dedesculpas:

Page 16: TDD em django sem desculpas versao fisl

Eu não sei nadasobre testes

Page 17: TDD em django sem desculpas versao fisl

O ecossistema detestes no python

• Tipos• Sabores• TestRunners

Page 18: TDD em django sem desculpas versao fisl

Tipos de testes

Page 19: TDD em django sem desculpas versao fisl

Doctest

def add(a,b): """ testa a soma >>> add(1,2) 3 """ return a + b

Page 20: TDD em django sem desculpas versao fisl

Unittestunittest.TestCase

django.test.TestCase

Page 21: TDD em django sem desculpas versao fisl

django.test.TestCasefrom django.test import TestCase

class SimpleTest(TestCase): def test_adicao(self): """ Testa que a adicao de 1 + 1 da 2. """ self.assertEqual(1 + 1, 2)

Page 22: TDD em django sem desculpas versao fisl

Sabores de testes

Page 23: TDD em django sem desculpas versao fisl

UnitáriosNível de função

self.assertTrue(add(1,2),3)

Page 24: TDD em django sem desculpas versao fisl

IntegraçãoEntre Módulos

r = self.client.get('/foo')self.assertRedirects(r,'/login/')self.client.login(user_name='foo' ,password='bar')r = self.client.get('/foo')self.assertEquals(r.status_code,200)

Page 25: TDD em django sem desculpas versao fisl

De RegressãoCorreção de erros

Page 26: TDD em django sem desculpas versao fisl

TestRunnersAcha e Roda os testes

• Padrão• py.test• nose• outros

Page 27: TDD em django sem desculpas versao fisl

Meu estilo

Page 28: TDD em django sem desculpas versao fisl

• Django.test.TestCase• Unitário

Um TestCase por modeloUm ou mais testes por função

• IntegraçãoUm por TestCase por conjunto de apps

• RegressãoUm teste por erro

• nose / django-noseAcha testes

Page 29: TDD em django sem desculpas versao fisl

Por que eu precisode testesautomatizados?

Page 30: TDD em django sem desculpas versao fisl

Código evolve

Page 31: TDD em django sem desculpas versao fisl

Se o seu código nãotem testes refatorar eleé um pesadelo

Page 32: TDD em django sem desculpas versao fisl

Imagina isso$ cat `find . | grep "py$" \ | grep -v migration` | wc -l47260

Page 33: TDD em django sem desculpas versao fisl

Agora isso:

$ cat `find . | grep "py$" \ | grep test` | wc -l34108

Page 34: TDD em django sem desculpas versao fisl

Tranquilidade derefatorarFelicidade é um código com boa cobertura

Page 35: TDD em django sem desculpas versao fisl

Eu meio que nãosei o que é TDD

Page 36: TDD em django sem desculpas versao fisl

Ciência da computaçãoé tanto sobrecomputadores quantocomo a astronomia ésobre telescópios

-- E W Dijkstra

Page 37: TDD em django sem desculpas versao fisl

Test DrivenDevelopment é tantosobre testes assimquanto a ciência dacomputação é sobrecomputadores

Page 38: TDD em django sem desculpas versao fisl

TDD é sobredesenvolvimento equalidade

Page 39: TDD em django sem desculpas versao fisl

Testes são umsubproduto

Page 40: TDD em django sem desculpas versao fisl

TDD

Page 41: TDD em django sem desculpas versao fisl

TDDSó escreve código quando testes falham

Page 42: TDD em django sem desculpas versao fisl

TDDSó escreve código quando testes falham

Só escreve testes quando testes passam

Page 43: TDD em django sem desculpas versao fisl

Eu nunca fizmuitos testes noDjango

Page 44: TDD em django sem desculpas versao fisl

Como fazer$ django-admin.py startproject foobar$ cd foobar/$ chmod +x manage.py$ vi settings.py

Page 45: TDD em django sem desculpas versao fisl

settings.pyimport osPROJECT_PATH = os.path.abspath( os.path.split(__file__)[0])...configura o banco...TEMPLATE_DIRS = ( os.path.join(PROJECT_PATH,'templates'),)

Page 46: TDD em django sem desculpas versao fisl

Hora de testar./manage.py test

------------------------------------Ran 0 tests in 0.000s

OKDestroying test database 'default'...

Page 47: TDD em django sem desculpas versao fisl

TDDSó escreve código quando testes falham

Só escreve testes quando testes passam

Page 48: TDD em django sem desculpas versao fisl

PassouEscreve testes

Page 49: TDD em django sem desculpas versao fisl

Mais Testes, então

./manage.py startapp forumcd forum/

Page 50: TDD em django sem desculpas versao fisl

Meu estilo (v.2)

rm tests.pymkdir teststouch tests/__init__.pytouch tests/test_models.py

Page 51: TDD em django sem desculpas versao fisl

vi tests/test_models.py

#coding:utf8from django.test import TestCase

class TopicoTest(TestCase):

Page 52: TDD em django sem desculpas versao fisl

Teste de importaçãodef test_existe(self): """ O topico esta la? """ try: from foobar.forum.models import Topico except ImportError: self.fail('Nao existe topico')

Page 53: TDD em django sem desculpas versao fisl

Inclui a app no projeto

INSTALLED_APPS = ( ... 'foobar.forum',)

Page 54: TDD em django sem desculpas versao fisl

Testa./manage.py test

------------------------------------Ran 0 tests in 0.000s

OKDestroying test database 'default'...

Page 55: TDD em django sem desculpas versao fisl

0 testes!

Page 56: TDD em django sem desculpas versao fisl

noseAcha testes para você sem que você tenhaque por eles no __init__.py

Dá pra chamar o pdb no ponto em que falha( --pdb-failures) (ou ipdb)

Page 57: TDD em django sem desculpas versao fisl

django-nose

$ pip install nose$ pip install django-nose

Page 58: TDD em django sem desculpas versao fisl

settings.pyTEST_RUNNER = 'django_nose.NoseTestSuiteRunner'

INSTALLED_APPS = ( ... 'south', # migracoes 'django_nose', # depois do south)#opcional#NOSE_ARGS = ['--pdb-failures', ]

Page 59: TDD em django sem desculpas versao fisl

Testa de novoF====================================FAIL: O topico esta la?------------------------------------Traceback (most recent call last): File "test_models", line 18, in test_existe self.fail('Nao existe topico')AssertionError: Nao existe topico------------------------------------Ran 1 test in 0.003s

Page 60: TDD em django sem desculpas versao fisl

TDDSó escreve código quando testes falham

Só escreve testes quando testes passam

Page 61: TDD em django sem desculpas versao fisl

FalhouEscreve código

Page 62: TDD em django sem desculpas versao fisl

vi forum/models.py

class Topico(models.Model): """representa um topico""" pass

Page 63: TDD em django sem desculpas versao fisl

testa.------------------------------------Ran 1 test in 0.014s

Page 64: TDD em django sem desculpas versao fisl

Pera!Voce gastou 8 slides para escrever umpass?

Page 65: TDD em django sem desculpas versao fisl

Mas TDD é muitolento

Page 66: TDD em django sem desculpas versao fisl

e por lento euquero dizer chato

Page 67: TDD em django sem desculpas versao fisl

A primeira vez élento

Page 68: TDD em django sem desculpas versao fisl

Entenda o que vocêesta testandotry: from foobar.forum.models import Topicoexcept ImportError: self.fail('Nao existe topico')

Page 69: TDD em django sem desculpas versao fisl

Não teste a frameworkTesta a lógica da sua applicação

Page 70: TDD em django sem desculpas versao fisl

Facilitadores

Page 71: TDD em django sem desculpas versao fisl

Continous testingToda vez que você salva um arquivo elererola os testes

Page 72: TDD em django sem desculpas versao fisl

django test extensionsFaz isso para você

Ainda é um pouco tosco

Page 73: TDD em django sem desculpas versao fisl

django-test-extensions$ pip install django-test-extensions

Page 74: TDD em django sem desculpas versao fisl

settings.pyINSTALLED_APPS = ( ... 'south', # migracoes 'django_nose', # depois do south 'test_extensions', # depois do south)

Page 75: TDD em django sem desculpas versao fisl

Rodando o servidor

$ ./manage.py runtester

ou ainda

$ ./manage.py runtester forum

Page 76: TDD em django sem desculpas versao fisl

Mas eu nãoconheco todas asassertions

Page 77: TDD em django sem desculpas versao fisl

Bico

Page 78: TDD em django sem desculpas versao fisl

Modo mais fácil:no ./manage shell (com ipython instalado)

>>> from django.test import TestCase>>> In [2]: TestCase.assert<tab><tab>

Page 79: TDD em django sem desculpas versao fisl

assertsTestCase.assert_ TestCase.assertAlmostEqualTestCase.assertAlmostEquals TestCase.assertContainsTestCase.assertEqual TestCase.assertEqualsTestCase.assertFalse TestCase.assertFormErrorTestCase.assertNotAlmostEquals TestCase.assertNotContainsTestCase.assertNotEqual TestCase.assertNotEqualsTestCase.assertRaises TestCase.assertRedirectsTestCase.assertTemplateNotUsed TestCase.assertTemplateUsedTestCase.assertTrue TestCase.assertNotAlmostEqual

Page 80: TDD em django sem desculpas versao fisl

Asserts básicasEssas você deve usar bastante

assertTrue(True)assertFalse(False)

assertEqual(1,1)assertNotEqual(1,2)

Page 81: TDD em django sem desculpas versao fisl

Asserts amigáveisEssas facilitam a vida para testes funcionais

assertContains(response,texto,status)assertNotContains(response,texto,status)

Page 82: TDD em django sem desculpas versao fisl

exemplodef test_welcome(self): resp = self.client.get('/',{}) self.assertContains(resp,'<h1>Oi</h1>' ,200)

Page 83: TDD em django sem desculpas versao fisl

Asserts amigáveis(cont)assertRedirects(response,nova_url)assertTemplateUsed(response,template)assertTemplateNotUsed(response,template)assertFormError(response,form,fields,errors)

Page 84: TDD em django sem desculpas versao fisl

WTF?

assertAlmostEqual

assertNotAlmostEqual

Page 85: TDD em django sem desculpas versao fisl

Não quase iguais?

a = 1.21b = 1.22#sao iguais ate a primeira casaself.assertAlmostEqual(a,b,1)#diferentes depois da segunda casaself.assertNotAlmostEqual(a,b,2)

Page 86: TDD em django sem desculpas versao fisl

Asserts que eu não uso

assertRaises

Page 87: TDD em django sem desculpas versao fisl

Testo assim:try: foobar.bang(): self.fail('Bang tem que explodir')except ExplodingException: pass

Page 88: TDD em django sem desculpas versao fisl

Agora é tardedemais para TDD,meu projeto jáexiste

Page 89: TDD em django sem desculpas versao fisl

Pera! Olha só• Testes de Regressão• django_test_utils

Page 90: TDD em django sem desculpas versao fisl

Seu melhor amigoGarante que um erro que aconteceu nuncamais volte a acontecer

Usado por todos os grandes projetos desoftware livre

Mesmo você não vai fazer mais nenhumaforma de teste você tem que fazer esta

Page 91: TDD em django sem desculpas versao fisl

Testes de Regressão

Page 92: TDD em django sem desculpas versao fisl

Encontrou um erro[24/Jul/2010 11:14:51] "GET / HTTP/1.1" 404 1946

Page 93: TDD em django sem desculpas versao fisl

Escreve um teste quefalha por causa do erro

$ vi forum/test_regression.py

Page 94: TDD em django sem desculpas versao fisl

cont

#coding:utf8from django.test import TestCase

class TestRegression(TestCase): """testes de regressao"""

Page 95: TDD em django sem desculpas versao fisl

cont+=1def test_regress_home(self): """Home precisa existir""" r = self.client.get('/', {}) self.assertEqual(r.status_code, 200)

Page 96: TDD em django sem desculpas versao fisl

Testa e falha..E================================================ERROR: Home precisa existir------------------------------------------------Traceback (most recent call last): File "foobar/forum/tests/test_regresssion.py", line 10, in test_regress_home r = self.client.get('/', {}) ... raise TemplateDoesNotExist(name)TemplateDoesNotExist: 404.html

Page 97: TDD em django sem desculpas versao fisl

Corrige o errofrom django.views.generic.simple import direct_to_templateurlpatterns = patterns('', ... (r'^$', direct_to_template, {'template': 'index.html'}), ...)

$ vi templates/index.html

Page 98: TDD em django sem desculpas versao fisl

Roda os testes e passa

nosetests --verbosity 1....-----------------------Ran 4 tests in 0.025s

OK

Page 99: TDD em django sem desculpas versao fisl

Garantia que errosantigos não vãoretornar para teassombrar

Page 100: TDD em django sem desculpas versao fisl

Toda vez que eucomeço com TDDmas acabodesistindo no meio

Page 101: TDD em django sem desculpas versao fisl

2 formassustentáveis paracomeçar econtinuar comTDD

Page 102: TDD em django sem desculpas versao fisl

Primeiro:

Page 103: TDD em django sem desculpas versao fisl

TDD:Eu queria ter issoVocê escreve nos testes a API que vocêqueria ter

Page 104: TDD em django sem desculpas versao fisl

Eu queria que fosseassim:def test_metodos(self): topico = Topico() self.assertTrue(hasattr(topico, 'titulo')) self.assertTrue(hasattr(topico, 'replies'))

Page 105: TDD em django sem desculpas versao fisl

TestaF.=================================================FAIL: test_metodos (test_forum.TestForum)-------------------------------------------------Traceback (most recent call last): self.assertTrue(hasattr(topico, 'titulo'))AssertionError

--------------------------------------------------Ran 2 tests in 0.002sFAILED (failures=1)

Page 106: TDD em django sem desculpas versao fisl

Implementaclass Topico(models.Model): """representa um topico""" titulo = models.CharField(max_length=64)class Resposta(models.Model): '''Uma resposta no topico''' topico = models.ForeignKey(Topico, related_name='replies')

Page 107: TDD em django sem desculpas versao fisl

Testa..--------------------------------------------------Ran 2 tests in 0.002s

OK

Page 108: TDD em django sem desculpas versao fisl

Prós e Cons• Não é exatamente TDD• Funciona• Mais rápido• Você está perdendo cobertura

Page 109: TDD em django sem desculpas versao fisl

Segundo: SDT

Page 110: TDD em django sem desculpas versao fisl

SDTEu não faço TDD eu faco Stupidity-driventesting. Quando eu faco algo estúpido, euescrevo um teste para garantir que eu nãovou repetir isso de novo

--Titus Brown pycon '07

Page 111: TDD em django sem desculpas versao fisl

Em sumaEscreve código para solucinar um problema

Se o código quebrar de alguma forma besta

Escreve um teste para isso nunca vaiacontecer de novo

goto 10

Page 112: TDD em django sem desculpas versao fisl

Prós e Cons• Não é TDD• Funciona mas beira Cowboyismo• Cobertura só sobre o código mais frágil• Lembra teste de regressão

Page 113: TDD em django sem desculpas versao fisl

Por que lembra umteste de regressão?Porque é.

São testes de regressão para você mesmo.

Page 114: TDD em django sem desculpas versao fisl

Escrever testes émais complicadoque o problema

Page 115: TDD em django sem desculpas versao fisl

Longo sim, complicadonãoEspecialmente longo para testes funcionais

django_test_utils, o utlimo bastião dospreguiçosos

Page 116: TDD em django sem desculpas versao fisl

django-test-utils

$ pip install django-test-utils

Page 117: TDD em django sem desculpas versao fisl

settings.pyINSTALLED_APPS = ( ... 'south', # migracoes 'django_nose', # depois do south 'test_extensions', # depois do south 'test_utils', # depois do south ...)

Page 118: TDD em django sem desculpas versao fisl

Você começa o servidor

$ ./manage.py testmaker -a forum

Page 119: TDD em django sem desculpas versao fisl

Cria testes para vocêHandling app 'forum'Logging tests to foobar/forum/tests/forum_testmaker.pyAppending to current log fileInserting TestMaker logging server...Validating models...0 errors found

Django version 1.2.1, using settings 'foobar.settings'Development server is running at http://127.0.0.1:8000/Quit the server with CONTROL-C.

Page 120: TDD em django sem desculpas versao fisl

Quando você termina

$ cd forum/tests$ ls forum*forum_testdata.serializedforum_testmaker.py

Page 121: TDD em django sem desculpas versao fisl

Testes geradosdef test_forum_127958317459(self): r = self.client.get('/forum/', {}) self.assertEqual(r.status_code, 200) self.assertEqual( unicode(r.context["paginator"]), u"None") self.assertEqual( unicode(r.context["object_list"]), u"[<Topico: Topico object>, <Topico: Topico object>]") .....

Page 122: TDD em django sem desculpas versao fisl

Eu conserto ostestes depois

Page 123: TDD em django sem desculpas versao fisl

PFFFFFFFFFF!

Page 124: TDD em django sem desculpas versao fisl

TDD não é díficil.Díficil é não fazerquando voceacostuma

Page 125: TDD em django sem desculpas versao fisl

Créditoshttp://www.flickr.com/photos/blue-moose/3528603529

Page 126: TDD em django sem desculpas versao fisl

Dúvidas?

Page 127: TDD em django sem desculpas versao fisl

Agradecimentoshttp://associacao.python.org.br/

Nos vemos na PythonBrasil[6] emCuritiba

Outubro 21 a 23

Page 128: TDD em django sem desculpas versao fisl

Referênciashttp://code.google.com/p/python-nose/http://github.com/jbalogh/django-nosehttp://github.com/garethr/django-test-extensionsgithub.com/ericholscher/django-test-utilsgithub.com/ctb/pony-build

Tdd em django sem desculpas@[email protected] commons (by) (sa)