Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Testes além do TDD

Testes além do TDD

Vinícius Alonso

June 21, 2023
Tweet

More Decks by Vinícius Alonso

Other Decks in Programming

Transcript

  1. 11

  2. Funcionais x Não funcionais • Feitos geralmente por devs •

    O foco é testar requisitos funcionais • Testa a conformidade dos requisitos do cliente 12 • Podem ser feitos por stakeholders • Foco é testar requisitos não funcionais • Testa as expectativas do cliente
  3. Funcionais x Não funcionais • Testes unitários • Testes de

    integração • Testes de sistema • Testes de contrato • Testes alpha/beta 13 • Testes de performance ◦ Teste de carregamento ◦ Teste de stress • Testes de segurança • Testes de usabilidade
  4. Testes unitários • Testa um componente de forma isolada ◦

    Classe ◦ Método ◦ Função ◦ .. 15
  5. 16 public function testShouldBePalindrome () { $checker = new Checker();

    $isPalindrome = $checker->isPalindrome('arara') $this->assertTrue($isPalindrome); }
  6. Testes de integração • Testa como diferentes partes do sistema

    se comportam ◦ Controllers ◦ Models ◦ DB ◦ ... 17
  7. 18 public function testCreateUserByPOST() { $response = $this->json('POST', '/users', ['name'

    => 'Juca']); $this->assertStatus(201) ->assertJson([ 'created' => true ]); }
  8. Testes de Sistema • Testa como o comportamento do ponto

    de vista do usuário ◦ Acessa uma página ◦ Clica nos links ◦ Preenche formulários ◦ … • Automatiza passos do usuário de uma forma programática 19
  9. 20 public function testBasicExample () { $user = factory(User:: class)->create();

    $this->browse(function ($browser) use ($user) { $browser->visit( '/login') ->type( 'email', $user->email) ->type( 'password', 'password') ->press( 'Login') ->assertPathIs( '/home'); }); }
  10. Testes de contrato • Contrato é o que esperamos de

    outra parte ◦ XML ◦ JSON ◦ ... • Testes de contrato validam ◦ respostas externas à nossa aplicação ◦ Objetos disponíveis 21
  11. 22

  12. 23

  13. Testes alpha e beta • Consistem em criar um ambiente

    semelhante ao de prod • Testa alpha ◦ Equipe dev ◦ Encontrar possíveis falhas ◦ Ver como as funcionalidades se comportam • Teste beta ◦ Usuários ◦ Feedbacks/Melhorias 24
  14. 27

  15. Testes de stress • Testa a capacidade da aplicação para

    responder a múltiplas requisições ◦ Neotys ◦ ... 28
  16. 29

  17. Testes de segurança • Busca possíveis brechas na segurança que

    possam comprometer os usuários ◦ Arachni ◦ ... 30
  18. 31

  19. Kent Beck: um pouco de história • Escreveu Sunit 1994

    • Apresentou TDD na OOPSLA 1995 • Junto com Erich Gramma publicou “Test Infected” (2000) • TDD by Example 33
  20. 34

  21. 35 public function testShouldBePalindrome () { $checker = new Checker();

    $isPalindrome = $checker->isPalindrome('arara') $this->assertTrue($isPalindrome); }
  22. 36 class Checker { public function isPalindrome(string $word) : bool

    { $originalWord = str_replace(' ', '', strtolower($word)); $reversed = str_replace(' ', '', strrev($originalWord)); return $originalWord == $reversed; } }
  23. Detalhes sobre TDD Algumas curiosidades sobre a prática que geralmente

    não entendemos de cara quando começamos a estudar 37
  24. “ As suítes de testes não são tão fiéis ao

    que estudamos na literatura. 40
  25. 41

  26. Conhecendo a família xUnit Agora que já entendemos um pouco

    de TDD, vamos falar sobre as suítes de testes. 4
  27. Gerard Meszaros • Estudou as estruturas das principais suítes de

    testes • Lançou xUnit Test Patterns (2007) 43
  28. As fases do xUnit • Setup ◦ Preparamos o ambiente

    para o teste • Exercise ◦ Simulamos o comportamento que esperamos testar • Verify ◦ Verificamos se ele teve o resultado esperado • Teardown ◦ Fazemos o ambiente voltar ao normal, como se o teste nunca tivesse acontecido 44
  29. 45 public function testShouldBeInactivated () { $this->user = User::create( $this->data);

    $this->user->setStatus(UserStatus::INACTIVE); $this->assertFalse($this->user->isActive()); } public function teardown() { $this->user->destroy(); }
  30. 46 public function testShouldBeInactivated () { $this->user = User::create( $this->data);

    $this->user->setStatus(UserStatus::INACTIVE); $this->assertFalse($this->user->isActive()); } public function teardown() { $this->user->destroy(); } Setup Exercise Verify Teardown
  31. SUT e colaboradores • SUT (System Under Test) ◦ O

    que está sendo testado em si ◦ Classe, método, função, etc • Colaboradores ◦ Interagem com o SUT durante a execução do teste 47
  32. 48 public function testShouldSumItemsValueAtCart () { $product = new Product(['value'

    => 20]); $item = new Item(['quantity' => 2, 'product' => $product]); $cart = new Cart(); $cart->addItem($item); $this->assertEquals(40, $cart->totalValue()); }
  33. 49 public function testShouldSumItemsValueAtCart () { $product = new Product(['value'

    => 20]); $item = new Item(['quantity' => 2, 'product' => $product]); $cart = new Cart(); $cart->addItem($item); $this->assertEquals(40, $cart->totalValue()); } Colaboradores SUT
  34. Colaboradores • No exemplo anterior utilizamos as classes reais para

    testar o SUT • Podemos substituir esses colaboradores reais por dublês, com isso, poderíamos chamar de Test Double 50
  35. Test Doubles • Termo genérico para testes que substituem objetos

    de produção por: ◦ Dummy; ◦ Fake; ◦ Stub; ◦ Spy; ◦ Mock; 52
  36. Dummy • São utilizados para preencher listas de parâmetros, porém,

    não são utilizados • Existem dois tipos: ◦ Dummy Object ◦ Dummy Value 53
  37. 54 public function depositMoney(float value, Account $account) { if ($value

    <= 0) { throw new \InvalidArgumentException(); } $account->subtractCurrentBalance( $value); }
  38. 55 /** * @expectedException InvalidArgumentException * */ public function testWhenValueLessOrEqualZeroShouldThrowAnException

    () { $account = $this->prophesize(Account::class); $deposit = new Deposit(); $deposit->depositMoney(-10, $account->reveal(); }
  39. Fake • Substituem objetos para criar atalhos ou formas mais

    fáceis de executar algo • Exemplo: InMemoryTestDatabase 56
  40. 57 class ClientRepositoryFake { private $clients = []; public function

    save(Client $client) : Client { $id = count($this->clients); $client->setId($id); $this->clients[$id] = $client; return $client; } public function find(int $id) : Client { return $this->clients[$id]; } public function update(Client $client) : Client { $this->clients[$client->getId()] = $client; return $client; } }
  41. 58 public function setup() { $client = new Client(['name' =>

    'Gandalf', 'cpf' => '87511196098']); $this->clientRepository = new ClientRepositoryFake(); $this->clientRepository->save($user); } public function testAssociateShouldGenerateAccountNumber() { $client = $this->clientRepository->find(1); $account = new Account(); $account->setClient($client); $accountAssociator = AccountAssociator(); $accountAssociator->associateAccountToClient($account, $client); $this->assertNotNull($account->getNumber()); }
  42. Stub • Fornece respostas prontas programadas para chamadas específicas em

    momento de execução • São utilizados na fase do setup 59
  43. 60 public function create() { if (!$this->validator->isCPFValid( $this->data['cpf']) { throw

    new \Exception('Invalid CPF'); } return $this->repository->create(); }
  44. 61 public function testShouldCreateAccountWhenCPFIsValid () { $validator = $this->prophesize(Validator::class); $validator->isCPFValid('23430222915')->willReturn(true);

    $data = ['cpf' => '23430222915']; $account = new Account($data); $account->setValidator($validator->reveal()); $this->instanceOf(Account::class, $account->create()); }
  45. Spy • Possue controle sobre as chamadas que são feitas

    em tempo de execução • Se foco é saber se determinado método/função foi chamado e como foi 62
  46. 64 public function shouldSaveNewAddress() { $em = $prophet->prophesize('Doctrine\ORM\EntityManager' ); $address

    = new Address(); $addressRepository = new AddressRepository($em->reveal()); $addressRepository->save($address); $em->flush()->shouldHaveBeenCalled(); }
  47. Mock • São utilizados na fase do verify • Diferente

    dos demais, é o único que faz a verificação por comportamento e não por estado 65
  48. 66 public function create() { if (!$this->validator->isCPFValid( $this->data['cpf']) { throw

    new \Exception('Invalid CPF'); } return $this->repository->create(); }
  49. public function testShouldCreateAccountWhenCPFIsValid() { $validator = $this->prophesize(Validator::class); $validator->isCPFValid('23430222915') ->willReturn(true) ->shouldBeCalled($this->once());

    $repository = $this->prophesize(Repository::class); $repository->create()->shouldBeCalled($this->once()); $data = ['cpf' => '23430222915']; $account = new Account($data); $account->setValidator($validator->reveal()); $account->setRepository($repository->reveal()); $account->create(); }
  50. BDD • Behaviour Driven Development • É uma metodologia na

    qual todos os stakeholders são envolvidos • Começa com especificações do cliente e termina no projeto entregue 69
  51. 70

  52. 71 BDD • Feature: … ◦ Scenario: … ▪ When:

    … ▪ And: … ▪ Then: … • Especificações executáveis
  53. 72 BDD x TDD • Começa descrevendo features e scenarios

    • Envolve vários stakeholders • Foco no comportamento final • Começa escrevendo casos de teste • Envolve apenas devs • Foco na implementação
  54. Projetos legados • De dentro para fora • Testar apenas

    código modificado • Testar apenas os requisitos • Adicionar apenas código testado • Quebrar dependências escondidas 74
  55. Referências • https:/ /martinfowler.com/bliki/InMemoryTestDatabase.ht ml • https:/ /martinfowler.com/bliki/TestDouble.html • https:/

    /martinfowler.com/articles/mocksArentStubs.html • https:/ /www.amazon.com.br/Xunit-Test-Patterns-Refacto ring-Code/dp/0131495054 • https://www.softwaretestinghelp.com/functional-testing-vs-no n-functional-testing/ 83
  56. Referências • https://docs.pact.io/ • https://martinfowler.com/bliki/ContractTest.html • https://martinfowler.com/articles/practical-test-pyramid.html • https://medium.com/edureka/types-of-software-testing-d7aa2 9090b5b

    • https://hackr.io/blog/top-10-open-source-security-testing-tools -for-web-applications • https://danlimerick.wordpress.com/2012/04/25/tdd-when-up-t o-your-neck-in-legacy-code/ 84