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

Escrever testes vs testar

Escrever testes vs testar

Nesta talk, discuto a diferença entre escrever testes... e testar!

Mauricio Aniche

May 22, 2020
Tweet

More Decks by Mauricio Aniche

Other Decks in Technology

Transcript

  1. TDD • Já sabemos que: • Vermelho -> Verde ->

    Refatora • “TDD é sobre design, não sobre teste” • “Se seu código é difícil testar, é pq o design precisa mudar” • O que mais tem pra falar?
  2. Escrever testes vs testar • Ritmo de trabalho • Reflete

    sobre o código e design • Refatoração como parte do ciclo • Geração de modelos pra suportar o teste • Análise do domínio • Análise do limite (boundary) • Teste estrutural como complemento • Teste inteligente (AI, análise estática, mutante)
  3. Escrever testes vs testar • Ritmo de trabalho • Reflete

    sobre o código e design • Refatoração como parte do ciclo • Geração de modelos pra suportar o teste • Análise do domínio • Análise do limite (boundary) • Teste estrutural como complemento • Teste inteligente (AI, análise estática, mutante, fuzzing) Todo mundo fala sobre na comunidade! Poucos falam sobre na comunidade!
  4. Modelos! • Não descarte a possibilidade de criar modelos que

    te ajudarão no teste. • Modelos abstraem a complexidade do sistema, e te ajudam a ver o que importa. • (“Ah, mas agile fala pra não fazer documentação… Meus amigos vão me chamar de Waterfallzeiro se eu committar algo que não é código!) • Claro que só onde faz sentido!
  5. Passive learning Modelar o comportamento do sistema a partir de

    observações do sistema real. 20170101160001 Adyen version: ****** 20170101160002 Starting TX/amt=10001/currency=978 20170101160003 Starting EMV 20170101160004 EMV started 20170101160005 Magswipe opened 20170101160006 CTLS started 20170101160007 Transaction initialised 20170101160008 Run TX as EMV transaction 20170101160009 Application selected app:****** 20170101160010 read_application_data succeeded 20170101160011 data_authentication succeeded 20170101160012 validate 0 20170101160013 DCC rejected 20170101160014 terminal_risk_management succeeded 20170101160015 verify_card_holder succeeded 20170101160016 generate_first_ac succeeded 20170101160017 Authorizing online 20170101160018 Data returned by the host succeeded 20170101160019 Transaction authorized by card 20170101160020 Approved receipt printed 20170101160021 pos_result_code:APPROVED 20170101160022 Final status: Approved 20170101160001 Adyen version: ****** 20170101160002 Starting TX/amt=10001/currency=978 20170101160003 Starting EMV 20170101160004 EMV started 20170101160005 Magswipe opened 20170101160006 CTLS started 20170101160007 Transaction initialised 20170101160008 Run TX as EMV transaction 20170101160009 Application selected app:****** 20170101160010 read_application_data succeeded 20170101160011 data_authentication succeeded 20170101160012 validate 0 20170101160013 DCC rejected 20170101160014 terminal_risk_management succeeded 20170101160015 verify_card_holder succeeded 20170101160016 generate_first_ac succeeded 20170101160017 Authorizing online 20170101160018 Data returned by the host succeeded 20170101160019 Transaction authorized by card 20170101160020 Approved receipt printed 20170101160021 pos_result_code:APPROVED 20170101160022 Final status: Approved 20170101160001 Adyen version: ****** 20170101160002 Starting TX/amt=10001/currency=978 20170101160003 Starting EMV 20170101160004 EMV started 20170101160005 Magswipe opened 20170101160006 CTLS started 20170101160007 Transaction initialised 20170101160008 Run TX as EMV transaction 20170101160009 Application selected app:****** 20170101160010 read_application_data succeeded 20170101160011 data_authentication succeeded 20170101160012 validate 0 20170101160013 DCC rejected 20170101160014 terminal_risk_management succeeded 20170101160015 verify_card_holder succeeded 20170101160016 generate_first_ac succeeded 20170101160017 Authorizing online 20170101160018 Data returned by the host succeeded 20170101160019 Transaction authorized by card 20170101160020 Approved receipt printed 20170101160021 pos_result_code:APPROVED 20170101160022 Final status: Approved 20170101160001 Adyen version: ****** 20170101160002 Starting TX/amt=10001/currency=978 20170101160003 Starting EMV 20170101160004 EMV started 20170101160005 Magswipe opened 20170101160006 CTLS started 20170101160007 Transaction initialised 20170101160008 Run TX as EMV transaction 20170101160009 Application selected app:****** 20170101160010 read_application_data succeeded 20170101160011 data_authentication succeeded 20170101160012 validate 0 20170101160013 DCC rejected 20170101160014 terminal_risk_management succeeded 20170101160015 verify_card_holder succeeded 20170101160016 generate_first_ac succeeded 20170101160017 Authorizing online 20170101160018 Data returned by the host succeeded 20170101160019 Transaction authorized by card 20170101160020 Approved receipt printed 20170101160021 pos_result_code:APPROVED 20170101160022 Final status: Approved 20170101160001 Adyen version: ****** 20170101160002 Starting TX/amt=10001/currency=978 20170101160003 Starting EMV 20170101160004 EMV started 20170101160005 Magswipe opened 20170101160006 CTLS started 20170101160007 Transaction initialised 20170101160008 Run TX as EMV transaction 20170101160009 Application selected app:****** 20170101160010 read_application_data succeeded 20170101160011 data_authentication succeeded 20170101160012 validate 0 20170101160013 DCC rejected 20170101160014 terminal_risk_management succeeded 20170101160015 verify_card_holder succeeded 20170101160016 generate_first_ac succeeded 20170101160017 Authorizing online 20170101160018 Data returned by the host succeeded 20170101160019 Transaction authorized by card 20170101160020 Approved receipt printed 20170101160021 pos_result_code:APPROVED 20170101160022 Final status: Approved Rick Wieman, Maurício Aniche, Willem Lobbezoo, Sicco Verwer and Arie van Deursen. An Experience Report on Applying Passive Learning in a Large-Scale Payment Company. ICSME Industry Track, 2017
  6. Signup Error Login Error Registering About Authenticating not-ok not-ok close

    close ok Authenticated ok logoff about signup login Public
  7. Análise do domínio e limites • Estudos empíricos mostram que

    um grande número de bugs acontecem nas “fronteiras” do domínio. • Teste os limites! • Tem um if(x > 10), testa o que acontece entre 9, 10, 11. • Tem um for? Testa 0, 1, N. • Analisar variável por variável por ajudar. • Você pensa em todas fronteiras quando faz TDD? • Eu não! L https://sttp.site/chapters/testing-techniques/domain-testing.html
  8. Teste estrutural • (“Ah, code coverage não serve pra nada,

    é fácil de enganar, patati patató”) • Code coverage não é sobre um número. • É sobre aumentar a sua suíte de testes (que você criou baseado no que sabe do requisito) baseado no que você vê no código. • A ferramenta de cobertura pode te ajudar a encontrar códigos que não são explícitos no requisito. https://sttp.site/chapters/testing-techniques/structural-testing.html
  9. Dublês e mocks • Facilitam demais o teste. • Em

    especial quando dependências são difíceis ou caras de serem simuladas. • Escolha o tipo de dublê certo: • Fake: uma implementação simplística • Stubs: retorna valores hard-coded • Mocks: grava as interações com o objeto, pq depois você vai perguntar se elas aconteceram! • Decidir ou não se mockar é uma boa ideia! https://sttp.site/chapters/pragmatic-testing/test-doubles.html
  10. State testing vs interaction testing • Duas escolas diferentes de

    TDD. • Classical vs London • State vs Interaction testing • State testing: eu testo a “mudança de estado” do meu objeto. • Invoco método A.a(), não ligo pra como A.a() faz o trabalho, ou de quem ele depende, faço a asserção para garantir que A tem um novo estado. • Interaction testing: eu testo “interação” entre dependências • Invoco método A.a(). A depende de uma abstração B. Eu garanto que A invoca B da maneira correta. • Pensa nos seus Mockito.verify(). Você está garantindo a integração.
  11. To mock or not mock? • “Se você usa mock,

    você tá testando o mock!” • Problema: • SuperServico depende de RepositorioDeNotasFiscais#pegaTodasDoMes(). • pegaTodasDoMes() nunca retorna nulo. • Quando testa SuperServico, desenvolvedor mocka pegaTodasDoMes() • Testes passam • No futuro, desenvolvedor 2 faz pegaTodasDoMes() retornar nulo. • Testes passam, mas em produção quebra. • O problema é manter o mock com o mesmo contrato da classe original. • Difícil mockar se design é inconstante. Requer times com bons designers!
  12. Design-by-contracts • Pense de maneira rigorosa sobre o contrato que

    seus métodos e serviços oferecem pro mundo de fora. • Pré-condições, pós-condições, invariantes. • Deixe-as explícitas no código! • Mudou alguma delas? Análise em cascata! • Hyrum’s law: “Dado um número suficiente de clientes, não importa o que você promete no contrato. Todo e qualquer comportamento observado no sistema será dependido por alguém”. https://www.hyrumslaw.com https://sttp.site/chapters/testing-techniques/design-by-contracts.html
  13. Teste inteligente • Até então, você desenhou os todos. A

    máquina só executou! • Pq não deixar a máquina criar uns testes pra você também? • Não, não é ficção! • Não, AI não vai dominar o mundo! • Pense em: • Análise estática • Testes de mutantes • Fuzz testing • Geração automática de casos de testes https://sttp.site/chapters/intelligent-testing/
  14. Análise estática • Desde linters simples até análises mais complicadas.

    • Veja Facebook’s Infer • Veja Google’s errorprone • Veja Uber’s NullAway https://sttp.site/chapters/intelligent-testing/static-testing.html
  15. Testes de mutante • Uma suíte de testes forte é

    aquela que te revela bugs, quando bugs acontecem. • Mutante: uma pequena variação (bugada) do seu código. Seu teste falha? • Imagina um “if(x>10)”. Se eu trocasse por “if(x>=10)”, algum teste falharia? • Sim? Ótimo. Não? Talvez valha a pena reforçar a sua suíte de teste. • Hipótese: • código é escrito por um programador “competente” e erros acontecem por combinações de erros simples. • “Falhas complicadas” acontecem por causa de “falhas simples”. https://sttp.site/chapters/intelligent-testing/mutation-testing.html
  16. Geração automática de teste • Se você parar pra pensar,

    um caso de teste é: • Cria a classe, pelo construtor. • Invoca um método. • Passa valores pra esse método • Faz a asserção no final. • A máquina pode criar código como esse! https://sttp.site/chapters/intelligent-testing/sbst.html
  17. Problema do oráculo • Como saber o que um programa

    tem que produzir? • Difícil… • Mas sabemos de muitas coisas, independente do programa. • Ele não pode soltar exceção. • A app mobile não pode congelar. • Ele não pode demorar mais que X segundos. • Até contextual: Ele não pode retornar nota fiscal com valor negativa… • Esse tipo de bug, a máquina pode facilmente procurar pra você!
  18. Ferramentas estão aí (mas ainda não maduras)! • Randoop: gera

    aleatório! • EvoSuite: usa algoritmo genético pra achar uma boa suíte de testes!
  19. Não falei de… • Design de código de teste •

    Invista em infraestrutura de testes • Leia sobre design patterns e code smells em códigos de teste • Property-based testing • Boa ideia, em especial quando combinado com DbC • (Eu tenho pouca experiência prática…) • Design for testability • Boas práticas de arquitetura para facilitar testes. • Fundamental!! • Decidir nível do teste • Sinto que todo mundo já tem um bom feeling de quando usar teste de unidade ou teste de sistema