Tomasz Kowal, líder técnico do ClubCollect, apresentou no Lambda Days 2019 uma introdução de testes com base na propriedade stateful. Estes testes ajudaram as principais empresas a encontrar bugs que não foram detectados por meio de outros testes. Os testes baseado em propriedades stateful utilizam um modelo subjacente do sistema de teste para gerar sequências mais interessantes, aumentando a probabilidade de encontrar bugs.
Para ilustrar os testes baseados em propriedades, Kowal detalha como três empresas encontraram bugs nos sistemas, que não foram encontrados por métodos baseados em exemplos.
Quviq, o autor da ferramenta de teste baseada na propriedade QuickCheck, testou o sistema AUTOSAR para a Volvo, fabricante automotivo. O AUTOSAR é um barramento que conecta todos os dispositivos eletrônicos de um determinado veículo. Como são rigorosos os requisitos de certificação na indústria automobilística há a necessidade de testar minuciosamente os dispositivos incorporados e o sistema que os conecta. Enquanto os dispositivos incorporados foram testados individualmente pelas respeitadas equipes, os testes baseados em propriedades permitiram ao Quviq encontrar um comportamento incorreto não detectado. Quando o volume do rádio era aumentado ou diminuído, os freios não funcionavam. Este bug foi encontrado em uma semana, após o desenvolvimento do modelo do sistema de teste. O problema raiz acabou por ser devido a diferentes Endianess usadas em diferentes partes do sistema. As operações de rádio que tiveram a menor prioridade de todas as ações acabaram adquirindo a prioridade mais alta do que as operações de freios devido a uma mudança de Endianess (leia mais sobre o caso em Little Endian vs. Big Endian).
O armazenamento de valores-chave LevelDB do Google teve um problema recorrente com chaves fantasmas. Depois de modelar o banco de dados e usar testes baseados em propriedades, o Google encontrou exemplos reproduzíveis que levaram ao problema de chave fantasma. O exemplo mínimo consistiu em 17 operações consecutivas. Embora esse exemplo seja grande o suficiente para não aparecer nos testes de unidade gerados por testes humanos, é curto o suficiente para ser verificado e para identificar a causa raiz do comportamento.
O último exemplo foi o Dropbox que envolve teste de software distribuído e altamente simultâneo. Para modelar o comportamento do DropBox, que não determinava as ordens de quais operações eram recebidas, e com o uso da base de propriedade, os pesquisadores foram capazes de identificar a ordem das operações, que levou à perda de dados.
Kowal sinaliza a falta de recursos de nível intermediário, explicando como usar os testes baseados em propriedades de maneira diária no software. A maioria dos recursos conhecidos é bem simples (testando estruturas de dados), subestimando o escopo da aplicabilidade da técnica ou ilustrando sumariamente vitórias épicas para softwares grandes e sistemas complexos, como os exemplos citados acima.
O teste baseado em propriedades depende das propriedades que podem ser gravadas em pseudocódigo como:
for all (x, y, ...)
such as precondition(x, y, ...) holds
property(x, y, ...) is true
Exemplos introdutórios geralmente ilustram a técnica com o teste de uma estrutura ou função de dados, registrando as entradas e saídas e verificando se todas as propriedades especificadas estão válidas.
Poucos exemplos conhecidos tratam o testes baseados em propriedades (TBP) como sendo um stateful aplicado ao teste de sistemas ativos reais. Em sua palestra, Kowal dá um exemplo. O processo envolve a identificação de propriedades, a construção de um modelo estável para o sistema em teste, usando esse modelo para gerar sequências de testes interessantes, executando o teste nas sequências do sistema atual, comparando com cada etapa da execução o comportamento do sistema e produzindo resultados previstos pelo modelo e reduzindo as sequências de teste com falha para uma expressão mínima.
Para ajudar a identificar propriedades, Scott Wlaschin, arquiteto sênior e mantenedor de um recurso popular de aprendizado de F#, sugere uma taxonomia orientativa das propriedades:
- Caminhos diferentes, mesmo destino;
- Lá e cá outra vez;
- Algumas coisas nunca mudam;
- Quanto mais as coisas mudam, mais permanecem iguais;
- Primeiro resolva o menor problema;
- Difícil de provar, fácil de verificar;
- O oráculo de teste.
Gerar boas sequências de teste com maior probabilidade de encontrar bugs é fundamental para o sucesso de qualquer método de teste. No exemplo dado na palestra, um banco de dados de pacientes é modelado por um armazenamento de valores-chave, que manipula dois comandos, pesquisar e adicionar um paciente. Uma geração ingênua de sequências de teste resulta em sequências que contêm qualquer número dos dois comandos em qualquer ordem, envolvendo pacientes não relacionados:
search(p1)
add(p2, name1, surname1)
search(p3)
add(p4, name2, surname2)
Sequências mais interessantes podem ser geradas adicionando estados ao processo de geração da sequência de teste. Isso permite comandos mais inteligentes que levam em consideração as entradas de testes anteriores:
Search for existing patient
Search missing patient
Add new patient
Add patient who already exists
Enquanto o exemplo discutido por Kowal é apresentado com Erlang como linguagem base, a técnica é aplicável a qualquer outra, incluindo JavaScript.
O vídeo completo gravado no Lambda Days 2019 está disponível online. O Lambda Days é uma conferência de desenvolvedores com foco em métodos e técnicas de programação funcional. O Lambda Days 2020 será realizado nos dias 13 e 14 de fevereiro de 2020 na cidade de Cracóvia, Polônia.