Вот базовый пример того, каким должен быть мой модульный тест с использованием 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>
Теперь я думал, что это немного повторяется.
Может поместить все входы / выходы в массив и пройти через него.
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]);
}
}
);
И это прекрасно работает.
Единственное преимущество, которое я могу придумать для этого второго метода, заключается в том, что, если выясняется, что вы на самом деле не хотите использовать equal
, проще сделать это изменение в одном месте.
С точки зрения читабельности, я не думаю, что это так или иначе, но я, вероятно, предпочитаю второе.
Абстрагируя его дальше, вы можете поместить случаи ввода / вывода в отдельный файл CSV, что может упростить его изменение.
Вопрос в том, каковы общие правила написания подобных тестов?
Есть ли причина, по которой вы не должны помещать их в массивы?
источник
Ответы:
Ваши рефакторированные тесты имеют запах: логика условных тестов .
Причины, по которым вам следует избегать написания условной логики в ваших тестах, двояки. Во-первых, это подрывает вашу способность быть уверенным в правильности тестового кода, как описано в связанной статье xUnit Patterns.
Во-вторых, это заслоняет смысл тестов. Мы пишем методы тестирования, потому что они помещают логику для тестирования определенного поведения в одном месте и позволяют нам дать ему описательное имя (см . Оригинальную статью Дэна Норта о BDD для изучения значения хороших имен для тестов). Когда ваши тесты скрыты внутри одной функции с
for
циклом, это скрывает смысл кода для читателя. Мало того, что читатель должен понимать цикл, он также должен мысленно разгадать все различные поведения, тестируемые в цикле.Решение, как всегда, состоит в том, чтобы подняться на уровень абстракции. Используйте тестовый фреймворк, который дает вам параметризованные тесты , как это делают xUnit.NET или Contexts (заявление об отказе: я написал Contexts). Это позволяет группировать триангуляционные тесты для одного и того же поведения естественным образом, сохраняя при этом тесты для отдельных поведений раздельными.
источник
Кажется, вы действительно хотите модульный тест, управляемый данными. Поскольку вы упомянули об использовании QUnit, я обнаружил плагин, который позволяет параметризованные тесты:
https://github.com/AStepaniuk/qunit-parameterize
В тесте, управляемом данными, нет ничего идеологического, если сам код теста не является условным. Глядя на ваш тестовый код, он кажется очень хорошим кандидатом на тест на основе данных.
Пример кода для GitHub README:
источник
Вы повторяете себя меньше, используя массив, который более удобен в обслуживании. Один из подходов, который мне нравится использовать, - это иметь отдельный метод, который организует, выполняет и утверждает тесты, но принимает входные параметры, с которыми я тестирую, поэтому у меня есть 1 метод тестирования на каждый набор входов.
Это позволяет мне мгновенно определить, какие тесты / входные данные дают сбой.
источник
Мне нравится ваш второй подход, но я бы добавил 2 балла
for
петли`
Я не уверен насчет qunit, но хороший тестировщик покажет вам, какая строка ввода не удалась, и каков был ожидаемый результат
источник