Lições Aprendidas sobre Testes



Documentos relacionados
Behaviour-Driven Development com RSpec e RSpec on Rails. Danilo Sato

Desenvolvimento Guiado por Testes

Agile Methods for the Traditional Guy

Trilha Agile TDD e 20 coisas que você precisa saber

Desenvolvimento Dirigido por Testes (TDD)

Introdução ao TDD. Dionatan Moura. #guma10anos Abril de about.me/dionatanmoura

O CONCEITO DE TDD NO DESENVOLVIMENTO DE SOFTWARE

Desenvolvimento Dirigido por Testes (TDD)

Test-driven Development no Rails Começando seu projeto com o pé direito. 2007, Nando Vieira

A Evolução de XP segundo Kent Beck Parte 2

TESTES AUTOMATIZADOS COM JUNITE MOCKITO

XP extreme Programming, uma metodologia ágil para desenvolvimento de software. Equipe WEB Cercomp

Aprendendo a ESTUDAR. Ensino Fundamental II

UNIVERSIDADE FEDERAL DE SANTA MARIA CENTRO DE TECNOLOGIA AULA 06 PROFª BRUNO CALEGARO

Desenvolvendo Software Livre com Programação extrema

O evento não fará uso do vídeo (webcam), somente slides e áudio. Se necessário, ajuste o idioma da sala na barra de ferramentas superior

Estratégias para testes: a metáfora da pirâmide alimentar

Engenharia de Software II

Os desafios do Bradesco nas redes sociais

Sistemas de Informação I

Teste de software. Definição

CSF FasTest SOLUÇÕES DE OUTPUT DE PAGAMENTO

Guia de boas práticas para realização de Backup

Testes de Software. Por quê testar? 3/28/2011. Andrew Diniz da Costa. Manter alta qualidade. Prevenir e encontrar defeitos

TDD-Test Driven Development

Evolução do Design através de Testes e o TDD

Desenvolvendo Websites com PHP

DICAS PARA CÁLCULOS MAIS RÁPIDOS ARTIGO 07

Melhoria no Desenvolvimento Ágil com Implantação de Processo de Integração Contínua Multiplataforma para Java e.net. Hudson

ESPECIFICANDO OS REQUISITOS. Cleviton Monteiro

15 4 Operação Avançada do Sistema: Inclusão de Nota Fiscal e seus relacionamentos

Scrum Uma breve apresentação. Alfredo Goldman Dairton Bassi

1 Code::Blocks Criação de projetos

Manual de Relação de Pontos por Indicação

Tutorial de Active Directory Parte 3

Programação Orientada a Testes Rodrigo Rebouças de Almeida

TESTE DE SOFTWARE COM XP. Isac Aguiar isacaguiar.com.br

Extração de Requisitos

Introdução à ES - Continuação

Por que usar o Poka-Yoke no Lean Seis Sigma?

Métodos Ágeis para Desenvolvimento de Software Livre

Novas Ferramentas de Teste na plataforma Java Jorge Diz Workshop de testes para aplicativos web Slide 1

FOTOGRAFIA NA MONTANHA - Dicas

Manual do Sistema "Vida em Mão - Controle Financeiro Para PALM" Editorial Brazil Informatica

SPARK - CONFIGURAÇÃO

DISCIPLINA ENGENHARIA DE SOFTWARE Aula 03 Desenvolvimento Ágil Modelos Ágeis. Profª Esp.: Maysa de Moura Gonzaga

Resumo de: THE FOUR STEPS TO THE EPIPHANY de Steve Blank de Diogo Miguel Jesus, Engenharia Informática, Instituto Superior Técnico, Lisboa, 2011

Informática Básica. Microsoft Word XP, 2003 e 2007

Manual de uso do aplicativo Filho Sem Fila

Post excerpt to catch readers attention and describe the story in short

Seu Android está lento? tente as nossas dicas

Testes de Software. Anne Caroline O. Rocha TesterCertified BSTQB NTI UFPB

1. Instalei o DutotecCAD normalmente no meu computador mas o ícone de inicialização do DutotecCAD não aparece.

Jonas de Souza H2W SYSTEMS

Artigo Lean Seis Sigma e Benchmarking

UMA ABORDAGEM SOBRE TESTES AUTOMATIZADO DE SOFTWARES EM AMBIENTES DE DESENVOLVIMENTO

Lição 1 Introdução à programação de computadores

MD5 no Android como mecanismo de autenticação na API do Google Maps. Claudio André

Fundamentos em Teste de Software. Vinicius V. Pessoni

Manual do usuário. Manual do Usuário DER-MG Página : 1

Por que o quadrado de terminados em 5 e ta o fa cil? Ex.: 15²=225, 75²=5625,...

TDD depois do mainstream. E agora?

Liner. Manual do Usuário

Guia Prático. Sistema EAD PRO-CREA

a) Teste das funções do sistema com outros sistemas b) Teste de componentes que em conjunto compõem a função do sistema

SILVA MATTOS & Cia. Ltda. BANCO DE IMAGENS. Manual de Utilização. Banco de Imagens Silva Mattos & Cia. Ltda.

percebe diferença e qual?

Sphinx Scanner Informações gerais V

PROGRAMAÇÃO PARA INTERNET RICA INTRODUÇÃO AO ASP.NET

Tópicos. Métodos Ágeis. Histórico; Valores; Métodos Ágeis x Modelos Tradicionais; Exemplo: Referências Bibliográficas.

COMO INVESTIR PARA GANHAR DINHEIRO

Fala, CMO! Com Thiago Reis da Project Builder

4 O Workflow e a Máquina de Regras

COMO SOLICITAR O CADASTRO DE UM ITEM SSA Central de Cadastro

No meu caso usei o huawei e1756, onde tirei a opção de autorun, pois se estiver ativada, não será detectado pelo sistema.

Prof. Me. Marcos Echevarria

Estudo de Caso. Cliente: Rafael Marques. Coach: Rodrigo Santiago. Duração do processo: 12 meses

2. CAIXA DE FERRAMENTAS - CHEGANDO A REDAÇÃO

1 Detecção e correcção de erros Erros sintáticos Erros de execução Erros semânticos Erros semânticos...

Casa do Código Livros para o programador Rua Vergueiro, º andar Vila Mariana São Paulo SP Brasil

PASSO A PASSO: CRIAÇÃO DE PERSONAS

Guia Rápido do Usuário - Assinatura Digital

Sei... Entra, Fredo, vem tomar um copo de suco, comer um biscoito. E você também, Dinho, que está parado aí atrás do muro!

Cartão SIM Eurail Roaming

Aplicações desktop a jato com JRuby e Netbeans

Adicionando um amplificador linear! Pensar duas vezes! Quanto vai aumentar o seu sinal?

FRAMEWORK PARA GERENCIAMENTO E MONITORAMENTO DE

Ambientação JAVA. Versão 0.1 MICHEL CORDEIRO ANALISTA DE NEGÓCIO (NTI 2014) 1 UNIVERSIDADE CEUMA 08/01/2014

Como melhorar a Qualidade de Software através s de testes e nua. Cláudio Antônio de Araújo 22/11/2008

2. Representação Numérica

Alice: Um mundo 3D de animação grátis para o ensino de programação.

O papel do CRM no sucesso comercial

CONTEÚDOS. Sobre Classroom tv A plataforma Por que Classroom tv Especificações Informação adicional

Cinco principais qualidades dos melhores professores de Escolas de Negócios

MANUAL DE INSTRUÇÕES. Versão 1.0. Visão Transportador

Equações do segundo grau

O que tem neste ebook?

ArpPrintServer. Sistema de Gerenciamento de Impressão By Netsource Rev: 02

Transcrição:

Lições Aprendidas sobre Testes Danilo Sato Rails Summit Latin America www.dtsato.com 16/Out/2008

Um pouco sobre vocês Será que estou na palestra certa?

Minha história com testes automatizados

Era uma vez

Era uma vez printf("passou 1\n"); printf("valor: %s\n",!

Era uma vez printf("passou 1\n"); printf("valor: %s\n",!

xunit! XP Kent Beck! Automatizar passos manuais! Você não quebra o que já está funcionando

Test::Unit! Classe que estende Test::Unit::TestCase! Métodos devem começar com "test"! Asserções:! assert(bool)!! assert_equal(expected, actual)!! assert_raise(args, blk)!! assert_nil(actual)!!!

require 'rubygems'" require 'test/unit'" require 'lib/card'" class CardTest < Test::Unit::TestCase" def test_equal" assert Card.new('QS') == Card.new('QC')" end" def test_greater" assert Card.new('AS') > Card.new('KH')" end" def test_lower" assert Card.new('TD') < Card.new('JH')" end" end

StrutsTestCase + AspectJ! Gravador de testes!! Gera as classes de teste pra você!

Primeiros Erros! Testes imensos! Várias asserções no mesmo cenário! Erros não ajudam muito! Debuggar o teste

Primeiras Lições! Testes grandes são difíceis de manter! Mas é bom cobrir a funcionalidade do ponto de vista externo Código de teste também é Código

! RCov! Quais linhas estão sendo executadas pelos testes?! Objetivo: 100% Cobertura de Código

Cuidado!! Cobertura não garante qualidade dos testes!! Heckle: Mutação

! Arrange-Act-Assert Testes Pequenos! Single Assertion per Test

E mais problemas! setup enormes! Carrega e limpa o banco de dados! E os métodos estáticos?

Test-Driven Development

Test-Driven Development

Testes Ajudam no Design! Refatoração! Maus Cheiros! YAGNI! Design Evolutivo

Testes Comunicam Intenção! Documentação Executável! Legibilidade é importante! Lemos mais código do que escrevemos

require 'rubygems'" require 'test/unit'" require 'lib/card'" class CardTest < Test::Unit::TestCase" def test_equal" assert Card.new('QS') == Card.new('QC')" end" def test_greater" assert Card.new('AS') > Card.new('KH')" end" def test_lower" assert Card.new('TD') < Card.new('JH')" end" end

RSpec require 'rubygems'" require 'spec'" require 'lib/card'" describe Card do" it 'should compare based on rank' do" Card.new('AS').should > Card.new('KH')" Card.new('QS').should == Card.new('QC')" Card.new('TD').should < Card.new('JH')" end" end!

Mais algumas lições Se está difícil de testar, provavelmente seu design precisa evoluir Use o código de teste para comunicar suas intenções atuais para o você do futuro (e seus colegas também)

Testes Unitários! Integridade Interna! Rápidos! Independentes! Desacoplados! Escrito por e para desenvolvedores! Não indicam integridade externa

Visão Mais Ampla

Histórias! Como <papel/usuário>! Eu gostaria de <funcionalidade>! Pois <valor de negócio>

Cenários (Exemplos)! Dado <contexto>! Quando <evento>! Então <consequência>

Story: I can rank poker hands" As a game player" I want to rank a poker hand" So that I can decide a winner for the prize" Scenario: Straight flush wins Four of a kind" Given a black hand with cards: 2H 3H 4H 5H 6H" And a white hand with cards: AC AH AD AS KC" Then black should win" Scenario: Four of a kind wins Full house" Given a white hand with cards: 2C 2H 2D 2S AC" And a black hand with cards: AC AH AD KS KC" Then white should win" Scenario: Full house wins Flush" Given a black hand with cards: 2C 2H 2S 3C 3S" And a white hand with cards: 4C 8C TC KC AC" Then black should win

require 'rubygems'" require 'spec/story'" require 'lib/hand'" require 'lib/card'" steps_for :poker do" Given "a $color hand with cards: $cards" do color, cards " instance_eval "@#{color} = Hand.new('#{cards}')"" end" Then ("black should win") { @black.should > @white }" Then ("white should win") { @white.should > @black }" Then ("tie") { @black.should == @white }" end" with_steps_for :poker do" Dir["**/*.story"].each { file run file }" end

! Novo Story Runner Cucumber! Histórias em Português! Funcionalidade: Adição! Como um péssimo matemático" Eu quero saber saomr dois números! Para evitar erros bobos" Cenário: Adicionar dois números! Dado que eu digitei 50 na calculadora" E que eu digitei 70 na calculadora" Quando eu aperto o botão de soma! Então o resultado na calculadora deve ser 120

require 'spec " class Calculadora" def push(n)" @args = []" @args << n" end " def soma; @args.inject(0) { n,sum sum+n}; end" end" Before { @calc = Calculadora.new }" Given /que eu digitei (\d+) na calculadora/ do n! @calc.push n.to_i! end " When 'eu aperto o botão de soma do! @result = @calc.soma! end " Then(/o resultado na calculadora deve ser (\d*)/) { result @result.should == result.to_i }

Testes de Aceitação! Integridade Externa! Mais lentos! Acoplados! Mais difícil detectar causa de erros! Escrito para clientes! Não indicam integridade interna

! Dirige o browser como se um usuário estivesse navegando as páginas! Várias ferramentas:! Selenium IDE! Selenium RC! Selenium on Rails! Selenium Grid* Selenium * Você está curioso? Vá para a palestra do lado!

Testes Unitários

Testes de Aceitação

?

Integração

Mock! Permitem especificar interações! Trocam o objeto real por um dublê! Verificam se as expectativas foram atendidas! Substituem:! Objetos gordos! Serviços externos! Bibliotecas (não quero testar se o gem funciona)!

RSpec # Expectativas" band.should_receive(:rock)" band.should_not_receive(:pause)" # Quantidade de chamadas" guitar.should_receive(:tune).once" guitar.should_receive(:play).at_least(3).times" # Argumentos" guitar.should_receive(:strum_chord).with("e")" guitar.should_receive(:strum_chord).with(:anything)" # Valores de Retorno" band.should_receive(:rocking?).and_return(true)" band.should_receive(:stop).and_raise(cantstoprocking)

# Expectativas" band.expects(:rock)" band.expects(:pause).never" Mocha # Quantidade de chamadas" guitar.expects(:tune).once" guitar.expects(:play).at_least(3) " # Argumentos" guitar.expects(:strum_chord).with("e")" guitar.expects(:strum_chord).with(:anything)" # Valores de Retorno" band.expects(:rocking?).returns(true)" band.expects(:stop).raises(cantstoprocking)

Stubs! Dublês que não verificam expectativas! Não se importam com o que aconteceu # RSpec" band.stub!(:autograph).and_return('signature')" Guitar.stub!(:find).and_return(guitar)" # Mocha" band.stubs(:autograph).returns('signature')" Guitar.stubs(:find).returns(guitar)

Meus erros com mocks/stubs! Precisar gravar muitas expectativas! Muito acoplado com implementação! Muitos stubs poucos mocks! Mockar o próprio objeto! Testes podem passar com o sistema quebrado

! Mock Roles not Objects [OOPSLA04]! Use mocks para desacoplar testes! Cuidado com mock de bibliotecas externas! Use um Adapter! Mocks não tiram o valor dos testes acoplados! CRC com testes Lições sobre mocks

class DataBranderTest < Test::Unit::TestCase" def test_saves_branded_to_storage" storage = Storage.new 'whatever'" storage.expects(:save).with('metal - rock')" DataBrander.new(storage).save_branded('rock')" end " end! class DataBrander" BRAND = "METAL"" def initialize(storage)" @storage = storage" end" def save_branded(data)" @storage.save "#{BRAND} - #{data}"" end" end!

class DataBranderTest < Test::Unit::TestCase" def test_saves_branded_to_storage" storage = Storage.new 'whatever'" storage.expects(:save).with('metal - rock')" DataBrander.new(storage).save_branded('rock')" end " end! class DataBrander" BRAND = "METAL"" def initialize(storage)" @storage = storage" end" def save_branded(data)" @storage.save "#{BRAND} - #{data}"" end" end!

class StorageTest < Test::Unit::TestCase" def test_saves_to_file" Storage.new('test.txt').save('rock')" assert_equal 'rock', File.read('test.txt')" ensure" FileUtils.rm_f('test.txt')" end" end class Storage" def initialize(filename)" @filename = filename" end" def save(val)" File.open(@filename, 'w') { f f << val}" end" end!

class StorageTest < Test::Unit::TestCase" def test_saves_to_file" Storage.new('test.txt').save('rock')" assert_equal 'rock', File.read('test.txt')" ensure" FileUtils.rm_f('test.txt')" end" end class Storage" def initialize(filename)" @filename = filename" end" def save(val)" File.open(@filename, 'w') { f f << val}" end" end!

class StorageTest < Test::Unit::TestCase" def test_saves_to_file" Storage.new('test.txt').save('rock', 'w')" assert_equal 'rock', File.read('test.txt')" ensure" FileUtils.rm_f('test.txt')" end" end class Storage" def initialize(filename)" @filename = filename" end" def save(val, mode)" File.open(@filename, mode) { f f << val}" end" end!

class StorageTest < Test::Unit::TestCase" def test_saves_to_file" Storage.new('test.txt').save('rock', 'w')" assert_equal 'rock', File.read('test.txt')" ensure" FileUtils.rm_f('test.txt')" end" end class Storage" def initialize(filename)" @filename = filename" end" def save(val, mode)" File.open(@filename, mode) { f f << val}" end" end!

storage = Storage.new("hello.txt")" data_brander = DataBrander.new(storage)" data_brander.save_branded('hello')!

storage = Storage.new("hello.txt")" data_brander = DataBrander.new(storage)" data_brander.save_branded('hello')!

Synthesis

class DataBranderTest < Test::Unit::TestCase" def test_saves_branded_to_storage" storage = Storage.new 'whatever'" storage.expects(:save).with('metal rock', 'w')" DataBrander.new(storage).save_branded('rock')" end " end! class DataBrander" BRAND = "METAL"" def initialize(storage)" @storage = storage" end" def save_branded(data)" @storage.save "#{BRAND} - #{data}", 'w'" end" end!

Synthesis

Synthesis! Cobertura de mocks! Testes acoplados somente nas bordas! Feedback rápido sobre potenciais erros! Funciona com Rspec/Mocha/Expectations! Tarefa Rake: Synthesis::Task.new('synthesis:spec') do t " t.adapter = :rspec" t.pattern = 'test_project/rspec/*_spec.rb'" end!

Visualizações

Builds rápidos!

Behaviour-Driven Development! Um processo ponta-a-ponta de desenvolvimento! Independente de ferramenta! Outside-in

Normalmente

BDD

BDD

Momento para Refletir

Resumo! Testes Unitários! Cobertura de Código! TDD! Histórias e STDD! Testes de Aceitação! Selenium! Mocks/Stubs! Synthesis! BDD

Por que testar?

Custo de encontrar um erro

Feedback! Confiança! Erros são detectados rapidamente! Ajudam a saber quando terminamos! Pensar no design antes de implementar! Evita generalização desnecessária! Regressão automatizada

Build Quality In Work smarter, not harder -- Tom de Marco, Slack Inspecionar para previnir defeitos é bom; Inspecionar para encontrar defeitos é desperdício -- Shigeo Shingo, The Toyota Production System

Auto-Inspeção

Bugs Bugs são testes que você esqueceu de escrever! Resolva a Causa Raiz

Verificação e Validação

Obrigado! Perguntas? dsato@thoughtworks.com www.dtsato.com