Oto podstawowy przykład tego, czym powinien być mój test jednostkowy, za pomocą 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>
Teraz myślałem, że to trochę powtarzalne.
Można umieścić wszystkie wejścia / wyjścia w tablicy i przejść przez nią.
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]);
}
}
);
I to działa dobrze.
Jedyną zaletą tej drugiej metody, jaką mogę wymyślić, jest to, że jeśli okaże się, że tak naprawdę nie chcesz jej używać equal
, łatwiej jest dokonać tej zmiany w jednym miejscu.
Jeśli chodzi o czytelność, nie sądzę, że jest to jednoznaczne, chociaż prawdopodobnie wolę drugą.
Abstrahując go dalej, możesz umieścić przypadki wejścia / wyjścia w osobnym pliku CSV, co może ułatwić modyfikację.
Pytanie brzmi - jakie są ogólne konwencje dotyczące pisania tego rodzaju testów jednostkowych?
Czy istnieje powód, dla którego nie powinieneś umieszczać ich w tablicach?
źródło
Odpowiedzi:
Twoje refaktoryzowane testy mają zapach: Logika testów warunkowych .
Powody, dla których należy unikać pisania logiki warunkowej w testach, są dwojakie. Po pierwsze, podważa to twoją zdolność do upewnienia się, że kod testowy jest poprawny, jak opisano w połączonym artykule Wzory xUnit.
Drugi polega na tym, że przesłania on znaczenie testów. Piszemy Metody testowe, ponieważ umieszczają logikę testowania danego zachowania w jednym miejscu i pozwalają nam nadać mu opisową nazwę (zobacz oryginalny artykuł BDD Dana Northa , aby poznać wartość dobrych nazw dla testów). Gdy testy są ukryte w jednej funkcji z
for
pętlą, przesłania to znaczenie kodu dla czytnika. Czytelnik nie tylko musi zrozumieć pętlę, ale także mentalnie rozwikłać wszystkie zachowania badane w pętli.Rozwiązaniem, jak zawsze, jest podniesienie poziomu abstrakcji. Użyj frameworka testowego, który daje sparametryzowane testy , takie jak xUnit.NET lub Contexts do (zrzeczenie się: Napisałem Contexts). Umożliwia to grupowanie testów triangulacyjnych dla tego samego zachowania razem w naturalny sposób, przy jednoczesnym zachowaniu osobnych testów dla osobnych zachowań.
źródło
Wygląda na to, że naprawdę chcesz przeprowadzić test jednostkowy oparty na danych. Ponieważ wspomniałeś o użyciu QUnit, znalazłem wtyczkę, która umożliwia sparametryzowane testy:
https://github.com/AStepaniuk/qunit-parameterize
Nie ma nic ideologicznie złego w teście opartym na danych, o ile sam kod testu nie jest warunkowy. Patrząc na kod testowy, wydaje się być bardzo dobrym kandydatem do testu opartego na danych.
Przykładowy kod GADHub README:
źródło
Powtarzasz się mniej, używając tablicy, która jest łatwiejsza w utrzymaniu. Jednym z podejść, które lubię stosować, jest oddzielna metoda, która porządkuje, wykonuje i potwierdza testy, ale akceptuje parametry wejściowe, które testuję, więc mam 1 metodę testową na zestaw danych wejściowych.
To pozwala mi natychmiast stwierdzić, które testy / wejścia zawodzą.
źródło
Podoba mi się twoje drugie podejście, ale dodałbym 2 punkty
for
pętli`
Nie jestem pewien co do qunit, ale dobry tester pokaże, który łańcuch wejściowy zawiódł i jaki był oczekiwany wynik
źródło