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

Testes além do TDD

Testes além do TDD

Avatar for Vinícius Alonso

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