Aqui está um exemplo básico do que meu teste de unidade precisa ser, usando o qunit:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<link rel="stylesheet" href="qunit/qunit-1.13.0.css">
<script src = "qunit/qunit-1.13.0.js"></script>
<script src = "../js/fuzzQuery.js"></script>
<script>
test("Fuzz Query Basics", function()
{
equal(fuzzQuery("name:(John Smith)"), "name:(John~ Smith~)");
equal(fuzzQuery("name:Jon~0.1"), "name:Jon~0.1");
equal(fuzzQuery("Jon"), "Jon~");
//etc
}
);
</script>
</head>
<body>
<div id="qunit"></div>
</body>
</html>
Agora eu estava pensando que isso é um pouco repetitivo.
Poderia colocar todas as entradas / saídas em uma matriz e passar por ela.
test("Fuzz Query Basics", function()
{
var equals = [
["name:(John Smith)", "name:(John~ Smith~)"],
["name:Jon~0.1", "name:Jon~0.1"],
["Jon", "Jon~"]
];
for (var i = 0; i<equals.length; i++)
{
equal(fuzzQuery(equals[i][0]), equals[i][1]);
}
}
);
E isso funciona bem.
A única vantagem que posso pensar para esse segundo método é que, se você realmente não quiser usar equal
, será mais fácil fazer essa alteração em um único local.
Em termos de legibilidade, não acho que seja conclusivo de qualquer maneira, embora provavelmente prefira o segundo.
Abstraindo ainda mais, você pode colocar os casos de entrada / saída em um arquivo CSV separado, o que pode facilitar a modificação.
A pergunta é: quais são as convenções gerais sobre como escrever esses tipos de testes de unidade?
Existe uma razão para você não colocá-los em matrizes?
fonte
Respostas:
Seus testes refatorados têm um cheiro: Lógica Condicional de Testes .
Os motivos pelos quais você deve evitar escrever lógica condicional em seus testes são duplos. A primeira é que isso prejudica sua capacidade de ter certeza de que seu código de teste está correto, conforme descrito no artigo vinculado de padrões do xUnit.
A segunda é que obscurece o significado dos testes. Escrevemos Métodos de Teste porque eles colocam a lógica para testar um determinado comportamento em um único local e nos permitem dar um nome descritivo (consulte o artigo original do BDD de Dan North para uma exploração do valor de bons nomes para testes). Quando seus testes estão ocultos em uma única função com um
for
loop, oculta o significado do código para o leitor. O leitor não apenas precisa compreender o loop, mas também desvendar mentalmente todos os diferentes comportamentos sendo testados dentro do loop.A solução, como sempre, é subir um nível de abstração. Use uma estrutura de teste que ofereça testes parametrizados , como xUnit.NET ou Contexts (isenção de responsabilidade: escrevi Contexts). Isso permite agrupar testes de triangulação para o mesmo comportamento de maneira natural, mantendo os testes para comportamentos separados separados.
fonte
Parece que você realmente deseja um teste de unidade orientado a dados. Desde que você mencionou o uso do QUnit, encontrei um plug-in que permite testes parametrizados:
https://github.com/AStepaniuk/qunit-parameterize
Não há nada ideologicamente errado em um teste orientado a dados, desde que o código de teste em si não seja condicional. Olhando para o seu código de teste, ele parece ser um candidato muito bom para um teste orientado a dados.
Exemplo de código para o README do GitHub:
fonte
Você está se repetindo menos usando a matriz que é mais sustentável. Uma abordagem que eu gosto de usar é ter um método separado que organize, atue e afirme os testes, mas aceite os parâmetros de entrada com os quais estou testando, por isso tenho 1 método de teste por conjunto de entradas.
Isso me permite dizer instantaneamente quais testes / entradas estão falhando.
fonte
Eu gosto da sua segunda abordagem, mas gostaria de adicionar 2 pontos
for
loops`
Não tenho certeza sobre o qunit, mas um bom executor de testes mostrará qual sequência de entrada falhou e qual foi o resultado esperado.
fonte