В то время как предусловия являются теми аспектами системы, которые должны быть установлены перед запуском теста, входные значения являются теми значениями, которые передаются напрямую в тестируемую функциональность. Это различие может быть трудноуловимым, поэтому давайте рассмотрим несколько примеров.
Представим, что у нас есть алгоритм сортировки billSort, который предположительно в 20 раз быстрее, чем любой другой алгоритм. Не принимая на веру то, что billSort всегда дает правильный результат, мы разрабатываем тесты для него. В одном из них используется глобальная переменная SORT_ASCENDING. В зависимости от того, какое значение принимает эта булева переменная — true или false, сортировка будет идти либо по возрастанию (от меньшего значения к большему, т. е. "a", "b", "c"), либо по убыванию (от большего значения к меньшему, т. е. "c", "b", "a"). Если мы собираемся протестировать этот алгоритм сортировки, установка флага будет считаться предусловием, т. к. это то, что должно быть установлено перед тестом. Массив ["a", "b", "c"] будет являться входными значениями; эти значения подаются напрямую для тестирования.
Другой способ понять разницу между входными значениями и предусловиями — представить себе тесты как методы. В любом случае это хорошее упражнение для вас — ведь мы займемся этим, когда дойдем до главы о юнит-тестах!
public boolean testArraySort() {
// ПРЕДУСЛОВИЯ
SORT_ASCENDING = true;
// ВХОДНЫЕ ЗНАЧЕНИЯ
int[] vals = [1, 2, 3];
// Новый улучшенный метод billSort! :)
billSorted = billSort(vals);
// Старый унылый метод сортировки из Java :(
NormalSorted = Arrays.sort(vals);
if (Arrays.equals(billSorted, normalSorted) {
// Наши массивы равны, тест пройден
return true;
} else {
// Наши массивы не равны, тест провален
return false;
}
}
Обратите внимание, что вы не используете флаг SORT_ASCENDING в тестируемой функциональности (в частности, в методе billSort()), и, значит, он не является входным значением. Однако массив vals передается в метод billSort, и поэтому этот массив рассматривается как входное значение.
Но разве нельзя перестроить систему так, чтобы можно было отправлять флаг в качестве входного значения в метод billSort()?
// Аргументы = массив vals, флаг SORT_ASCENDING
billSorted = billSort(vals, true)
Это, конечно, возможно, и тогда можно рассматривать SORT_ASCENDING как входное значение, а не предусловие. Является ли что-то предусловием или входным значением — очень часто зависит от реализации программы. Если бы мы программировали на таком языке, например, как Haskell, где побочные эффекты для большинства функций крайне ограничены, то функции, подобные нашей, никогда бы не имели никаких предусловий кроме "программа запущена".
Сортировка является чисто математической идеей, но многое из того, что тестирует тестировщик, не настолько однозначно. В таких случаях зачастую сложно определить, что считается входными значениями, а что предусловиями. Эвристически, если кто-то выбирает или вводит значение во время выполнения теста, то это следует рассматривать как входное значение, в ином случае это предусловие. Например, если тест-кейс проверяет авторизацию пользователя с разными именамилогинами, тогда такое имя будет входным значением. Если тест проверяет способность добавлять предметы в корзину после того, как залогинился определенный пользователь, тогда имя пользователя будет предусловием, т. к. оно не вводится напрямую в тесте, а авторизация должна быть выполнена перед началом теста.