Slide 1

Slide 1 text

Pirâmide de Testes Domine a arte de entregar software com qualidade.

Slide 2

Slide 2 text

Randson Oliveira twitter.com/rands0n github.com/rands0n speakerdeck.com/rands0n

Slide 3

Slide 3 text

O que veremos? Por que fazer testes? Qualidade de testes Mocks e Stubs Alguns exemplos a mais…

Slide 4

Slide 4 text

Por que fazer testes? Manter o projeto em níveis saudáveis Ajudar na qualidade externa Ajudar na qualidade interna

Slide 5

Slide 5 text

Qualidade de testes Como posso avaliar se meu teste ou suíte está com qualidade?

Slide 6

Slide 6 text

Corretude O teste está verificando o comportamento correto do meu código?

Slide 7

Slide 7 text

describe Stack do describe '#push' do it 'puts an element at the top of the Stack' do stack = Stack.new stack.push 1 stack.push 2 expect(stack.top).to eq 1 end end end describe Stack do describe '#push' do it 'puts an element at the top of the Stack' do stack = Stack.new stack.push 1 stack.push 2 expect(stack.top).to eq 2 end end end Teste errado Teste correto

Slide 8

Slide 8 text

Adequação do tipo de teste O teste foi feito com o tipo mais adequado? Aceitação, integração ou unitário?

Slide 9

Slide 9 text

Aceitação Testa um requisito funcional, normalmente feito pela UI

Slide 10

Slide 10 text

São sobre o domínio do problema(regras de negócio), não sobre o domínio de UI

Slide 11

Slide 11 text

feature 'Users make the To do complete' do scenario 'update todos as completed' do sign_in create_todo 'Buy me a beer' find('.todos li', text: 'Buy me a beer').click_on 'Mark complete' expect(page).to have_css('.todos li.completed', text: 'Buy me a beer') end end

Slide 12

Slide 12 text

feature 'Users make the To do complete' do scenario 'update todos as completed' do sign_in create_todo 'Buy me a beer' find('.todos li', text: 'Buy me a beer').click_on 'Mark complete' expect(page).to have_css('.todos li.completed', text: 'Buy me a beer') end end Domínio do problema Domínio de UI Domínio de UI

Slide 13

Slide 13 text

feature 'Users make the To do complete' do scenario 'update todos as completed' do sign_in create_todo 'Buy me a beer' mark_complete 'Buy me a beer' expect(page).to have_completed_todo 'Buy me a beer' end end

Slide 14

Slide 14 text

feature 'Users make the To do complete' do scenario 'update todos as completed' do sign_in create_todo 'Buy me a beer' mark_complete 'Buy me a beer' expect(page).to have_completed_todo 'Buy me a beer' end end Domínio do problema Domínio do problema

Slide 15

Slide 15 text

Escreva exemplos de uso do seu código, não testes

Slide 16

Slide 16 text

Integração Está entre o teste de aceitação e o unitário, testa o comportamento de 2 ou mais objetos juntos

Slide 17

Slide 17 text

Unitário Testa o comportamento de apenas um objeto

Slide 18

Slide 18 text

describe Stack do describe '#push' do it 'puts an element at the top of the Stack' do stack = Stack.new stack.push 1 stack.push 2 expect(stack.top).to eq 2 end end describe '#pop' do it 'remove an element at the final of the Stack' do stack = Stack.new stack.push 1 stack.push 2 stack.push 3 stack.pop expect(stack.last).to eq 2 end end end

Slide 19

Slide 19 text

Pirâmide de Testes Guia de estratégia de testes baseados na natureza do tipo de teste

Slide 20

Slide 20 text

Aceitação Integração Unitário + Frágil + Lento + Garantia de qualidade externa + Rápido - Frágil - Garantia de qualidade externa

Slide 21

Slide 21 text

Clareza Está claro para entender do que o teste se trata?

Slide 22

Slide 22 text

xUnit Tente estruturar seu teste nas 4 fases do padrão http://xunitpatterns.com

Slide 23

Slide 23 text

Setup Coloca o sistema no estado necessário

Slide 24

Slide 24 text

Exercise Interage com o objeto sob teste

Slide 25

Slide 25 text

Verify Verifica o comportamento esperado

Slide 26

Slide 26 text

Teardown Coloca o sistema no estado anterior do teste

Slide 27

Slide 27 text

describe Stack do describe '#push' do it 'puts an element at the top of the Stack' do stack = Stack.new stack.push 1 stack.push 2 expect(stack.top).to eq 2 end end end

Slide 28

Slide 28 text

describe Stack do describe '#push' do it 'puts an element at the top of the Stack' do stack = Stack.new stack.push 1 stack.push 2 expect(stack.top).to eq 2 end end end Setup Exercise Verify

Slide 29

Slide 29 text

Clareza = Causa e consequência O teste é claro quando é fácil de entender a relação de causa e consequência entre as fases do xUnit

Slide 30

Slide 30 text

Setup Dado o seguinte estado do meu sistema

Slide 31

Slide 31 text

Exercise Quando aplico tal mudança nele

Slide 32

Slide 32 text

Verify Então consigo verificar tal comportamento nele

Slide 33

Slide 33 text

describe Game, 'in the final phase' do context 'when player hits the target' do it 'congratulates the player' do @game = Game.new @game.phase = :final @game.hit_the_target expect(@game.output).to eq 'Congratulations!' end it 'set the score to the player' do @game = Game.new @game.phase = :final @game.hit_the_target expect(@game.score).to eq 100 end end end

Slide 34

Slide 34 text

describe Game, 'in the final phase' do context 'when player hits the target' do it 'congratulates the player' do @game = Game.new @game.phase = :final @game.hit_the_target expect(@game.output).to eq 'Congratulations!' end it 'set the score to the player' do @game = Game.new @game.phase = :final @game.hit_the_target expect(@game.score).to eq 100 end end end DRY

Slide 35

Slide 35 text

O teste está claro?

Slide 36

Slide 36 text

describe Game, 'in the final phase' do context 'when player hits the target' do before do @game = Game.new @game.phase = :final @game.hit_the_target end it 'congratulates the player' do expect(@game.output).to eq 'Congratulations!' end it 'set the score to the player' do expect(@game.score).to eq 100 end end end DRY

Slide 37

Slide 37 text

describe Game, 'in the final phase' do context 'when player hits the target' do before do @game = Game.new @game.phase = :final @game.hit_the_target end it 'congratulates the player' do expect(@game.output).to eq 'Congratulations!' end it 'set the score to the player' do expect(@game.score).to eq 100 end end end

Slide 38

Slide 38 text

O teste está claro? Em que estado o objeto game precisa estar setado como 100? O que tem que ser feito no objeto para ele setar o score para 100?

Slide 39

Slide 39 text

it 'set the score to the player' do expect(@game.score).to eq 100 end

Slide 40

Slide 40 text

Uso excessivo de DRY nos testes prejudica a clareza

Slide 41

Slide 41 text

DRY não deve ser aplicado em testes do mesmo modo que é aplicado em produção

Slide 42

Slide 42 text

Favoreça clareza sobre DRY

Slide 43

Slide 43 text

Mocks & Stubs It’s all about dependencies

Slide 44

Slide 44 text

SUT e Collaborator SUT: System Under Test DOC: Dependent On Component (Collaborator)

Slide 45

Slide 45 text

SETUP EXERCISE TEARDOWN VERIFY SUT DOC Teste rodando

Slide 46

Slide 46 text

Teste doubles Um objeto que substitui o DOC real

Slide 47

Slide 47 text

SETUP EXERCISE TEARDOWN VERIFY SUT DOC Teste doubles doubles

Slide 48

Slide 48 text

Tipos de test doubles Existem vários tipos de testes doubles, entre eles estão: - Mocs - Stubs - Spy - Fake - Dummy Object

Slide 49

Slide 49 text

Porque precisamos de Mock?

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

Uso de mocks seguindo seu propósito

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

Criadores do conceito de mock

Slide 54

Slide 54 text

Especificando o Secret of Life

Slide 55

Slide 55 text

describe SecretOfLife do it 'prints the number of the life' do end end

Slide 56

Slide 56 text

describe SecretOfLife do it 'prints the number of the life' do computer = SecretOfLife.new computer.print_the_answer expect(STDOUT.read).to eq 42 end end

Slide 57

Slide 57 text

describe SecretOfLife do it 'prints the number of the life' do computer = SecretOfLife.new computer.print_the_answer expect(STDOUT.read).to eq 42 end end IOError: not opened for reading from (irb):1:in `read' from (irb):1

Slide 58

Slide 58 text

Interface Discovery Especificando uma API de dependência

Slide 59

Slide 59 text

describe SecretOfLife do it 'prints the number of the life' do end end SecretOfLife Printer print(42)

Slide 60

Slide 60 text

describe SecretOfLife do it 'prints the number of the life' do printer = double('printer')' computer = SecretOfLife.new(printer) expect(printer).to receive(:print).with('42') computer.print_the_answer end end

Slide 61

Slide 61 text

describe SecretOfLife do it 'prints the number of the life' do printer = double('printer') computer = SecretOfLife.new(printer) expect(printer).to receive(:print).with('42') computer.print_the_answer end end Test double

Slide 62

Slide 62 text

describe SecretOfLife do it 'prints the number of the life' do printer = double('printer') computer = SecretOfLife.new(printer) expect(printer).to receive(:print).with('42') computer.print_the_answer end end Test double Injeção de dependência

Slide 63

Slide 63 text

describe SecretOfLife do it 'prints the number of the life' do printer = double('printer') computer = SecretOfLife.new(printer) expect(printer).to receive(:print).with('42') computer.print_the_answer end end Test double Injeção de dependência Mock do test double

Slide 64

Slide 64 text

Fases do xUnit Mudança de fases quando usamos mock

Slide 65

Slide 65 text

describe SecretOfLife do it 'prints the number of the life' do printer = double('printer') computer = SecretOfLife.new(printer) expect(printer).to receive(:print).with('42') computer.print_the_answer end end Setup Verify Exercise

Slide 66

Slide 66 text

Estado X Comportamento Diferenças de exercises entre estado e comportamento

Slide 67

Slide 67 text

Tradicional Verificação pelo estado final do Objeto

Slide 68

Slide 68 text

Objeto Objeto Objeto

Slide 69

Slide 69 text

Com Mocks Verifica a iteração entre os objetos

Slide 70

Slide 70 text

Objeto Objeto Objeto

Slide 71

Slide 71 text

describe SecretOfLife do it 'prints the number of the life' do printer = double('printer')' computer = SecretOfLife.new(printer) expect(printer).to receive(:print).with('42') computer.print_the_answer end end describe Stack do describe '#push' do it 'puts an element at the top of the Stack' do stack = Stack.new stack.push 1 stack.push 2 expect(stack.top).to eq 1 end end end Verify Verify

Slide 72

Slide 72 text

O que é um mock?

Slide 73

Slide 73 text

Mock é um teste double usado na fase do verify

Slide 74

Slide 74 text

Mockar um objeto é programá- lo para verificar se ele recebeu as mensagens corretas do SUT

Slide 75

Slide 75 text

Criado originalmente para ser usado na com a tecnica de interface discovery

Slide 76

Slide 76 text

O que é um Stub?

Slide 77

Slide 77 text

Stub é um test double usado na fase de setup

Slide 78

Slide 78 text

Stubar um objeto é programá- lo para retornar uma resposta de um certo método

Slide 79

Slide 79 text

describe Account do it 'log the user on the system' do user = double('user')' allow(user).to receive(:log_in) .with(:name => 'rands0n', :password => '12345') .and_return true account = Account.new(user).log_in expect(account.is_logged?).to be_true end end

Slide 80

Slide 80 text

describe Account do it 'log the user on the system' do user = double('user')' allow(user).to receive(:log_in) .with(:name => 'rands0n', :password => '12345') .and_return true account = Account.new(user).log_in expect(account.is_logged?).to be_true end end Estubando o objeto user

Slide 81

Slide 81 text

describe Account do it 'log the user on the system' do user = double('user')' allow(user).to receive(:log_in) .with(:name => 'rands0n', :password => '12345') .and_return true account = Account.new(user).log_in expect(account.is_logged?).to be_true end end Stub: fase de setup

Slide 82

Slide 82 text

Concluindo - Qualidade de Testes - Mocks vs Stubs

Slide 83

Slide 83 text

Qualidade de Testes

Slide 84

Slide 84 text

Prefira clareza ao invés de DRY nos testes

Slide 85

Slide 85 text

Organize sua suite segundo a pirâmide de testes

Slide 86

Slide 86 text

Mocks vs Stubs

Slide 87

Slide 87 text

Stubs são para a fase de setup, mocks são para a verify

Slide 88

Slide 88 text

describe SecretOfLife do it 'prints the number of the life' do printer = double('printer')' computer = SecretOfLife.new(printer) expect(printer).to receive(:print).with('42') computer.print_the_answer end end Verify describe Account do it 'log the user on the system' do user = double('user')' allow(user).to receive(:log_in) .with(:name => 'rands0n', :password => '12345') .and_return true account = Account.new(user).log_in expect(account.is_logged?).to be_true end end Setup

Slide 89

Slide 89 text

Mocks foram feitos com o propósito de fazer design com a técnica de interface discovery

Slide 90

Slide 90 text

Quando alguém falar "mockar", provavelmente ele/ela quis dizer "stubar"

Slide 91

Slide 91 text

Algumas coisas a mais - Paper para entender a origem dos mocks: Mock roles, not Objects - Livro sobre testes avançados: Growing object-oriented software guided by testes

Slide 92

Slide 92 text

Obrigado! :) twitter.com/rands0n github.com/rands0n speakerdeck.com/rands0n