Construímos um número substancial de testes de unidade para o nosso programa principal ao longo dos anos. Vários milhares. O problema é que não temos uma ideia clara de quais testes temos, porque existem muitos. E isso é um problema, porque não sabemos onde somos fracos nos testes (ou onde temos duplicatas).
Nosso aplicativo é um mecanismo de relatórios. Assim, você pode ter um modelo usado para testar a análise (lemos todas as propriedades da tabela), mesclando dados (mantivemos as propriedades corretas da tabela na mesclagem), formatando a página final (a tabela é colocada corretamente na página) ) e / ou o formato de saída (o arquivo DOCX criado está correto).
Adicione a isso o que precisamos testar. Pegue o preenchimento em torno de uma célula da tabela (usamos Word, Excel e PowerPoint para o design do relatório). Temos que testar o preenchimento na quebra de página, para uma tabela dentro de uma célula, células mescladas verticalmente, células mescladas horizontalmente, uma célula mesclada vertical e horizontalmente que contém uma tabela com células mescladas vertical e horizontalmente na tabela interna, onde essa tabela quebra em uma página.
Então, em que categoria esse teste entra? Preenchimento de tabela, quebras de página, células aninhadas, células mescladas verticalmente, células mescladas horizontalmente ou algo mais?
E como documentamos essas categorias, nomeamos os testes de unidade etc.?
Atualização: várias pessoas sugeriram o uso de ferramentas de cobertura para verificar se temos cobertura total. Infelizmente, isso é de uso limitado no nosso caso, porque os bugs tendem a ser devidos a combinações específicas, por isso é o código que foi todo testado, mas não nessa combinação.
Por exemplo, ontem tivemos um cliente que iniciou um marcador do Word no final de um loop forEach em seu modelo (um documento do Word) e o finalizou no início do próximo loop forEach. Todo esse código foi usado com testes de unidade, mas não tínhamos pensado na combinação de um modelo expandindo um início de marcador para ser iniciado 25 vezes e depois terminado 10 vezes (os dois loops forEach tinham um número diferente de linhas).
fonte
Respostas:
Geralmente, costumo espelhar a árvore de origem para meus testes de unidade. Portanto, se eu tivesse src / lib / fubar, teria um teste / lib / fubar que conteria os testes de unidade para o fubar.
No entanto, o que você parece estar descrevendo são testes mais funcionais. Nesse caso, eu teria uma tabela multidimensional que enumerasse todas as suas condições possíveis. Então, aqueles que não têm testes não fazem sentido ou precisam de um novo teste. É claro que você pode colocá-los em conjuntos de suítes de teste.
fonte
A estrutura mais comum parece ser o espelho do diretório
src
etest
.No entanto, há uma estrutura alternativa que eu vi que agora acredito ser melhor.
Como o teste de unidade tende a espelhar a classe que eles estão testando, colocá-los no mesmo diretório fornece acesso muito mais fácil aos arquivos, para que você possa trabalhar lado a lado.
fonte
No .NET, costumo espelhar, ou pelo menos aproximar, a estrutura do espaço para nome do código-fonte nos projetos de teste, abaixo do espaço para nome mestre "Tests.Unit" ou "Tests.Integration". Todos os testes de unidade são executados em um projeto, com a estrutura básica do código-fonte replicada como pastas no projeto. O mesmo para testes de integração. Portanto, uma solução simples para um projeto pode ser assim:
Para quaisquer AATs ou AEETs codificados com uma estrutura de teste de unidade, isso muda um pouco; geralmente esses testes refletem um conjunto de etapas que testam a funcionalidade de um novo caso de uso ou história. Geralmente estruturo esses testes em um
MyProduct.Tests.Acceptance
projeto como tal, com testes para cada história, possivelmente agrupados por marcos ou história "épica" à qual a história em desenvolvimento pertencia. No entanto, esses são realmente apenas testes de integração excessiva e, portanto, se você preferir estruturar os testes de maneira mais orientada a objetos, em vez de orientada a histórias, nem precisa de umMyProduct.Tests.Acceptance
projeto semelhante; basta jogá-los noMyProduct.Tests.Integration
escopo do objeto de nível mais alto em teste.fonte
Não há razão para um teste de unidade estar em apenas uma categoria. Todos os principais conjuntos de ferramentas de teste de unidade apoiar a criação de conjuntos de testes , que empacotam testes para uma determinada categoria. Quando uma área específica do código é alterada, o desenvolvedor deve executar esse conjunto primeiro e frequentemente para ver o que está quebrado. Quando um teste preocupações estofamento e breaks e nidificação, por todos os meios colocá-lo em todos os três suites.
Dito isso, o objetivo dos testes de unidade é executá-los o tempo todo, ou seja, eles devem ser pequenos e rápidos o suficiente para que seja possível executá-los todos antes de cometer qualquer código. Em outras palavras, não importa realmente qual é a categoria de um teste, ele deve ser executado antes de ser confirmado. As suítes são realmente apenas uma muleta que você usa se, por algum motivo, não puder escrever testes tão rápidos quanto deveriam.
Quanto à cobertura, existem ferramentas de cobertura muito boas que informam qual porcentagem de linhas foi realmente executada ao executar seus testes - esse é um indicador óbvio do tipo de teste que você ainda está perdendo.
Quanto à nomenclatura, não há valor particular em gastar esforços nos nomes dos testes de unidade. Tudo o que você deseja ouvir de seus testes é "5235 dos 5235 testes aprovados". Quando um teste falha, o que você lê não é o nome, mas a mensagem , por exemplo, a String no
assert()
que implementa sua crítica de sucesso. A mensagem deve ser informativa o suficiente para que você tenha uma idéia do que está errado sem ler o corpo do teste. O nome não é importante em comparação com isso.fonte
Uma maneira de saber se você é fraco nos testes é a rastreabilidade. Geralmente para testes, isso assume a forma de cobertura.
O objetivo é medir quais partes do código são exercidas pelos seus testes, para que você possa ver o código que não é coberto pelos seus testes. Cabe a você (e à ferramenta de cobertura) definir o que é uma "parte do código". O mínimo é a cobertura do ramo.
fonte