SlideShare uma empresa Scribd logo
1 de 118
Baixar para ler offline
Testes
Versão Python



     Osvaldo Santana Neto
        osantana@triveos.com
Osvaldo Santana Neto
Programador amador
desde 1988
Programador profissional
desde 1991
Programador Python
desde 2000
Programador Django
desde 2008
Eu e os testes...
 Objective Solutions      Triveos Tecnologia
   XP                       Testes unitários
   Pair Programming         Testes de aceitação
   Smalltalk                TODO
   Testes de aceitação/       Continuous
   integração                 Integration
   Klaus Wustefeld            Testes de integração
O Curso

Test-Driven Development
Testes unitários, integração e funcionais
Foco nos fundamentos de testes automatizados
Uso de ferramentas apenas como suporte na
execução das atividades
O Curso

A prática do uso de testes automatizados
Demonstrações das vantagens da abordagem TDD no
curto prazo e dos testes automatizados no longo prazo
Esclarecimento de dúvidas comuns na implementação
de testes automatizados
Teste automatizado
... é o uso de software para controlar a
execução dos testes.
Testes automatizados
Unitários
Integração
Funcionais
Aceitação
Regressão
Outros: performance, estático, performance,
segurança, ...
Inventory




Unitário
Integração



      Order
              DB
                        Inventory



Unitário

                       Unitário
Funcionais




              Integração



              DB
      Order


                   Inventory

  Unitário
                   Unitário
Testes automatizados
Prós                  Contras
 Asseguram uma         Não garatem que o
 qualidade maior no    código é "bug free"
 código
                       Tempo de
 Garante que os        desenvolvimento e
 sistemas continuem    manutenção de
 funcionando após      aplicação tem um
 mudanças              pequeno aumento
Testes automatizados
No longo prazo sempre trazem benefícios
Quando usar?
  para testar código que já existe
  antes de iniciar uma refatoração
  durante o processo de bugfix
  antes de implementar o código (usado para guiar a
  implementação) — Test-Driven Development
Cobertura de código

Desejável 100%
Não existe ferramenta capaz de medir com 100% de
certeza a cobertura
Código 100% coberto != código sem bugs
Ferramenta: coverage.py
Test-Driven Development
Desenvolvimento guiado por testes
Test-Driven Development
Abreviação: TDD
Kent Beck: prática de




                        tr
                        ad
XP e depois em seu




                         uz
                             id o
livro Test-Driven
Development by
Examples
Utilização de testes
unitários na condução
do desenvolvimento
Test-Driven Development

TDD não é "ensinado".
TDD é "praticado"
Na fase de treinamento
é importante seguir as
regras. Depois
podemos quebrá-las.
  Baby Steps
Test-Driven Development


Uma linha de código só existe se tiver um teste a
avaliando
Altos índices de cobertura: >90%
Red. Green. Refactor.



   Escrever um               Fazer o
  teste que falha          teste passar



               Refatorar
Red.
Escrever um teste que inevitavelmente falhe
Se o teste não falhar?
  A nova funcionalidade já existe e,
  consequentemente, já deve ter sido testada.
    Mantê-lo é opcional mas se não tivermos
    segurança para removê-lo é melhor mantê-lo.
  Teste com problema
Green.
Escrever o mínimo de código que faça o teste passar
"Fake It ('Til you make it)" — valores 'hard coded' ou
objetos "fakes" no lugar de dependências ainda não
implementadas
Triangulate — implementação real quando você tem
dois ou mais exemplos
"Obvious Implementation ('Til you get red bars)" —
implementações óbvias podem ser feitas
Refactor.




                          tr
                          ad
 Refatoração:




                           uz
                               id o
   Aperfeiçoar o código
   sem alterar o seu
   comportamento
 Remover duplicação
 de código entre o
 código implementado
 e o teste
Testes unitários
Teste de uma unidade de código
Testes unitários
 Unidades de código: funções, métodos, classes, ...
   System Under Test (SUT) — código que está sendo
   testado
 Framework xUnit: unittest, nose e py.test
   Criado por Kent Beck para Smalltalk e
   posteriormente para Java (jUnit)
 Doctests — documentação "executável"
Testes unitários
 Ferramentas Python — http://j.mp/ptRk
 Unit Test e Runners: unittest, doctest, nose, py.test, ...
 Mockery: mocker, pyMock, pMock, Mock, mox, ...
 Functional/Acceptance: selenium, windmill, pyccuracy,
 twirl, django-client, ...
 Static: pylint, pyflakes, pychecker, ...
 Coverage: coverage
Testes unitários
 Usaremos:
  Ambiente virtual isolado: virtualenv
  Unit Test e Runners: unittest e nose
  Mockery: mocker
  Functional/Acceptance: selenium
  Coverage: coverage
Testes unitários

 Existe a possibilidade de usar outras ferramentas para
 os casos:
   Unittest e Runners: py.test
   Mockery: Mock
 Neste caso os exemplos precisarão ser feitos "na mão"
Primeira atividade
Hello World do mundo dos testes:
Converter um número para algarismos romanos
Primeira atividade
 Não existe zero    C = 100
 Algarísmos:        D = 500
   I=1              M = 1000
   V=5             Exemplo:
   X = 10           MCMLXXXIII = 1983
   L = 50           Casos especiais: 4, 9,
                    40, 90, 400, 900, ...
Preparando o ambiente
$ sudo easy_install virtualenv
ou
$ sudo pip install virtualenv

$ virtualenv tdd
New python executable in tdd/bin/python
Installing setuptools............done.

$ cd tdd
tdd/$ source bin/activate

(tdd)tdd/$ pip install nose coverage mocker
Downloading/unpacking nose
:
Downloading/unpacking coverage
:
Downloading/unpacking mocker
:

Installing collected packages: coverage, nose, mocker
:
Successfully installed coverage nose mocker
Cleaning up...
Nose
http://somethingaboutorange.com/mrl/projects/nose
Test Runner com discovery de testes:
  Se parece com um teste então é um teste :D
  Arquivos com 'test' no nome.
  Objetos TestCase, TestSuite e funções com 'test' no
  nome
  Funções 'avulsas' com 'test' no nome
Nose
Opcionalmente executa doctests:
  --with-doctest --doctest-extension=txt
Sistema de plugins e vários plugins third-parties:
  Usaremos: coverage (requer coverage.py), rednose
  Opcional: tdaemon + nose-growl
Configuração em ~/.nose.cfg ou em <proj>/setup.cfg
tdaemon + nose-growl
Para usuários de Mac:
  hg clone http://bitbucket.org/osantana/nosegrowl/
  hg clone http://bitbucket.org/osantana/tdaemon/
Instalar:
  (cd nosegrowl/nose-growl && python setup.py install)
  (cd tdaemon && python setup.py install)
Nose
nosetests package.module:TestCase.test_method
Configuração ~/.noserc
Testes unitários
 Etapas:
   Setup (setUp) — preapara o ambiente onde o teste
   será executado (fixtures)
   Exercise (test*) — executa o procedimento a ser
   testado
   Assert (assert*/verify) — verifica os resultados
   Teardown (tearDown) — limpa o ambiente
Testes unitários


 Dicas
   O melhor "primeiro teste" é o teste que verifica o
   caso de uso mais comum. O teste mais básico.
   Comece a escrever pelas "assertions"
Testes unitários
 Características
   Isolamento — testes são independentes
   Legibilidade — devem privilegiar legibilidade
   Velocidade — devem executar rapidamente
   Manutenabilidade — manutenção deve ser fácil
   Não intrusivos — código de teste deve ficar somente
   no teste e não no SUT
Testes unitários
 Isolamento
   Um teste devem funcionar de forma independente
   de outros testes e assumir um ambiente "limpo" para
   execução
   Todas as dependências do código testado devem
   ser subtituídas por "doubles" (fakes/stubs ou mocks)
     Mocks aren't Stubs - Martin Fowler
     http://bit.ly/mockrnstubs
Testes unitários
  Legibilidade
      O código do teste não precisa ser elegante, precisa
      ser legível. Testes são para "consumo" humano
      Resultados esperados em primeiro lugar:
                   Pior                                     Melhor

banco = Banco()                           banco = Banco()
banco.indice("USD", "BRL", TAXA_PADRAO)   banco.indice("USD", "BRL", TAXA_PADRAO)
banco.comissao(COMISSAO_PADRAO)           banco.comissao(COMISSAO_PADRAO)

res = banco.converte(                     res = banco.converte(
         Nota(100, "USD"), "BRL)                   Nota(100, "USD"), "BRL)

assert res == Nota(49.25, "BRL")          assert Nota(49.25, "BRL") == res
Testes unitários
  Legibilidade


      Dados evidentes: deixe a relação entre as entradas e
      os resultados aparente:
                   Pior                                     Melhor

                                          banco = Banco()
banco = Banco()
                                          banco.indice("USD", "BRL", 2.00)
banco.indice("USD", "BRL", TAXA_PADRAO)
                                          banco.comissao(0.015)
banco.comissao(COMISSAO_PADRAO)

                                          res = banco.converte(
res = banco.converte(
                                                   Nota(100, "USD"), "BRL)
         Nota(100, "USD"), "BRL)

                                          assert Nota(100 / 2 * (1 - 0.015), "BRL")
assert Nota(49.25, "BRL") == res
                                                   == res
Testes unitários
 Legibilidade
   Nome de teste: test_(pass|fail)_descricao_(invalid|
   with_x|without_y|basic)
   Apenas 1 ciclo setup/exercise/verify/teardown por
   teste
 A legibilidade sempre é subjetiva mas é importante
 estabelecer padrões em projetos desenvolvidos por
 equipes com vários desenvolvedores
Testes unitários

 Dicas
   O ciclo completo de red/green/refactor deve ser
   curto para privilegiar o ritmo.
   Se o teste está ficando grande: quebre-o em testes
   menores
Testes unitários
 Dicas
   Programando sozinho? Deixe o último teste
   "quebrado" no fim de uma sessão de programação
   para saber de onde retomar o desenvolvimento
   Programando em equipe? Faça 'commit' somente
   se todos os testes estiverem passando
   Usa um sistema de controle de versão distribuído?
   Deixe 'quebrado' localmente
Testes unitários
 Testabilidade
   Fácil testar: código bem desenhado, código criado
   com TDD, funções determinísticas, etc
   Difícil testar: GUI, código assíncrono, esquemas em
   banco de dados, componentes de aplicações
   distribuídas, funções não-determinísticas, etc
     Existem práticas e padrões que tornam alguns
     tipos de testes mais fáceis de serem feitos
Testes problemáticos
Test Smells
Testes problemáticos

Tipos de problemas:
  Code Smells — problemas relacionados com o
  código dos testes
  Behaviour Smells — problemas relacionados ao
  comportamento dos testes
Técnicas e padrões podem ser usados para resolver
esse tipo de problema
Problemas com
código dos testes
Code Smells
Teste obscuro
Dificuldade em entender o código do teste

                Causas                             Possíveis Soluções

Teste verifica muitas informações ao      Reduzir número de verificações
mesmo tempo

O número de objetos construídos no       Construir somente as fixtures necessárias
setup é maior que o necessário           para aquele teste

Interação com o SUT não se dá de forma Remover a indireção e testar o SUT
direta e sim através de um intermediário diretamente

Não é possível identificar o que está     Simplificar o processo de setup
sendo testado

Excesso de informações irrelevantes no   Partir da verificação e remover todos os
teste                                    objetos e informações desnecessárias
Lógica condicional
Código que pode ou não ser executado no teste

                Causas                               Possíveis Soluções

Teste verifica coisas diferentes            Desacoplar o SUT de suas dependências
dependendo de como executado               e/ou dividir o teste

Modificar o valor esperado numa             Criar testes individuais dedicados apenas
verificação dependendo de um caso           para os casos especiais e excluí-los do
especial                                   teste genérico

Restauração do ambiente é muito            Fazer a restauração do ambiente no
complexa e cheia de verificações            método tearDown no lugar de deixá-lo
                                           dentro do teste

Múltiplos testes condicionais no mesmo     Separando os testes para privilegiar a
teste percorrento uma collection (input,   localização de um problema eventual
output)
Código difícil de testar
Código é muito difícil de testar

               Causas                   Possíveis Soluções

Código extremamente acoplado   Desacoplar o código e parametrizar as
                               dependências para substituí-las por
                               objetos fake

Código assíncrono              Separar partes síncronas do código
                               assíncrono e testar somente esse código
Duplicação de código
O mesmo código de teste repetido muitas vezes

                 Causas                            Possíveis Soluções

Reproveitamento de código no estilo      Aplicar padrões de refatoração ao código
Copy & Paste                             do teste (ex. Extract Method)

"Reinvenção da Roda" - Escrita de        Aplicar padrões de refatoração ao código
trechos de testes já escrito por outra   do teste (ex. Extract Method)
pessoa
Lógica de teste no código
Código de teste no código sendo testado

                   Causas                        Possíveis Soluções

"Ganchos" para teste:                  Substituir o teste lógico por uma
if testing: ... else: ...              dependência que pode ser substituída
                                       por um objeto Fake.

Variações: dependências específicas     Refatorar o código para eliminar esse
para teste, reimplementações de        tipo de lógica por uma dependência que
métodos específicos para testes, etc.   pode ser substituída por um objeto Fake.
Problemas com
comportamento dos testes
Behaviour Smells
Roleta de verificações
Difícil saber qual verificação falhou

                Causas                              Possíveis Soluções

Teste "fominha": um único teste verifica   Dividir o teste em em vários
muitas funcionalidades

Não é possível identificar o problema      Acrescentar mensagens nos casos onde
com a mensagem da verificação quando       a verificação não usa valores constantes/
ela falha.                                referência como parâmetro. (ex. assert
                                          p1.x == p2.x, "coordenada x deveria ser
                                          igual")
Testes erráticos (I)
Testes se comportam erraticamente

               Causas                               Possíveis Soluções

Teste depende de outro e falha quando a   Remover a dependência copiando-a
ordem de execução muda ou o teste         para o teste em questão ou fazendo os
quando é executado sozinho                dois compartilharem as mesmas fixtures

Mais de um teste roda simultaneamente     Cada teste deve rodar em seu próprio
compartilhando o mesmo ambiente           ambiente.


Testes vão ficando mais lentos ou          Se o problema estiver no SUT o certo é
ocupando mais recursos da máquina         corrigir o bug. Se estiver no teste o bug
                                          está no processo de tearDown

Testes dependem de recursos externos      Criar uma cópia deste recurso
que podem estar indisponíveis             localmente ou substituí-lo por um stub.
Testes erráticos (II)
Testes se comportam erraticamente

                Causas                               Possíveis Soluções

Teste passa na primeira execução e         O teste não está restaurando o ambiente
depois falha sucessivamente                inicial corretamente.

Teste falha aleatoriamente quando várias   Criar ambientes de teste individuais
pessoas executam testes
simultaneamente.

Teste falha aleatoriamente mesmo com       Tentar eliminar, dentro do possível, os
uma pessoa executando ele por estar        elementos determinísticos do teste.
testando código não-determinístico
Depuração manual
Depuração manual para localizar problemas

               Causas                            Possíveis Soluções

Existência de código sem cobertura de   Providenciar a cobertura do código em
teste                                   questão
Intervenção Manual
Intervenção manual na execução dos testes

                Causas                             Possíveis Soluções

O teste foi construído sem ter em mente   Automatizar todo o processo
que "teste automatizado" implica que
não deve existir "intervenção manual"
Testes lentos
Testes demoram para executar

                Causas                             Possíveis Soluções

O teste depende de recursos externos     Tentar substituir esse recurso por um
que têm uma latência muito alta          objeto fake

Testes executam fixtures muito extensas   A solução ideal é simplificar a construção
para cada um dos cenários                dessas fixtures. Não sendo possível fazer
                                         isso permita que os testes compartilhem
                                         as fixtures

Teste acrescenta explicitamente um       Extrair a parte síncrona do código e
intervalo para lidar com código          testar somente ela
assíncrono

Muitos testes                            Não é necessário executar todos os
                                         testes o tempo todo
Padrões de
teste
Práticas e padrões
para uso em testes
Padrões…
… de estratégia           … para banco de dados
… básicos xUnit           … de desenho para
                          testabilidade
… para setup de fixtures
… de verificação
… para teardown
… com objetos falsos
Padrões de estratégia
Test Strategy Patterns
Estratégia de Automação
Recorded Test — usam a estratégia grava & reproduz.
ex. Selenium IDE, Sikuli, etc
Data-Driven Test — úteis para testar parsers,
conversores de formatos, etc. ex. teste de um crawler
Scripted Test — cria-se um programa especificamente
para testar outro
Test Automation Framework — é um tipo de programa
de testes mas usa um framework para isso. ex. xUnit
Estratégia para fixtures
 Minimal Fixture — todo teste precisa de fixtures, com
 essa estratégia cria-se o mínimo necessário para
 executar apenas o teste em questão
 Standard Fixture — testes compartilham um método
 que cria as fixtures usadas por eles
 Fresh Fixture — teste constrói as suas próprias fixtures
 Shared Fixture — testes compartilham as mesmas
 fixtures
Estratégia de Interação

 Back Door Manipulation (ui!) — nos casos onde não é
 possível avaliar o funcionamento do SUT diretamente
 as verificações são feitas com os dados das fixtures.
 Ex. verificar se o SUT manipulou os dados do banco
 de dados corretamente.
 Layer Test — escrever testes para cada uma das
 camadas de uma aplicação com várias camadas. Ex.
 testar o 'driver' do DB, o ORM, os objetos model, etc
Padrões básicos xUnit
xUnit Basics Patterns
Definição dos testes

Test Method — um cenário de teste por método
  Four-Phase Test — setup, exercise, assert, teardown
Assertion Method — métodos de verificação (.assert*())
  Assertion Message — exibida quando a verificação
  falha
Testcase Class — agrupamento de testes relacionados
Execução dos testes
Test Runner — aplicação que executa os testes e
mostra os resultados
Testcase object — instância contendo um conjunto de
testes relacionados
Test Suite object — objeto com a mesma interface de
Testcase que agrupa um ou mais objetos Testcase
Test Discovery — mecanismo pelo qual o Test Runner
encontra os testes
Padrões para setup de
fixtures
Fixture Setup Patterns
Setup de Fresh Fixtures

 In-Line Setup — cada teste constrói suas fixtures por
 conta própria
 Delegated Setup — testes constroem suas fixtures
 chamando um método auxiliar
 Implicit Setup — a construção das fixtures é implicita e
 executada dentro do método .setUp()
Criação compartilhada

Prebuilt Fixture — as fixtures são compartilhadas pelos
testes e são construídas por outro componente. Ex. ./
manage.py loaddata data.json do Django
Suite Fixture Setup — fixtures construídas no .setUp()
da suíte e não no Testcase
Padrões de verificação de
resultados
Result Verification Patterns
Estratégia de verificação

 State Verification — verificamos o estado do SUT após
 o exercício. Ex. sut.set(1); assert sut.get() == 1
 Behaviour Verification — verificamos os resultados
 indiretos após o exercício do SUT. Ex. web.open
 ("http://j.mp", mock); mocker.verify()
Estilos de verificação
 Custom Assertion — criamos uma verificação
 personalizada. Ex. chk(d, r) { assert r == roman(d) }
 Delta Assertion — verificamos a diferença do objeto
 antes do exercício e depois de exercitá-lo
 Guard Assertion — verifica o resultado com if. No caso
 de erro executa uma falha explicitamente.
 Unfinished Test Assertion — força falha pra indicar que
 o teste não está pronto
Padrões para teardown
Fixture Teardown Patterns
Estratégia para teardown

Garbage-Collected Teardown — deixar o garbage
collector da linguagem fazer a limpeza do ambiente
Automated Teardown — registramos a criação de
todos os objetos no setup para removê-los na fase de
teardown
Organização do código


In-line Teardown — a limpeza do ambiente é feita no
próprio teste
Implicit Teardown — a limpeza do ambiente fica por
conta do método .tearDown()
Padrões com objetos falsos
Test Double Patterns
Exemplo de código
Exemplo de código
                    Dependência
Testes falham
Testes falham



                AM !
        FA L H
Test Double
Substituir uma ou mais dependências do SUT por um
equivalente específico para o teste:

                   Test Double




 Dummy      Test                 Mock      Fake
                    Test Spy
 Object     Stub                 Object   Object
Dummy


Geralmente são valores que não são usados no teste.
Algumas vezes são apenas passados como
parâmetros para atender ao número de parâmetros de
um método.
Fake
Uma implementação funcional do objeto original
Stubs

Similares aos objetos Fake
Não tem uma implementação funcional, apenas
retorna valores pré-estabelecidos
Podem gerar uma exceção para testar comportamento
do SUT nessa situação
Ex: Simular um erro de timeout na conexão com um
banco de dados
Spy


Similares aos objetos Stub
Registram chamadas para seus métodos para que seja
possível fazer uma verificação indireta posteriormente
Ex. Servidor de e-mail que registra e-mails "enviados"
Mock



Tipo especial de objeto que pode ser programado com
as expectativas de chamadas e retornos
Fonte: Growing Object-Oriented Software, Guided by Tests




Mock
Rede de objetos
Fonte: Growing Object-Oriented Software, Guided by Tests




Mock
Testando objeto
isoladamente
Fonte: Growing Object-Oriented Software, Guided by Tests




Mock
Testando com um
objeto mock
Fonte: Growing Object-Oriented Software, Guided by Tests




Mock
Testando com um
objeto mock
Mocker

http://labix.org/mocker
Desenvolvida pelo brasileiro Gustavo Niemeyer
Usa a estratégia Record (para especificar as
expectativas e retornos) & Play (para verificar os
resultados)
Mock
Mocker
Padrões para banco de
dados
Database Patterns
Padrões de banco de dados
Database Sandbox — cada desenvolvedor tem um
banco de dados à sua disposição (ex. Django SQLite in
memory)
Table Truncate Teardown — truncar as tabelas na fase
do teardown
Transaction Rollback Teardown — iniciar uma
transação na fase de setup e efetuar um rollback na
fase de teardown. Deve-se cuidar para que não tenha
nenhum commit no SUT
Padrões de desenho para
testabilidade
Design-for-Testability Patterns
Padrões para testabilidade
 Dependency Injection — permite substituir
 dependências do SUT por Test Doubles.
   A dependência pode ser passada na construção ou
   como parâmetro do método.
   Ex. O objeto TimeDisplay depende de TimeProvider
   que, nos testes, é substituído por stub/mock
 Dependency Lookup — o objeto busca suas
 dependências em um local específico. Ex. registro, dict
Padrões para testabilidade
                                         Exemplo!
                                         pag. 764 do xunit

 Humble object — extrair a lógica num componente
 separado e mais fácil de testar.
   Ex. extrair a parte síncrona de um objeto com
   operações assíncronas
   Pode-se usar um método no lugar de um objeto
 Test Hook — não use: adicionar lógica condicional no
 SUT para se comportar de modo específico com os
 testes
Desenvolvendo aplicações
Desenvolvendo aplicações completas usando
Test-Driven Development
Desenvolvendo aplicações
Testes de aceitação
  Validar requisitos dos
  clientes
  Selenium2,
  Pyccuracy, Windmill,
  Django Client, etc.
Inicia ciclo red/green/
refactor
Desenvolvendo aplicações


   Escrever um
teste de aceitação    Escrever um          Fazer o
                     teste que falha     teste passar
     que falha
                                  Refatorar
Desenvolvendo aplicações
                                       Se surgir alguma idéia
                                       nova para outro teste:
                                          anote no papel



   Escrever um
teste de aceitação    Escrever um             Fazer o
                     teste que falha        teste passar
     que falha
                                  Refatorar
Atividade
Pastebin-like
Codb.in
Usuário submete o código e a linguagem
Uma URL curta é gerada
O usuário é encaminhado para o Twitter:
  http://twitter.com/home?status=???
Usaremos a biblioteca Pygments
Google App Engine
Resumo
Sumário dos tópicos abordados
Resumo

Testes são isolados
A ordem dos testes não é garantida
Não se deve adicionar lógica de teste no código de
produção
Testes devem assumir um ambiente limpo quando
começam e limpar o ambiente quando terminam
Resumo


red / green / refactor
setup, exercise, verify, teardown
F.A.Q.

 Quando sei que os testes são suficientes?
   Quando você tiver certeza que seu software está
   completo e sem bugs: nunca serão.
 Quando eu preciso fazer testes:
   Resposta curta: sempre. Resposta longa: quando
   você não tiver segurança total daquilo que precisa
   ser feito
F.A.Q.
 Qual o tamanho ideal de um baby-step?
   Resposta curta: do tamanho que te dê segurança.
   Resposta longa: TDD é uma prática e como tal
   requer treino. O ideal é que no início se use passos
   pequenos e posteriormente aumentá-los.
 Existe uma relação direta entre a cobertura de testes e
 a quantidade de bugs num código?
   Existe essa relação mas ela não é linear.
Mensagens
Teste é algo desejável num software. Melhor se forem
automatizados e ótimos se o código foi feito depois do
teste
Falácia: "Código não testado é código bugado"
  Não existe bala de prata, logo, teste automatizado
  não é uma delas
  Atenção para os "radicais do teste". Radicalismo
  nunca é bom para um programador
Leitura complementar
Não terminamos por aqui...
Leitura Complementar
Internet
  TDD @ Wikipedia — http://j.mp/zBGgt
  Mocks aren't Stubs — http://j.mp/7MdzF
  Inversion of Control and Dependency Injection —
  http://j.mp/I0YAA
Leitura Complementar
Atividade opcional
Coding-Dojo
Coding-Dojo
O melhor modo de aprender um jogo é jogando
Coding-Dojo
Escolha do desafio           Todos participam
Pair programming em         Solução construidas na
uma máquina                 hora (não vale usar
                            bibliotecas dedicadas)
Piloto codifica a solução
usando TDD                  Design reviews em
                            intervalos
Co-piloto troca com
piloto em intervalos de 5   Piloto deve descrever o
minutos                     que está fazendo
Coding-Dojo
O piloto pode pedir         Análise de pontos
ajuda para o co-piloto ou   positivos e negativos
para a platéia              após a sessão
A experiência é mais        No Brasil criou-se o
importante que a            #horaextra: uma "happy
solução do problema         hour" após o Dojo
Sessões com tempo fixo       Mais informações:
                            http://codingdojo.org/
Sugestões de problemas

Mão de poker
Mostrador LCD
Valor por extenso
Caixa empilhadas

Mais conteúdo relacionado

Mais procurados

Banco de Dados II Aula 02 - Modelagem de Dados (Definição, Modelo conceitual)
Banco de Dados II  Aula 02 - Modelagem de Dados (Definição, Modelo conceitual)Banco de Dados II  Aula 02 - Modelagem de Dados (Definição, Modelo conceitual)
Banco de Dados II Aula 02 - Modelagem de Dados (Definição, Modelo conceitual)Leinylson Fontinele
 
Introdução à Engenharia de Software
Introdução à Engenharia de SoftwareIntrodução à Engenharia de Software
Introdução à Engenharia de SoftwareNécio de Lima Veras
 
tmn - Introdução ao JavaScript
tmn - Introdução ao JavaScripttmn - Introdução ao JavaScript
tmn - Introdução ao JavaScriptClaudio Gamboa
 
Testes de Software
Testes de SoftwareTestes de Software
Testes de SoftwareCapgemini
 
Aula 1 - Introdução a Engenharia de Software
Aula 1 -  Introdução a Engenharia de SoftwareAula 1 -  Introdução a Engenharia de Software
Aula 1 - Introdução a Engenharia de SoftwareLeinylson Fontinele
 
Introdução à Qualidade e Testes Ágeis de Software
Introdução à Qualidade e Testes Ágeis de SoftwareIntrodução à Qualidade e Testes Ágeis de Software
Introdução à Qualidade e Testes Ágeis de SoftwareClaudia Melo
 
Estrutura de Dados - Aula 02
Estrutura de Dados - Aula 02Estrutura de Dados - Aula 02
Estrutura de Dados - Aula 02thomasdacosta
 
Algoritmos e Estrutura de Dados - Aula 01
Algoritmos e Estrutura de Dados - Aula 01Algoritmos e Estrutura de Dados - Aula 01
Algoritmos e Estrutura de Dados - Aula 01thomasdacosta
 
Introdução a estruturas de dados em python
Introdução a estruturas de dados em pythonIntrodução a estruturas de dados em python
Introdução a estruturas de dados em pythonAlvaro Oliveira
 
Tutorial Django + Python
Tutorial Django + PythonTutorial Django + Python
Tutorial Django + PythonMateus Padua
 
Desenvolvimento orientado a testes - TDD
Desenvolvimento orientado a testes - TDDDesenvolvimento orientado a testes - TDD
Desenvolvimento orientado a testes - TDDwashingtonlslima
 
Engenharia de requisitos
Engenharia de requisitosEngenharia de requisitos
Engenharia de requisitosMailson Queiroz
 
Python e django na prática
Python e django na práticaPython e django na prática
Python e django na práticaRafael Cassau
 
Estrutura de Dados - Aula 01 - Apresentação
Estrutura de Dados - Aula 01 - ApresentaçãoEstrutura de Dados - Aula 01 - Apresentação
Estrutura de Dados - Aula 01 - ApresentaçãoLeinylson Fontinele
 

Mais procurados (20)

Projeto de Software
Projeto de SoftwareProjeto de Software
Projeto de Software
 
Banco de Dados II Aula 02 - Modelagem de Dados (Definição, Modelo conceitual)
Banco de Dados II  Aula 02 - Modelagem de Dados (Definição, Modelo conceitual)Banco de Dados II  Aula 02 - Modelagem de Dados (Definição, Modelo conceitual)
Banco de Dados II Aula 02 - Modelagem de Dados (Definição, Modelo conceitual)
 
Introdução à Engenharia de Software
Introdução à Engenharia de SoftwareIntrodução à Engenharia de Software
Introdução à Engenharia de Software
 
Analise Algoritmos
Analise AlgoritmosAnalise Algoritmos
Analise Algoritmos
 
tmn - Introdução ao JavaScript
tmn - Introdução ao JavaScripttmn - Introdução ao JavaScript
tmn - Introdução ao JavaScript
 
Testes de Software
Testes de SoftwareTestes de Software
Testes de Software
 
Aula 1 - Introdução a Engenharia de Software
Aula 1 -  Introdução a Engenharia de SoftwareAula 1 -  Introdução a Engenharia de Software
Aula 1 - Introdução a Engenharia de Software
 
Introdução à Qualidade e Testes Ágeis de Software
Introdução à Qualidade e Testes Ágeis de SoftwareIntrodução à Qualidade e Testes Ágeis de Software
Introdução à Qualidade e Testes Ágeis de Software
 
Python Interface Gráfica Tkinter
Python Interface Gráfica TkinterPython Interface Gráfica Tkinter
Python Interface Gráfica Tkinter
 
Estrutura de Dados - Aula 02
Estrutura de Dados - Aula 02Estrutura de Dados - Aula 02
Estrutura de Dados - Aula 02
 
Aula03 - JavaScript
Aula03 - JavaScriptAula03 - JavaScript
Aula03 - JavaScript
 
Arquitetura de Software
Arquitetura de SoftwareArquitetura de Software
Arquitetura de Software
 
Algoritmos e Estrutura de Dados - Aula 01
Algoritmos e Estrutura de Dados - Aula 01Algoritmos e Estrutura de Dados - Aula 01
Algoritmos e Estrutura de Dados - Aula 01
 
Introdução a estruturas de dados em python
Introdução a estruturas de dados em pythonIntrodução a estruturas de dados em python
Introdução a estruturas de dados em python
 
Tutorial Django + Python
Tutorial Django + PythonTutorial Django + Python
Tutorial Django + Python
 
Desenvolvimento orientado a testes - TDD
Desenvolvimento orientado a testes - TDDDesenvolvimento orientado a testes - TDD
Desenvolvimento orientado a testes - TDD
 
Engenharia de requisitos
Engenharia de requisitosEngenharia de requisitos
Engenharia de requisitos
 
Curso de Python e Django
Curso de Python e DjangoCurso de Python e Django
Curso de Python e Django
 
Python e django na prática
Python e django na práticaPython e django na prática
Python e django na prática
 
Estrutura de Dados - Aula 01 - Apresentação
Estrutura de Dados - Aula 01 - ApresentaçãoEstrutura de Dados - Aula 01 - Apresentação
Estrutura de Dados - Aula 01 - Apresentação
 

Semelhante a TDD com Python (Completo)

TDD em django sem desculpas versao fisl
TDD em django sem desculpas versao fislTDD em django sem desculpas versao fisl
TDD em django sem desculpas versao fislAdriano Petrich
 
Tdd em django sem desculpas versao final
Tdd em django sem desculpas versao finalTdd em django sem desculpas versao final
Tdd em django sem desculpas versao finalAdriano Petrich
 
Paletra sobre TDD, ocorrida no #DevDojo
Paletra sobre TDD, ocorrida no #DevDojoPaletra sobre TDD, ocorrida no #DevDojo
Paletra sobre TDD, ocorrida no #DevDojoflavio1110
 
Padrões para Desenvolvimento de Software Guiado por Testes
Padrões para Desenvolvimento de Software Guiado por TestesPadrões para Desenvolvimento de Software Guiado por Testes
Padrões para Desenvolvimento de Software Guiado por TestesEverton Rodrigues
 
Introdução a testes automatizados
Introdução a testes automatizadosIntrodução a testes automatizados
Introdução a testes automatizadosThiago Ghisi
 
ALM - Testes Manuais no Microsoft Test Manager
ALM - Testes Manuais no Microsoft Test ManagerALM - Testes Manuais no Microsoft Test Manager
ALM - Testes Manuais no Microsoft Test ManagerAlan Carlos
 
Treinamento Testes Unitários - parte 1
Treinamento Testes Unitários - parte 1Treinamento Testes Unitários - parte 1
Treinamento Testes Unitários - parte 1Diego Pacheco
 
Desenvolvimento Dirigido por Testes
Desenvolvimento Dirigido por TestesDesenvolvimento Dirigido por Testes
Desenvolvimento Dirigido por TestesCamilo Ribeiro
 
Palestra Testes Unidade Com JUnit
Palestra Testes Unidade Com JUnitPalestra Testes Unidade Com JUnit
Palestra Testes Unidade Com JUnitRobinson Castilho
 
Testes com javascript
Testes com javascriptTestes com javascript
Testes com javascriptLaís Lima
 
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...O que seus testes garantem, o funcionamento do código ou das funcionalidades ...
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...Isaac de Souza
 
TDD - Pós Graduação em Engenharia de Software Ágil
TDD - Pós Graduação em Engenharia de Software ÁgilTDD - Pós Graduação em Engenharia de Software Ágil
TDD - Pós Graduação em Engenharia de Software ÁgilBruno Eustáquio
 
ybr789try
ybr789tryybr789try
ybr789tryteste
 
Testes de software
Testes de softwareTestes de software
Testes de softwareteste
 

Semelhante a TDD com Python (Completo) (20)

TDD em django sem desculpas versao fisl
TDD em django sem desculpas versao fislTDD em django sem desculpas versao fisl
TDD em django sem desculpas versao fisl
 
JUnit Sample
JUnit SampleJUnit Sample
JUnit Sample
 
TDD com Python
TDD com PythonTDD com Python
TDD com Python
 
Tdd em django sem desculpas versao final
Tdd em django sem desculpas versao finalTdd em django sem desculpas versao final
Tdd em django sem desculpas versao final
 
Paletra sobre TDD, ocorrida no #DevDojo
Paletra sobre TDD, ocorrida no #DevDojoPaletra sobre TDD, ocorrida no #DevDojo
Paletra sobre TDD, ocorrida no #DevDojo
 
Padrões para Desenvolvimento de Software Guiado por Testes
Padrões para Desenvolvimento de Software Guiado por TestesPadrões para Desenvolvimento de Software Guiado por Testes
Padrões para Desenvolvimento de Software Guiado por Testes
 
Introdução a testes automatizados
Introdução a testes automatizadosIntrodução a testes automatizados
Introdução a testes automatizados
 
Testes de Sofware
Testes de SofwareTestes de Sofware
Testes de Sofware
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
 
ALM - Testes Manuais no Microsoft Test Manager
ALM - Testes Manuais no Microsoft Test ManagerALM - Testes Manuais no Microsoft Test Manager
ALM - Testes Manuais no Microsoft Test Manager
 
Treinamento Testes Unitários - parte 1
Treinamento Testes Unitários - parte 1Treinamento Testes Unitários - parte 1
Treinamento Testes Unitários - parte 1
 
O que é Teste de Software?
O que é Teste de Software?O que é Teste de Software?
O que é Teste de Software?
 
Desenvolvimento Dirigido por Testes
Desenvolvimento Dirigido por TestesDesenvolvimento Dirigido por Testes
Desenvolvimento Dirigido por Testes
 
Palestra Testes Unidade Com JUnit
Palestra Testes Unidade Com JUnitPalestra Testes Unidade Com JUnit
Palestra Testes Unidade Com JUnit
 
Testes com javascript
Testes com javascriptTestes com javascript
Testes com javascript
 
Introdução a tdd
Introdução a tddIntrodução a tdd
Introdução a tdd
 
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...O que seus testes garantem, o funcionamento do código ou das funcionalidades ...
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...
 
TDD - Pós Graduação em Engenharia de Software Ágil
TDD - Pós Graduação em Engenharia de Software ÁgilTDD - Pós Graduação em Engenharia de Software Ágil
TDD - Pós Graduação em Engenharia de Software Ágil
 
ybr789try
ybr789tryybr789try
ybr789try
 
Testes de software
Testes de softwareTestes de software
Testes de software
 

Mais de Osvaldo Santana Neto

Contruindo um Framework Web de Brinquedo só com Python
Contruindo um Framework Web de Brinquedo só com PythonContruindo um Framework Web de Brinquedo só com Python
Contruindo um Framework Web de Brinquedo só com PythonOsvaldo Santana Neto
 
Dave Thomas - Agile is Dead (GOTO 2015)
Dave Thomas - Agile is Dead (GOTO 2015)Dave Thomas - Agile is Dead (GOTO 2015)
Dave Thomas - Agile is Dead (GOTO 2015)Osvaldo Santana Neto
 
Como funciona um time remoto de desenvolvimento - Caipyra 2018
Como funciona um time remoto de desenvolvimento - Caipyra 2018Como funciona um time remoto de desenvolvimento - Caipyra 2018
Como funciona um time remoto de desenvolvimento - Caipyra 2018Osvaldo Santana Neto
 
Escalando times através do trabalho remoto
Escalando times através do trabalho remotoEscalando times através do trabalho remoto
Escalando times através do trabalho remotoOsvaldo Santana Neto
 
Plataforma distribuída de Microserviços ou, como a Olist funciona
Plataforma distribuída de Microserviços ou, como a Olist funcionaPlataforma distribuída de Microserviços ou, como a Olist funciona
Plataforma distribuída de Microserviços ou, como a Olist funcionaOsvaldo Santana Neto
 
Real Life Hackers @ PechaKucha 20x20
Real Life Hackers @ PechaKucha 20x20Real Life Hackers @ PechaKucha 20x20
Real Life Hackers @ PechaKucha 20x20Osvaldo Santana Neto
 
De Zero à Web com Python e Django
De Zero à Web com Python e DjangoDe Zero à Web com Python e Django
De Zero à Web com Python e DjangoOsvaldo Santana Neto
 
Entendiendo Unicode (Facundo Batista)
Entendiendo Unicode (Facundo Batista)Entendiendo Unicode (Facundo Batista)
Entendiendo Unicode (Facundo Batista)Osvaldo Santana Neto
 
Como me tornei um empreendedor pythonista
Como me tornei um empreendedor pythonistaComo me tornei um empreendedor pythonista
Como me tornei um empreendedor pythonistaOsvaldo Santana Neto
 
Matando (ou quase) Unicode(De|En)codeErrors (lightning talk)
Matando (ou quase) Unicode(De|En)codeErrors (lightning talk)Matando (ou quase) Unicode(De|En)codeErrors (lightning talk)
Matando (ou quase) Unicode(De|En)codeErrors (lightning talk)Osvaldo Santana Neto
 
Ludeos - Venda seu conteúdo online (how it works)
Ludeos - Venda seu conteúdo online (how it works)Ludeos - Venda seu conteúdo online (how it works)
Ludeos - Venda seu conteúdo online (how it works)Osvaldo Santana Neto
 
App Engine: aplicações escaláveis em poucas horas
App Engine: aplicações escaláveis em poucas horasApp Engine: aplicações escaláveis em poucas horas
App Engine: aplicações escaláveis em poucas horasOsvaldo Santana Neto
 
Desenvolvimento RAD com Python (Fenasoft)
Desenvolvimento RAD com Python (Fenasoft)Desenvolvimento RAD com Python (Fenasoft)
Desenvolvimento RAD com Python (Fenasoft)Osvaldo Santana Neto
 

Mais de Osvaldo Santana Neto (20)

Basic Brainf*ck
Basic Brainf*ckBasic Brainf*ck
Basic Brainf*ck
 
Contruindo um Framework Web de Brinquedo só com Python
Contruindo um Framework Web de Brinquedo só com PythonContruindo um Framework Web de Brinquedo só com Python
Contruindo um Framework Web de Brinquedo só com Python
 
A Web é uma API
A Web é uma APIA Web é uma API
A Web é uma API
 
Dave Thomas - Agile is Dead (GOTO 2015)
Dave Thomas - Agile is Dead (GOTO 2015)Dave Thomas - Agile is Dead (GOTO 2015)
Dave Thomas - Agile is Dead (GOTO 2015)
 
Olist Architecture v2.0
Olist Architecture v2.0Olist Architecture v2.0
Olist Architecture v2.0
 
Advanced Brainf*ck
Advanced Brainf*ckAdvanced Brainf*ck
Advanced Brainf*ck
 
Corrigindo Bugs no CPython
Corrigindo Bugs no CPythonCorrigindo Bugs no CPython
Corrigindo Bugs no CPython
 
Como funciona um time remoto de desenvolvimento - Caipyra 2018
Como funciona um time remoto de desenvolvimento - Caipyra 2018Como funciona um time remoto de desenvolvimento - Caipyra 2018
Como funciona um time remoto de desenvolvimento - Caipyra 2018
 
Escalando times através do trabalho remoto
Escalando times através do trabalho remotoEscalando times através do trabalho remoto
Escalando times através do trabalho remoto
 
Plataforma distribuída de Microserviços ou, como a Olist funciona
Plataforma distribuída de Microserviços ou, como a Olist funcionaPlataforma distribuída de Microserviços ou, como a Olist funciona
Plataforma distribuída de Microserviços ou, como a Olist funciona
 
Real Life Hackers @ PechaKucha 20x20
Real Life Hackers @ PechaKucha 20x20Real Life Hackers @ PechaKucha 20x20
Real Life Hackers @ PechaKucha 20x20
 
De Zero à Web com Python e Django
De Zero à Web com Python e DjangoDe Zero à Web com Python e Django
De Zero à Web com Python e Django
 
Entendiendo Unicode (Facundo Batista)
Entendiendo Unicode (Facundo Batista)Entendiendo Unicode (Facundo Batista)
Entendiendo Unicode (Facundo Batista)
 
Como me tornei um empreendedor pythonista
Como me tornei um empreendedor pythonistaComo me tornei um empreendedor pythonista
Como me tornei um empreendedor pythonista
 
Matando (ou quase) Unicode(De|En)codeErrors (lightning talk)
Matando (ou quase) Unicode(De|En)codeErrors (lightning talk)Matando (ou quase) Unicode(De|En)codeErrors (lightning talk)
Matando (ou quase) Unicode(De|En)codeErrors (lightning talk)
 
Ludeos - Venda seu conteúdo online (how it works)
Ludeos - Venda seu conteúdo online (how it works)Ludeos - Venda seu conteúdo online (how it works)
Ludeos - Venda seu conteúdo online (how it works)
 
App Engine: aplicações escaláveis em poucas horas
App Engine: aplicações escaláveis em poucas horasApp Engine: aplicações escaláveis em poucas horas
App Engine: aplicações escaláveis em poucas horas
 
Programação RAD com Python
Programação RAD com PythonProgramação RAD com Python
Programação RAD com Python
 
Desenvolvimento RAD com Python (Fenasoft)
Desenvolvimento RAD com Python (Fenasoft)Desenvolvimento RAD com Python (Fenasoft)
Desenvolvimento RAD com Python (Fenasoft)
 
Curso Python for S60
Curso Python for S60Curso Python for S60
Curso Python for S60
 

Último

ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docxATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx2m Assessoria
 
Padrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploPadrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploDanilo Pinotti
 
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx2m Assessoria
 
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docxATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx2m Assessoria
 
Boas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsBoas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsDanilo Pinotti
 
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docxATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx2m Assessoria
 

Último (6)

ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docxATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
 
Padrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploPadrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemplo
 
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
 
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docxATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
 
Boas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsBoas práticas de programação com Object Calisthenics
Boas práticas de programação com Object Calisthenics
 
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docxATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
 

TDD com Python (Completo)

  • 1. Testes Versão Python Osvaldo Santana Neto osantana@triveos.com
  • 2. Osvaldo Santana Neto Programador amador desde 1988 Programador profissional desde 1991 Programador Python desde 2000 Programador Django desde 2008
  • 3. Eu e os testes... Objective Solutions Triveos Tecnologia XP Testes unitários Pair Programming Testes de aceitação Smalltalk TODO Testes de aceitação/ Continuous integração Integration Klaus Wustefeld Testes de integração
  • 4. O Curso Test-Driven Development Testes unitários, integração e funcionais Foco nos fundamentos de testes automatizados Uso de ferramentas apenas como suporte na execução das atividades
  • 5. O Curso A prática do uso de testes automatizados Demonstrações das vantagens da abordagem TDD no curto prazo e dos testes automatizados no longo prazo Esclarecimento de dúvidas comuns na implementação de testes automatizados
  • 6. Teste automatizado ... é o uso de software para controlar a execução dos testes.
  • 9. Integração Order DB Inventory Unitário Unitário
  • 10. Funcionais Integração DB Order Inventory Unitário Unitário
  • 11. Testes automatizados Prós Contras Asseguram uma Não garatem que o qualidade maior no código é "bug free" código Tempo de Garante que os desenvolvimento e sistemas continuem manutenção de funcionando após aplicação tem um mudanças pequeno aumento
  • 12. Testes automatizados No longo prazo sempre trazem benefícios Quando usar? para testar código que já existe antes de iniciar uma refatoração durante o processo de bugfix antes de implementar o código (usado para guiar a implementação) — Test-Driven Development
  • 13. Cobertura de código Desejável 100% Não existe ferramenta capaz de medir com 100% de certeza a cobertura Código 100% coberto != código sem bugs Ferramenta: coverage.py
  • 15. Test-Driven Development Abreviação: TDD Kent Beck: prática de tr ad XP e depois em seu uz id o livro Test-Driven Development by Examples Utilização de testes unitários na condução do desenvolvimento
  • 16. Test-Driven Development TDD não é "ensinado". TDD é "praticado" Na fase de treinamento é importante seguir as regras. Depois podemos quebrá-las. Baby Steps
  • 17. Test-Driven Development Uma linha de código só existe se tiver um teste a avaliando Altos índices de cobertura: >90%
  • 18. Red. Green. Refactor. Escrever um Fazer o teste que falha teste passar Refatorar
  • 19. Red. Escrever um teste que inevitavelmente falhe Se o teste não falhar? A nova funcionalidade já existe e, consequentemente, já deve ter sido testada. Mantê-lo é opcional mas se não tivermos segurança para removê-lo é melhor mantê-lo. Teste com problema
  • 20. Green. Escrever o mínimo de código que faça o teste passar "Fake It ('Til you make it)" — valores 'hard coded' ou objetos "fakes" no lugar de dependências ainda não implementadas Triangulate — implementação real quando você tem dois ou mais exemplos "Obvious Implementation ('Til you get red bars)" — implementações óbvias podem ser feitas
  • 21. Refactor. tr ad Refatoração: uz id o Aperfeiçoar o código sem alterar o seu comportamento Remover duplicação de código entre o código implementado e o teste
  • 22. Testes unitários Teste de uma unidade de código
  • 23. Testes unitários Unidades de código: funções, métodos, classes, ... System Under Test (SUT) — código que está sendo testado Framework xUnit: unittest, nose e py.test Criado por Kent Beck para Smalltalk e posteriormente para Java (jUnit) Doctests — documentação "executável"
  • 24. Testes unitários Ferramentas Python — http://j.mp/ptRk Unit Test e Runners: unittest, doctest, nose, py.test, ... Mockery: mocker, pyMock, pMock, Mock, mox, ... Functional/Acceptance: selenium, windmill, pyccuracy, twirl, django-client, ... Static: pylint, pyflakes, pychecker, ... Coverage: coverage
  • 25. Testes unitários Usaremos: Ambiente virtual isolado: virtualenv Unit Test e Runners: unittest e nose Mockery: mocker Functional/Acceptance: selenium Coverage: coverage
  • 26. Testes unitários Existe a possibilidade de usar outras ferramentas para os casos: Unittest e Runners: py.test Mockery: Mock Neste caso os exemplos precisarão ser feitos "na mão"
  • 27. Primeira atividade Hello World do mundo dos testes: Converter um número para algarismos romanos
  • 28. Primeira atividade Não existe zero C = 100 Algarísmos: D = 500 I=1 M = 1000 V=5 Exemplo: X = 10 MCMLXXXIII = 1983 L = 50 Casos especiais: 4, 9, 40, 90, 400, 900, ...
  • 29. Preparando o ambiente $ sudo easy_install virtualenv ou $ sudo pip install virtualenv $ virtualenv tdd New python executable in tdd/bin/python Installing setuptools............done. $ cd tdd tdd/$ source bin/activate (tdd)tdd/$ pip install nose coverage mocker Downloading/unpacking nose : Downloading/unpacking coverage : Downloading/unpacking mocker : Installing collected packages: coverage, nose, mocker : Successfully installed coverage nose mocker Cleaning up...
  • 30. Nose http://somethingaboutorange.com/mrl/projects/nose Test Runner com discovery de testes: Se parece com um teste então é um teste :D Arquivos com 'test' no nome. Objetos TestCase, TestSuite e funções com 'test' no nome Funções 'avulsas' com 'test' no nome
  • 31. Nose Opcionalmente executa doctests: --with-doctest --doctest-extension=txt Sistema de plugins e vários plugins third-parties: Usaremos: coverage (requer coverage.py), rednose Opcional: tdaemon + nose-growl Configuração em ~/.nose.cfg ou em <proj>/setup.cfg
  • 32. tdaemon + nose-growl Para usuários de Mac: hg clone http://bitbucket.org/osantana/nosegrowl/ hg clone http://bitbucket.org/osantana/tdaemon/ Instalar: (cd nosegrowl/nose-growl && python setup.py install) (cd tdaemon && python setup.py install)
  • 34. Testes unitários Etapas: Setup (setUp) — preapara o ambiente onde o teste será executado (fixtures) Exercise (test*) — executa o procedimento a ser testado Assert (assert*/verify) — verifica os resultados Teardown (tearDown) — limpa o ambiente
  • 35. Testes unitários Dicas O melhor "primeiro teste" é o teste que verifica o caso de uso mais comum. O teste mais básico. Comece a escrever pelas "assertions"
  • 36. Testes unitários Características Isolamento — testes são independentes Legibilidade — devem privilegiar legibilidade Velocidade — devem executar rapidamente Manutenabilidade — manutenção deve ser fácil Não intrusivos — código de teste deve ficar somente no teste e não no SUT
  • 37. Testes unitários Isolamento Um teste devem funcionar de forma independente de outros testes e assumir um ambiente "limpo" para execução Todas as dependências do código testado devem ser subtituídas por "doubles" (fakes/stubs ou mocks) Mocks aren't Stubs - Martin Fowler http://bit.ly/mockrnstubs
  • 38. Testes unitários Legibilidade O código do teste não precisa ser elegante, precisa ser legível. Testes são para "consumo" humano Resultados esperados em primeiro lugar: Pior Melhor banco = Banco() banco = Banco() banco.indice("USD", "BRL", TAXA_PADRAO) banco.indice("USD", "BRL", TAXA_PADRAO) banco.comissao(COMISSAO_PADRAO) banco.comissao(COMISSAO_PADRAO) res = banco.converte( res = banco.converte( Nota(100, "USD"), "BRL) Nota(100, "USD"), "BRL) assert res == Nota(49.25, "BRL") assert Nota(49.25, "BRL") == res
  • 39. Testes unitários Legibilidade Dados evidentes: deixe a relação entre as entradas e os resultados aparente: Pior Melhor banco = Banco() banco = Banco() banco.indice("USD", "BRL", 2.00) banco.indice("USD", "BRL", TAXA_PADRAO) banco.comissao(0.015) banco.comissao(COMISSAO_PADRAO) res = banco.converte( res = banco.converte( Nota(100, "USD"), "BRL) Nota(100, "USD"), "BRL) assert Nota(100 / 2 * (1 - 0.015), "BRL") assert Nota(49.25, "BRL") == res == res
  • 40. Testes unitários Legibilidade Nome de teste: test_(pass|fail)_descricao_(invalid| with_x|without_y|basic) Apenas 1 ciclo setup/exercise/verify/teardown por teste A legibilidade sempre é subjetiva mas é importante estabelecer padrões em projetos desenvolvidos por equipes com vários desenvolvedores
  • 41. Testes unitários Dicas O ciclo completo de red/green/refactor deve ser curto para privilegiar o ritmo. Se o teste está ficando grande: quebre-o em testes menores
  • 42. Testes unitários Dicas Programando sozinho? Deixe o último teste "quebrado" no fim de uma sessão de programação para saber de onde retomar o desenvolvimento Programando em equipe? Faça 'commit' somente se todos os testes estiverem passando Usa um sistema de controle de versão distribuído? Deixe 'quebrado' localmente
  • 43. Testes unitários Testabilidade Fácil testar: código bem desenhado, código criado com TDD, funções determinísticas, etc Difícil testar: GUI, código assíncrono, esquemas em banco de dados, componentes de aplicações distribuídas, funções não-determinísticas, etc Existem práticas e padrões que tornam alguns tipos de testes mais fáceis de serem feitos
  • 45. Testes problemáticos Tipos de problemas: Code Smells — problemas relacionados com o código dos testes Behaviour Smells — problemas relacionados ao comportamento dos testes Técnicas e padrões podem ser usados para resolver esse tipo de problema
  • 46. Problemas com código dos testes Code Smells
  • 47. Teste obscuro Dificuldade em entender o código do teste Causas Possíveis Soluções Teste verifica muitas informações ao Reduzir número de verificações mesmo tempo O número de objetos construídos no Construir somente as fixtures necessárias setup é maior que o necessário para aquele teste Interação com o SUT não se dá de forma Remover a indireção e testar o SUT direta e sim através de um intermediário diretamente Não é possível identificar o que está Simplificar o processo de setup sendo testado Excesso de informações irrelevantes no Partir da verificação e remover todos os teste objetos e informações desnecessárias
  • 48. Lógica condicional Código que pode ou não ser executado no teste Causas Possíveis Soluções Teste verifica coisas diferentes Desacoplar o SUT de suas dependências dependendo de como executado e/ou dividir o teste Modificar o valor esperado numa Criar testes individuais dedicados apenas verificação dependendo de um caso para os casos especiais e excluí-los do especial teste genérico Restauração do ambiente é muito Fazer a restauração do ambiente no complexa e cheia de verificações método tearDown no lugar de deixá-lo dentro do teste Múltiplos testes condicionais no mesmo Separando os testes para privilegiar a teste percorrento uma collection (input, localização de um problema eventual output)
  • 49. Código difícil de testar Código é muito difícil de testar Causas Possíveis Soluções Código extremamente acoplado Desacoplar o código e parametrizar as dependências para substituí-las por objetos fake Código assíncrono Separar partes síncronas do código assíncrono e testar somente esse código
  • 50. Duplicação de código O mesmo código de teste repetido muitas vezes Causas Possíveis Soluções Reproveitamento de código no estilo Aplicar padrões de refatoração ao código Copy & Paste do teste (ex. Extract Method) "Reinvenção da Roda" - Escrita de Aplicar padrões de refatoração ao código trechos de testes já escrito por outra do teste (ex. Extract Method) pessoa
  • 51. Lógica de teste no código Código de teste no código sendo testado Causas Possíveis Soluções "Ganchos" para teste: Substituir o teste lógico por uma if testing: ... else: ... dependência que pode ser substituída por um objeto Fake. Variações: dependências específicas Refatorar o código para eliminar esse para teste, reimplementações de tipo de lógica por uma dependência que métodos específicos para testes, etc. pode ser substituída por um objeto Fake.
  • 52. Problemas com comportamento dos testes Behaviour Smells
  • 53. Roleta de verificações Difícil saber qual verificação falhou Causas Possíveis Soluções Teste "fominha": um único teste verifica Dividir o teste em em vários muitas funcionalidades Não é possível identificar o problema Acrescentar mensagens nos casos onde com a mensagem da verificação quando a verificação não usa valores constantes/ ela falha. referência como parâmetro. (ex. assert p1.x == p2.x, "coordenada x deveria ser igual")
  • 54. Testes erráticos (I) Testes se comportam erraticamente Causas Possíveis Soluções Teste depende de outro e falha quando a Remover a dependência copiando-a ordem de execução muda ou o teste para o teste em questão ou fazendo os quando é executado sozinho dois compartilharem as mesmas fixtures Mais de um teste roda simultaneamente Cada teste deve rodar em seu próprio compartilhando o mesmo ambiente ambiente. Testes vão ficando mais lentos ou Se o problema estiver no SUT o certo é ocupando mais recursos da máquina corrigir o bug. Se estiver no teste o bug está no processo de tearDown Testes dependem de recursos externos Criar uma cópia deste recurso que podem estar indisponíveis localmente ou substituí-lo por um stub.
  • 55. Testes erráticos (II) Testes se comportam erraticamente Causas Possíveis Soluções Teste passa na primeira execução e O teste não está restaurando o ambiente depois falha sucessivamente inicial corretamente. Teste falha aleatoriamente quando várias Criar ambientes de teste individuais pessoas executam testes simultaneamente. Teste falha aleatoriamente mesmo com Tentar eliminar, dentro do possível, os uma pessoa executando ele por estar elementos determinísticos do teste. testando código não-determinístico
  • 56. Depuração manual Depuração manual para localizar problemas Causas Possíveis Soluções Existência de código sem cobertura de Providenciar a cobertura do código em teste questão
  • 57. Intervenção Manual Intervenção manual na execução dos testes Causas Possíveis Soluções O teste foi construído sem ter em mente Automatizar todo o processo que "teste automatizado" implica que não deve existir "intervenção manual"
  • 58. Testes lentos Testes demoram para executar Causas Possíveis Soluções O teste depende de recursos externos Tentar substituir esse recurso por um que têm uma latência muito alta objeto fake Testes executam fixtures muito extensas A solução ideal é simplificar a construção para cada um dos cenários dessas fixtures. Não sendo possível fazer isso permita que os testes compartilhem as fixtures Teste acrescenta explicitamente um Extrair a parte síncrona do código e intervalo para lidar com código testar somente ela assíncrono Muitos testes Não é necessário executar todos os testes o tempo todo
  • 59. Padrões de teste Práticas e padrões para uso em testes
  • 60. Padrões… … de estratégia … para banco de dados … básicos xUnit … de desenho para testabilidade … para setup de fixtures … de verificação … para teardown … com objetos falsos
  • 61. Padrões de estratégia Test Strategy Patterns
  • 62. Estratégia de Automação Recorded Test — usam a estratégia grava & reproduz. ex. Selenium IDE, Sikuli, etc Data-Driven Test — úteis para testar parsers, conversores de formatos, etc. ex. teste de um crawler Scripted Test — cria-se um programa especificamente para testar outro Test Automation Framework — é um tipo de programa de testes mas usa um framework para isso. ex. xUnit
  • 63. Estratégia para fixtures Minimal Fixture — todo teste precisa de fixtures, com essa estratégia cria-se o mínimo necessário para executar apenas o teste em questão Standard Fixture — testes compartilham um método que cria as fixtures usadas por eles Fresh Fixture — teste constrói as suas próprias fixtures Shared Fixture — testes compartilham as mesmas fixtures
  • 64. Estratégia de Interação Back Door Manipulation (ui!) — nos casos onde não é possível avaliar o funcionamento do SUT diretamente as verificações são feitas com os dados das fixtures. Ex. verificar se o SUT manipulou os dados do banco de dados corretamente. Layer Test — escrever testes para cada uma das camadas de uma aplicação com várias camadas. Ex. testar o 'driver' do DB, o ORM, os objetos model, etc
  • 65. Padrões básicos xUnit xUnit Basics Patterns
  • 66. Definição dos testes Test Method — um cenário de teste por método Four-Phase Test — setup, exercise, assert, teardown Assertion Method — métodos de verificação (.assert*()) Assertion Message — exibida quando a verificação falha Testcase Class — agrupamento de testes relacionados
  • 67. Execução dos testes Test Runner — aplicação que executa os testes e mostra os resultados Testcase object — instância contendo um conjunto de testes relacionados Test Suite object — objeto com a mesma interface de Testcase que agrupa um ou mais objetos Testcase Test Discovery — mecanismo pelo qual o Test Runner encontra os testes
  • 68. Padrões para setup de fixtures Fixture Setup Patterns
  • 69. Setup de Fresh Fixtures In-Line Setup — cada teste constrói suas fixtures por conta própria Delegated Setup — testes constroem suas fixtures chamando um método auxiliar Implicit Setup — a construção das fixtures é implicita e executada dentro do método .setUp()
  • 70. Criação compartilhada Prebuilt Fixture — as fixtures são compartilhadas pelos testes e são construídas por outro componente. Ex. ./ manage.py loaddata data.json do Django Suite Fixture Setup — fixtures construídas no .setUp() da suíte e não no Testcase
  • 71. Padrões de verificação de resultados Result Verification Patterns
  • 72. Estratégia de verificação State Verification — verificamos o estado do SUT após o exercício. Ex. sut.set(1); assert sut.get() == 1 Behaviour Verification — verificamos os resultados indiretos após o exercício do SUT. Ex. web.open ("http://j.mp", mock); mocker.verify()
  • 73. Estilos de verificação Custom Assertion — criamos uma verificação personalizada. Ex. chk(d, r) { assert r == roman(d) } Delta Assertion — verificamos a diferença do objeto antes do exercício e depois de exercitá-lo Guard Assertion — verifica o resultado com if. No caso de erro executa uma falha explicitamente. Unfinished Test Assertion — força falha pra indicar que o teste não está pronto
  • 74. Padrões para teardown Fixture Teardown Patterns
  • 75. Estratégia para teardown Garbage-Collected Teardown — deixar o garbage collector da linguagem fazer a limpeza do ambiente Automated Teardown — registramos a criação de todos os objetos no setup para removê-los na fase de teardown
  • 76. Organização do código In-line Teardown — a limpeza do ambiente é feita no próprio teste Implicit Teardown — a limpeza do ambiente fica por conta do método .tearDown()
  • 77. Padrões com objetos falsos Test Double Patterns
  • 79. Exemplo de código Dependência
  • 81. Testes falham AM ! FA L H
  • 82. Test Double Substituir uma ou mais dependências do SUT por um equivalente específico para o teste: Test Double Dummy Test Mock Fake Test Spy Object Stub Object Object
  • 83. Dummy Geralmente são valores que não são usados no teste. Algumas vezes são apenas passados como parâmetros para atender ao número de parâmetros de um método.
  • 85. Stubs Similares aos objetos Fake Não tem uma implementação funcional, apenas retorna valores pré-estabelecidos Podem gerar uma exceção para testar comportamento do SUT nessa situação Ex: Simular um erro de timeout na conexão com um banco de dados
  • 86. Spy Similares aos objetos Stub Registram chamadas para seus métodos para que seja possível fazer uma verificação indireta posteriormente Ex. Servidor de e-mail que registra e-mails "enviados"
  • 87. Mock Tipo especial de objeto que pode ser programado com as expectativas de chamadas e retornos
  • 88. Fonte: Growing Object-Oriented Software, Guided by Tests Mock Rede de objetos
  • 89. Fonte: Growing Object-Oriented Software, Guided by Tests Mock Testando objeto isoladamente
  • 90. Fonte: Growing Object-Oriented Software, Guided by Tests Mock Testando com um objeto mock
  • 91. Fonte: Growing Object-Oriented Software, Guided by Tests Mock Testando com um objeto mock
  • 92. Mocker http://labix.org/mocker Desenvolvida pelo brasileiro Gustavo Niemeyer Usa a estratégia Record (para especificar as expectativas e retornos) & Play (para verificar os resultados)
  • 94. Padrões para banco de dados Database Patterns
  • 95. Padrões de banco de dados Database Sandbox — cada desenvolvedor tem um banco de dados à sua disposição (ex. Django SQLite in memory) Table Truncate Teardown — truncar as tabelas na fase do teardown Transaction Rollback Teardown — iniciar uma transação na fase de setup e efetuar um rollback na fase de teardown. Deve-se cuidar para que não tenha nenhum commit no SUT
  • 96. Padrões de desenho para testabilidade Design-for-Testability Patterns
  • 97. Padrões para testabilidade Dependency Injection — permite substituir dependências do SUT por Test Doubles. A dependência pode ser passada na construção ou como parâmetro do método. Ex. O objeto TimeDisplay depende de TimeProvider que, nos testes, é substituído por stub/mock Dependency Lookup — o objeto busca suas dependências em um local específico. Ex. registro, dict
  • 98. Padrões para testabilidade Exemplo! pag. 764 do xunit Humble object — extrair a lógica num componente separado e mais fácil de testar. Ex. extrair a parte síncrona de um objeto com operações assíncronas Pode-se usar um método no lugar de um objeto Test Hook — não use: adicionar lógica condicional no SUT para se comportar de modo específico com os testes
  • 99. Desenvolvendo aplicações Desenvolvendo aplicações completas usando Test-Driven Development
  • 100. Desenvolvendo aplicações Testes de aceitação Validar requisitos dos clientes Selenium2, Pyccuracy, Windmill, Django Client, etc. Inicia ciclo red/green/ refactor
  • 101. Desenvolvendo aplicações Escrever um teste de aceitação Escrever um Fazer o teste que falha teste passar que falha Refatorar
  • 102. Desenvolvendo aplicações Se surgir alguma idéia nova para outro teste: anote no papel Escrever um teste de aceitação Escrever um Fazer o teste que falha teste passar que falha Refatorar
  • 104. Codb.in Usuário submete o código e a linguagem Uma URL curta é gerada O usuário é encaminhado para o Twitter: http://twitter.com/home?status=??? Usaremos a biblioteca Pygments Google App Engine
  • 106. Resumo Testes são isolados A ordem dos testes não é garantida Não se deve adicionar lógica de teste no código de produção Testes devem assumir um ambiente limpo quando começam e limpar o ambiente quando terminam
  • 107. Resumo red / green / refactor setup, exercise, verify, teardown
  • 108. F.A.Q. Quando sei que os testes são suficientes? Quando você tiver certeza que seu software está completo e sem bugs: nunca serão. Quando eu preciso fazer testes: Resposta curta: sempre. Resposta longa: quando você não tiver segurança total daquilo que precisa ser feito
  • 109. F.A.Q. Qual o tamanho ideal de um baby-step? Resposta curta: do tamanho que te dê segurança. Resposta longa: TDD é uma prática e como tal requer treino. O ideal é que no início se use passos pequenos e posteriormente aumentá-los. Existe uma relação direta entre a cobertura de testes e a quantidade de bugs num código? Existe essa relação mas ela não é linear.
  • 110. Mensagens Teste é algo desejável num software. Melhor se forem automatizados e ótimos se o código foi feito depois do teste Falácia: "Código não testado é código bugado" Não existe bala de prata, logo, teste automatizado não é uma delas Atenção para os "radicais do teste". Radicalismo nunca é bom para um programador
  • 112. Leitura Complementar Internet TDD @ Wikipedia — http://j.mp/zBGgt Mocks aren't Stubs — http://j.mp/7MdzF Inversion of Control and Dependency Injection — http://j.mp/I0YAA
  • 115. Coding-Dojo O melhor modo de aprender um jogo é jogando
  • 116. Coding-Dojo Escolha do desafio Todos participam Pair programming em Solução construidas na uma máquina hora (não vale usar bibliotecas dedicadas) Piloto codifica a solução usando TDD Design reviews em intervalos Co-piloto troca com piloto em intervalos de 5 Piloto deve descrever o minutos que está fazendo
  • 117. Coding-Dojo O piloto pode pedir Análise de pontos ajuda para o co-piloto ou positivos e negativos para a platéia após a sessão A experiência é mais No Brasil criou-se o importante que a #horaextra: uma "happy solução do problema hour" após o Dojo Sessões com tempo fixo Mais informações: http://codingdojo.org/
  • 118. Sugestões de problemas Mão de poker Mostrador LCD Valor por extenso Caixa empilhadas