97 Вещей, Которые Должен Знать Каждый Программист
81. Тестируйте Точно и Конкретно
Важно проверять желаемое, существенное поведение кода, а не случайное поведение конкретной реализации. Но, помимо этого, тесты должны быть точными и конкретными.
Наглядный пример – всем знакомые и по сто раз перепроверенные методы сортировки. Реализация алгоритма сортировки вряд ли является повседневной задачей для программиста, но сортировка - настолько простое понятие, что большинство людей думают, что знают, чего от неё ожидать. Но эта кажущаяся простота усложняет обнаружение неправильного предположения.
Когда программистов спрашивают: «Что бы вы тут протестировали?», - наиболее частым ответом является что-то вроде: «Что в результате сортировки получается отсортированная последовательность элементов». Хотя это правда, это не вся правда. Если спросить, что ещё, то многие программисты добавят, что результирующая последовательность должна быть той же длины, что и исходная. И это тоже правильно, но всё равно недостаточно. Например, если взять последовательность:
3 1 4 1 5 9То ответ ниже удовлетворяет обоим условиям (результат отсортирован и той же длины):
3 3 3 3 3 3Хотя это соответствует спецификации, это определенно не то, что имелось в виду! Более того, этот пример основан на ошибке, взятой из реального производственного кода (к счастью, обнаруженной до того, как он был выпущен). Простое неверное нажатие клавиши или кратковременная невнимательность привели к тому, что результат заполнился первым элементом.
Полное требование состоит в том, что результат отсортирован и содержит перестановку исходной последовательности. Вот теперь мы получили требуемое поведение. То, что длина результата такая же, как длина исходной последовательности, и так подразумевается, и это не требует повторного определения.
Но даже хорошей формулировки требования недостаточно, чтобы дать вам хороший тест. Хороший тест должен быть читабельным. Он должен быть достаточно понятным и простым, чтобы вы могли легко увидеть, что он верен (или нет). В нашем случае, если только у вас нет библиотеки, проверяющей, что последовательность отсортирована и одна последовательность содержит перестановку значений другой, то вполне вероятно, что код тестов будет более сложным, чем тестируемый код.
Как заметил Тони Хоар: «Есть два варианта проектирования ПО: сделать его настолько простым, чтобы в нём очевидно не было недостатков, либо сделать его настолько сложным, чтобы в нём не было очевидных недостатков.»
Использование конкретных примеров позволяет избавиться от случайной сложности и случайных ошибок. Например, для той же самой последовательности:
3 1 4 1 5 9Результат сортировки будет:
1 1 3 4 5 9Никакой другой ответ не годится!
Конкретные примеры помогают проиллюстрировать общее поведение доступным и однозначным образом. Результатом добавления элемента в пустую коллекцию является не просто то, что она не пуста: теперь в коллекции есть единственный элемент, и этот элемент является добавленным элементом. Два или более элементов будут удовлетворять условию непустой коллекции, но этот тест будет неверен. Один элемент с другим значением – тоже. Результатом добавления строки в таблицу заключается не просто то, что в таблице становится на одну строку больше. Нужно также проверить, что первичный ключ этой строки совпадает с первичным ключом строки, которую мы добавили. И так далее.
При определении поведения тесты должны быть не просто правильными: они также должны быть точными.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Kelvin Henney