Versao Apresentada no TDC2010. Mais completa que a versao do fisl.
Transcript of Tdd em django sem desculpas versao final
1. #TDC2010
2. Cdigo sem testes cdigo j quebrado quando foi planejado --
Jacob Kaplan-Moss um dos criadores do django
3. Estamos em 2010
4. 2010 > 1960
5. 2010 > 1999
6. Alguma buzzword "gil" voc tem que estar usando
7. Buzzwords so quintessenciais Buzzwords trazem sinergia viral
e o empowerment das melhores prticas para a cauda longa
8. 3 anos atrs equipe: >40 pessoas numa mesma sala escopo:
Webapp em Tomcat buzzwords: Bodyshop tpico: cmms.. (< 1999)
9. 2.5 anos atrs equipe: 5 pessoas espalhadas pelo mundo
escopo: Modificaes no nvel de uma distro buzzwords: Scrum, cultura
de testes, sprints, entregas semanais
12. Prticas geis: Test Driven Development (TDD) Behavior Driven
Development (BDD) Code refactoring Continuous Integration Pair
Programming Planning poker
13. TDD Sustentvel Fcil No depende da gerncia
14. TDD no dficil. Dficil no fazer quando voce acostuma
15. Ento, chega de desculpas:
16. Eu no sei nada sobre testes
17. O ecossistema de testes no python Tipos Sabores
TestRunners
18. Tipos de testes
19. Doctest def add(a,b): """ testa a soma >>>
add(1,2) 3 """ return a + b
21. django.test.TestCase from 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)
22. Sabores de testes
23. Unitrios Nvel de funo self.assertTrue(add(1,2),3)
24. Integrao Entre Mdulos 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)
25. De Regresso Correo de erros
26. TestRunners Acha e Roda os testes Padro py.test nose
outros
27. Meu estilo Django.test.TestCase Unitrio Um TestCase por
modelo Um ou mais testes por funo
28. Integrao Um por TestCase por conjunto de apps Regresso Um
teste por erro nose / django-nose Acha testes
29. Eu no preciso de testes automatizados
30. Cdigo evolve
31. Se o seu cdigo no tem testes refatorar ele um pesadelo
52. vi tests/test_models.py #coding:utf8 from django.test
import TestCase class ModelTest(TestCase):
53. Teste de importao def test_existe(self): """ O topico esta
la? """ try: from foobar.forum.models import Topico except
ImportError: self.fail('Nao existe topico')
54. Inclui a app no projeto INSTALLED_APPS = ( ...
'foobar.forum', )
55. Testa ./manage.py test ------------------------------------
Ran 0 tests in 0.000s OK Destroying test database 'default'...
56. 0 testes!
57. nose Acha testes para voc sem que voc tenha que por eles no
__init__.py D pra chamar o pdb no ponto em que falha (
--pdb-failures) (ou ipdb)
59. settings.py TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
INSTALLED_APPS = ( ... 'south', # migracoes 'django_nose', # depois
do south ) NOSE_ARGS = [ '--with-notify', #'--pdb-failures', ]
60. Testa de novo F ==================================== 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
61. TDD S escreve cdigo quando testes falham S escreve testes
quando testes passam
62. Falhou Escreve cdigo
63. vi forum/models.py class Topico(models.Model):
"""representa um topico""" pass
64. testa . ------------------------------------ Ran 1 test in
0.014s
65. Pera! Voce gastou 8 slides para escrever um pass?
66. Mas TDD muito lento
67. e por lento eu quero dizer chato
68. A primeira vez lento
69. Entenda o que voc esta testando try: from
foobar.forum.models import Topico except ImportError:
self.fail('Nao existe topico')
70. No teste a framework Teste a lgica da sua applicao
71. Facilitadores
72. Continous testing Toda vez que voc salva um arquivo ele
rerola os testes
73. django test extensions Faz isso para voc Ainda um pouco
tosco
75. settings.py INSTALLED_APPS = ( ... 'south', # migracoes
'django_nose', # depois do south 'test_extensions', # depois do
south )
76. Rodando o servidor $ ./manage.py runtester ou ainda $
./manage.py runtester forum
77. Automagicamente nosetests --verbosity 1 --with-notify forum
..... ------------------------------------------- Ran 5 tests in
0.457s OK Destroying test database 'default'... Creating test
database 'default'...
78. Bonus combo django-test-extensions com NoseNotify
79. Mas eu no conheco todas as assertions
80. Bico
81. Modo mais fcil: no ./manage shell (com ipython instalado)
>>> from django.test import TestCase >>> In [2]:
TestCase.assert
88. No quase iguais? a = 1.21 b = 1.22 #sao iguais ate a
primeira casa self.assertAlmostEqual(a,b,1) #diferentes depois da
segunda casa self.assertNotAlmostEqual(a,b,2)
89. Asserts que eu no uso assertRaises
90. Testo assim: try: foobar.bang(): self.fail('Bang tem que
explodir') except ExplodingException: pass
91. Agora tarde demais para TDD, meu projeto j existe
92. Pera! Olha s Testes de Regresso django_test_utils
93. Seu melhor amigo Garante que um erro que aconteceu nunca
mais volte a acontecer Usado por todos os grandes projetos de
software livre Mesmo voc no vai fazer mais nenhuma forma de teste
voc tem que fazer esta
99. 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
100. Corrige o erro from django.views.generic.simple import
direct_to_template urlpatterns = patterns('', ... (r'^$',
direct_to_template, {'template': 'index.html'}), ... ) $ vi
templates/index.html
101. Roda os testes e passa nosetests --verbosity 1 ....
----------------------- Ran 4 tests in 0.025s OK
102. Garantia que erros antigos no vo retornar para te
assombrar
103. Toda vez que eu comeo com TDD mas acabo desistindo no
meio
104. 2 formas sustentveis para comear e continuar com TDD
105. Primeiro:
106. TDD:Eu queria ter isso Voc escreve nos testes a API que
voc queria ter
107. Eu queria que fosse assim: def test_metodos(self): topico
= Topico() self.assertTrue(hasattr(topico, 'titulo'))
self.assertTrue(hasattr(topico, 'replies'))
108. Testa F. =================================================
FAIL: test_metodos (test_forum.TestForum)
------------------------------------------------- Traceback (most
recent call last): self.assertTrue(hasattr(topico, 'titulo'))
AssertionError --------------------------------------------------
Ran 2 tests in 0.002s FAILED (failures=1)
109. Implementa class 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')
110. Testa ..
-------------------------------------------------- Ran 2 tests in
0.002s OK
111. Prs e Cons No exatamente TDD Funciona Mais rpido Voc est
perdendo cobertura
112. Segundo: SDT
113. SDT Eu no fao TDD eu faco Stupidity-driven testing. Quando
eu faco algo estpido, eu escrevo um teste para garantir que eu no
vou repetir isso de novo --Titus Brown pycon '07
114. Em suma Escreve cdigo para solucinar um problema Se o
cdigo quebrar de alguma forma besta Escreve um teste para isso
nunca vai acontecer de novo goto 10
115. Prs e Cons No TDD Funciona mas beira Cowboyismo Cobertura
s sobre o cdigo mais frgil Lembra teste de regresso
116. Por que lembra um teste de regresso? Porque . So testes de
regresso para voc mesmo.
117. Escrever testes mais complicado que o problema
118. Longo sim, complicado no Especialmente longo para testes
funcionais django_test_utils, o utlimo bastio dos preguiosos
120. settings.py INSTALLED_APPS = ( ... 'south', # migracoes
'django_nose', # depois do south 'test_extensions', # depois do
south 'test_utils', # depois do south ... )
121. Voc comea o servidor $ ./manage.py testmaker -a forum
122. Cria testes para voc Handling app 'forum' Logging tests to
foobar/forum/tests/forum_testmaker.py Appending to current log file
Inserting 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.
123. Quando voc termina $ cd forum/tests $ ls forum*
forum_testdata.serialized forum_testmaker.py