ensaio sobre testes automatizados

22
Ensaio sobre testes automatizados TDC2014 – 09/08/2014 Gustavo Fonseca @gustavonseca gustavofonseca 1

Upload: gustavo-fonseca

Post on 25-May-2015

5.155 views

Category:

Technology


3 download

DESCRIPTION

* Slides da apresentação realizada no TDC São Paulo, 2014. * A apresentação é um "fork" da realizada no FISL14, em 2013, entitulada O que você deve saber sobre Unit Tests. -- Testes automatizados é um tema que frequentemente atrai a atenção dos novatos e prende a atenção dos programadores mais experientes. Boa parte das dúvidas concentram-se em o que testar, como testar e as melhores práticas para testar determinado código ou funcionalidade e, um empurrãozinho pode fazer toda a diferença para quem está começando. O objetivo dessa palestra é de expor, de maneira prática, minhas experiências de sucesso e insucesso no design de códigos testáveis assim como dos seus testes.

TRANSCRIPT

Page 1: Ensaio sobre testes automatizados

Ensaio sobre testes automatizadosTDC2014 – 09/08/2014

Gustavo Fonseca @gustavonsecagustavofonseca

1

Page 2: Ensaio sobre testes automatizados

Níveis de teste

● Testes de aceitação

● Testes de integração

● Testes de sistema

● ...

● Testes de unidade

2

Page 3: Ensaio sobre testes automatizados

3

Page 4: Ensaio sobre testes automatizados

Testes de Unidade

4

Page 5: Ensaio sobre testes automatizados

O que é Teste de Unidade?

1 #coding: utf-8 2 3 def saudar(nome): 4 return u'Olá, %s.' % nome 5 6 7 # garantir que o nome do fulano passado como 8 # argumento seja utilizado na saudação 9 assert saudar('Gustavo') == u'Olá, Gustavo.' 10 11 # garantir que seja retornado um objeto unicode 12 assert isinstance(saudar('foo'), unicode)

Unidade objeto dos testes

Casos de teste

5

Page 6: Ensaio sobre testes automatizados

Características

● Garantir o isolamento dos testes

● Facilitar a configuração do ambiente

● Fomentar a organização dos testes

● Executar os testes

● Produzir relatórios úteis

6

Page 7: Ensaio sobre testes automatizados

1 #coding: utf-8 2 import unittest 3 4 5 def saudar(nome): 6 return u'Olá, %s.' % nome 7 8 9 class SaudarTests(unittest.TestCase): 10 11 def test_nome_do_fulano_seja_utilizado_na_saudacao(self): 12 self.assertEqual(saudar('Gustavo'), u'Olá, Gustavo.') 13 14 def test_objeto_retornado_tipo_unicode(self): 15 self.assertIsInstance(saudar('foo'), unicode)

Resumo da execução dos testes

Casos de teste são agrupados em subclasses de unittest.TestCase

O ambiente pode ser preparado por meio dos métodos setUp e tearDown

unittest (stdlib)

http://docs.python.org/2.7/library/unittest.html7

Page 8: Ensaio sobre testes automatizados

Associação

8

Page 9: Ensaio sobre testes automatizados

Exemplo de Composição 1 class Motor(object): 2 def __init__(self): 3 self.ligado = False 4 5 def ligar(self): 6 self.ligado = True 7 8 def desligar(self): 9 self.ligado = False 10 11 12 class Carro(object): 13 def __init__(self): 14 self.motor = Motor() 15 16 def dar_partida(self): 17 self.motor.ligar() 18 19 def esta_ligado(self): 20 return self.motor.ligado 21 22 def andar(self): 23 if self.esta_ligado(): 24 print 'Andando... uhul!' 25 else: 26 raise RuntimeError('O carro precisa estar ligado.')

Composição

9

Page 10: Ensaio sobre testes automatizados

1 import unittest 2 3 from cod3 import Carro, Motor 4 5 6 class MotorTests(unittest.TestCase): 7 """ 8 Os testes foram suprimidos para 9 economizar espaco 10 """ 11 12 class CarroTests(unittest.TestCase): 13 def setUp(self): 14 self.carro = Carro() 15 16 def test_dar_partida(self): 17 self.carro.dar_partida() 18 self.assertTrue(self.carro.esta_ligado()) 19 20 def test_andar(self): 21 self.carro.dar_partida() 22 self.assertIsNone(self.carro.andar()) 23 24 def test_andar_com_carro_desligado_levanta_excecao(self): 25 self.assertRaises(RuntimeError, self.carro.andar) 26

Uma instância de Motor foi criada

Motor().ligar()

10

Page 11: Ensaio sobre testes automatizados

Isolamento de dependências

dublê

11

Page 12: Ensaio sobre testes automatizados

__init__ 1 class Motor(object): 2 def __init__(self): 3 self.ligado = False 4 5 def ligar(self): 6 self.ligado = True 7 8 def desligar(self): 9 self.ligado = False 10 11 12 class Carro(object): 13 def __init__(self, motor=Motor): 14 self.motor = motor() 15 16 def dar_partida(self): 17 self.motor.ligar() 18 19 def esta_ligado(self): 20 return self.motor.ligado 21 22 def andar(self): 23 if self.esta_ligado(): 24 print 'Andando... uhul!' 25 else: 26 raise RuntimeError('O carro precisa estar ligado.')

Composição via argumento na inicialização do objeto

12

Page 13: Ensaio sobre testes automatizados

Atributo de classe 1 class Motor(object): 2 def __init__(self): 3 self.ligado = False 4 5 def ligar(self): 6 self.ligado = True 7 8 def desligar(self): 9 self.ligado = False 10 11 12 class Carro(object): 13 classe_motor = Motor 14 15 def __init__(self): 16 self.motor = self.classe_motor() 17 18 def dar_partida(self): 19 self.motor.ligar() 20 21 def esta_ligado(self): 22 return self.motor.ligado 23 24 def andar(self): 25 if self.esta_ligado(): 26 print 'Andando... uhul!' 27 else: 28 raise RuntimeError('O carro precisa estar ligado.') 13

Composição via atributo de classe

Page 14: Ensaio sobre testes automatizados

Atributo de classe (cont.)

14

from unittest import mock # python3!with mock.patch.object(Carro, 'classe_motor', autospec=True) as motor_teste: motor_teste.return_value = MotorDuble! carro = Carro() # testes aqui...

Page 15: Ensaio sobre testes automatizados

Dublês de teste

dummy - fake - stub - mock

http://martinfowler.com/articles/mocksArentStubs.html 15

Page 16: Ensaio sobre testes automatizados

Stubclass CarroTests(unittest.TestCase): def setUp(self):! class MotorStub(object): def __init__(self): self.ligado = False def ligar(self): return None def desligar(self): return None! self.carro = Carro(motor=MotorStub)! def test_dar_partida(self): self.carro.motor.ligado = True! self.carro.dar_partida() self.assertTrue(self.carro.esta_ligado())! def test_andar(self): self.carro.motor.ligado = True! self.carro.dar_partida() self.assertIsNone(self.carro.andar())! def test_andar_com_carro_desligado_levanta_excecao(self): self.assertRaises(RuntimeError, self.carro.andar)!

Implementa a interface do objeto, com retornos previsíveis.

O dublê entra em ação! rá!

16

Configuração de estado pré-teste.

Page 17: Ensaio sobre testes automatizados

Mockimport mocker # python 2 apenas =/!from cod3 import Carro!!class CarroTests(mocker.MockerTestCase):! def test_dar_partida(self): # Inicio do treinamento MotorMock = self.mocker.mock()! MotorMock() self.mocker.result(MotorMock)! MotorMock.ligar() self.mocker.result(None)! MotorMock.ligado self.mocker.result(True)! self.mocker.replay() # Fim do treinamento! carro = Carro(motor=MotorMock) carro.dar_partida() self.assertTrue(carro.esta_ligado())

Ver também: http://docs.python.org/3.3/library/unittest.mock.html

labix.org/mocker

17

Page 18: Ensaio sobre testes automatizados

import mocker!from cod3 import Carro!!class CarroTests(mocker.MockerTestCase):! def test_dar_partida(self): # Inicio do treinamento MotorMock = self.mocker.mock()! MotorMock() self.mocker.result(MotorMock)! MotorMock.ligar() self.mocker.result(None)! #MotorMock.ligado #self.mocker.result(True)! self.mocker.replay() # Fim do treinamento! carro = Carro(motor=MotorMock) carro.dar_partida() self.assertTrue(carro.esta_ligado())

Removido o treino do atributo .ligado

18

Page 19: Ensaio sobre testes automatizados

19

"Mocke" com moderação

• Testes menos manuteníveis

• Mudanças de interface (API)

• Inconsistências entre "treinamentos"

• Prefira "mockar" os pontos de integração

• Teste os mocks! o.O

Page 20: Ensaio sobre testes automatizados

Pontos de integração

20

Page 21: Ensaio sobre testes automatizados

21

Cliente REST

http://git.io/S9YCrg

Page 22: Ensaio sobre testes automatizados

Grato! Dúvidas?

Gustavo Fonseca @gustavonsecagustavofonseca 22