F.I.R.S.T.
Пять характеристик чистых тестов.
Многим разработчикам известны принципы проектирования, которые благодаря Роберту Мартину получили звучное название S.O.L.I.D. Многим из этих принципов уже не один десяток лет (принцип подстановки Лисков впервые был озвучен более двадцати лет назад), они были опробованы на миллионах строк кода, тысячами разработчиками (при этом добрая половина из них применяла эти принципы даже не имея понятия об этом). Конечно, слепое следование любым принципам никогда ни к чему хорошему не приводило и приводить не будет, но тем не менее в них описаны разумные вещи, о которых нужно как минимум знать, да и понимать их тоже будет совсем не лишним.
Помимо принципов проектирования существуют и другие, незаслуженно менее известные принципы, которые положены в основу написания качественных тестов. На каждом шагу говорится о качестве кода, продуманности дизайна или архитектуры, но при этом довольно слабо уделяется внимание читабельности и сопровождаемости тестов. А ведь объем кода в тестах по хорошему может быть (а точнее должен быть) не меньшим, чем объем кода; возможно именно из-за некачественного кода модульных тестов они так редко поддерживаются в актуальном состоянии, что очень быстро приводит к тому, что они устаревают, становятся неактуальными и вообще остаются на “обочине” процесса разработки.
Принципы написания качественных тестов придуманы не на пустом месте. Большинство опытных разработчиках знают о них точно так же, как и о принципах проектирования без помощи “Дядюшки” Боба, но как и в случае с принципами проектирования именно Боб Мартин объединил пять принципов тестирования, в результате чего получилось звучное название F.I.R.S.T.: Fast (Быстрота), Independent (Независимость), Repeatable (Повторяемость), Self-Validating (Очевидность) (*), Timely (Своевременность)).
Итак, каждый модульный тест должен обладать следующими характеристиками:
Быстрота (Fast). Тесты должны выполняться быстро. Все мы знаем, что разработчики люди, а люди ленивы, поскольку эти выражения являются “транзитивными”, то можно сделать вывод, что люди тоже ленивы. А ленивый человек не захочет запускать тесты при каждом изменении кода, если они будут долго выполняться.
Независимость (Independent). Результаты выполнения одного теста не должны быть входными данными для другого. Все тесты должны выполняться в произвольном порядке, поскольку в противном случае при сбое одного теста каскадно “накроется” выполнение целой группы тестов.
Повторяемость (Repeatable). Тесты должны давать одинаковые результаты не зависимо от среды выполнения. Результаты не должны зависеть от того, выполняются ли они на вашем локальном компьютере, на компьютере соседа или же на билд-сервере. В противном случае найти концы с концами будет весьма не просто.
Очевидность (Self-Validating). Результатом выполнения теста должно быть булево значение. Тест либо прошел, либо не прошел и это должно быть легко понятно любому разработчику. Не нужно заставлять людей читать логи только для того, чтобы определить прошел тест успешно или нет.
Своевременность (Timely). Тесты должны создаваться своевременно. Несвоевременность написания тестов является главной причиной того, что они откладываются на потом, а это “потом” так никогда и не наступает. Даже если вы и не будете писать тесты перед кодом (хотя этот вариант уже доказал свою жизнеспособность) их нужно писать как минимум параллельно с кодом.