Зачем разработчикам писать автотесты? С таким же успехом их можно заставить класть плитку или вести бухгалтерию. Не барское это дело! Или, все-таки, барское?
Примечание: в статье под автотестами имеются ввиду не unit-тесты, а автоматизированные функциональные тесты, выполняющиеся на полностью развернутом продукте в окружении, максимально приближенном к боевому.
В разработке программного обеспечения существует много мифов и глупостей. Рассмотрим два из них.
Так уж сложилось, что тестировщики в индустрии в среднем зарабатывают меньше, чем разработчики. Происходит это, видимо, из-за того, что бытует мнение, что на роль тестировщиков можно нанять студентов за недорого, показать им куда надо «тыкать» — и все, команда тестировщиков готова. Это заблуждение, конечно. Хороший тестировщик является по сути исследователем программ, который понимает как они устроены внутри и должен стоить дорого, но это почему-то мало кто понимает.
Второе заблуждение – это отношение к автотестам. Считается, что разработка автотестов – это глупая нудная работа, которую можно поручить кому угодно.
Если объединить эти два заблуждения, то получится ситуация, когда автотесты отдаются на откуп команде тестирования, в результате у нас нет ни команды тестирования, так как она занята разработкой автотестов, ни автотестов, так как выяснится, что:
Первая причина вышеописанных проблем заключается в том, что удовлетворительно работающая система автоматизированных тестов зачастую сложнее самого тестируемого продукта и она сама по себе является программным продуктом. От разработчиков системы автоматизированных тестов требуется высокая квалификация в области написания кода, а таких людей в команде тестирования не много. В результате получаются тесты, которые очень дорого поддерживать и развивать.
Вторая причина вытекает из того, что команда тестирования не владеет продуктовым кодом. Кодом владеют разработчики и только они могут вносить в него исправления.
Из практики применения юнит-тестов известно, что их разработка наиболее эффективна тогда, когда занимается ей автор тестируемого кода. В этом случае код, как правило, получается более пригодным для тестирования и в результате тесты выходят проще и надежнее.
Точно такая же ситуация имеет место быть и при разработке функциональных автотестов. Когда продуктовый код пишут разработчики, а тесты для этого кода тестировщики, то трудоемкость и качество (поддерживаемость, скорость выполнения, хрупкость и пр.) таких тестов получается хуже, чем если бы и то и другое разрабатывала одна команда. Это происходит из-за того, что разработчик имеет возможность слегка подправить код так, чтобы ему самому было удобнее для этого кода написать автотест. Теоретически, инженер из команды тестирования тоже может попросить команду продуктовых разработчиков модифицировать код. Но на практике, это происходит не всегда, так как часто тестировщику проще оставить в тесте костыль (например, sleep), чем обращаться с просьбой к команде разработчиков, которые в данный момент заняты чем-то важным, ждать пока они реализуют то, что ему нужно, потом получить не то, что он просил и так по кругу. В результате, со временем тесты обрастают костылями, становятся неподдерживаемыми и превращаются в тот самый чемодан без ручки, который и выбросить жалко и тащить тяжело.
Таким образом, самые надежные и легко поддерживаемые тесты получаются, когда их делает команда продуктовых разработчиков. Но данный вариант также не лишен недостатков. Эти недостатки хорошо известны и благодаря им вообще существуют тестировщики. Все в конечном итоге сводится к тому, что тестировщики лучше умеют находить ошибки.
Поэтому оптимальным является некоторый промежуточный вариант, когда автотесты пишутся и разработчиками и тестировщиками. При таком комбинированном подходе удается объединить сильный стороны тех и других. Разработчики закладывают грамотную архитектуру автотестов, адаптируют продукт и обеспечивают покрытие тестами продуктового кода. Тестировщики, со своей стороны, обеспечивают покрытие тест-кейзов, используя в качестве базы автотесты разработчиков.
Разработка автотестов является у нас неотъемлемой частью общего процесса разработки продукта. При планировании итерации для каждой пользовательской истории мы обязательно закладываем время на подготовку автотестов для неё. Трудоемкость автотестов обычно составляет 10-20% от трудоемкости истории, но потраченное время потом многократно окупается.
При внедрении такого подхода к разработке автотестов могут быть проблемы с мотивацией разработчиков, но преодолеть эти проблемы не сложно. Надо сделать так, чтобы прогон автотестов (по крайней мере, части из них) стал внутренним делом команды программистов. Это означает, что тестировщики получают в тестирование только работоспособные сборки, на которых полностью прошли автотесты. При этом, на сломанный функционал, который был обнаружен автотестами, не заводятся баги, так как тестировщики про этот позор ничего не знают.
После этого происходит удивительное – программисты внезапно замечают, что автотесты экономят им кучу времени:
Примечание: в статье под автотестами имеются ввиду не unit-тесты, а автоматизированные функциональные тесты, выполняющиеся на полностью развернутом продукте в окружении, максимально приближенном к боевому.
В разработке программного обеспечения существует много мифов и глупостей. Рассмотрим два из них.
Так уж сложилось, что тестировщики в индустрии в среднем зарабатывают меньше, чем разработчики. Происходит это, видимо, из-за того, что бытует мнение, что на роль тестировщиков можно нанять студентов за недорого, показать им куда надо «тыкать» — и все, команда тестировщиков готова. Это заблуждение, конечно. Хороший тестировщик является по сути исследователем программ, который понимает как они устроены внутри и должен стоить дорого, но это почему-то мало кто понимает.
Второе заблуждение – это отношение к автотестам. Считается, что разработка автотестов – это глупая нудная работа, которую можно поручить кому угодно.
Если объединить эти два заблуждения, то получится ситуация, когда автотесты отдаются на откуп команде тестирования, в результате у нас нет ни команды тестирования, так как она занята разработкой автотестов, ни автотестов, так как выяснится, что:
- Автотесты окажутся крайне дороги в разработке.
- Большое количество ложных срабатываний. Редко когда полный прогон автотестов завершается удачно, в результате сломанным атотестам никто не верит.
- Трудоемкий процесс анализа результатов прогона автотестов из-за большого количества ложных срабатываний и трудностей с диагностикой.
- Очень высокая хрупкость. Тесты постоянно ломаются даже после незначительных изменений в продукте. Из-за этого их нужно постоянно поддерживать.
- В конце концов, автотесты забрасывают и стараются забыть этот позор.
Первая причина вышеописанных проблем заключается в том, что удовлетворительно работающая система автоматизированных тестов зачастую сложнее самого тестируемого продукта и она сама по себе является программным продуктом. От разработчиков системы автоматизированных тестов требуется высокая квалификация в области написания кода, а таких людей в команде тестирования не много. В результате получаются тесты, которые очень дорого поддерживать и развивать.
Вторая причина вытекает из того, что команда тестирования не владеет продуктовым кодом. Кодом владеют разработчики и только они могут вносить в него исправления.
Из практики применения юнит-тестов известно, что их разработка наиболее эффективна тогда, когда занимается ей автор тестируемого кода. В этом случае код, как правило, получается более пригодным для тестирования и в результате тесты выходят проще и надежнее.
Точно такая же ситуация имеет место быть и при разработке функциональных автотестов. Когда продуктовый код пишут разработчики, а тесты для этого кода тестировщики, то трудоемкость и качество (поддерживаемость, скорость выполнения, хрупкость и пр.) таких тестов получается хуже, чем если бы и то и другое разрабатывала одна команда. Это происходит из-за того, что разработчик имеет возможность слегка подправить код так, чтобы ему самому было удобнее для этого кода написать автотест. Теоретически, инженер из команды тестирования тоже может попросить команду продуктовых разработчиков модифицировать код. Но на практике, это происходит не всегда, так как часто тестировщику проще оставить в тесте костыль (например, sleep), чем обращаться с просьбой к команде разработчиков, которые в данный момент заняты чем-то важным, ждать пока они реализуют то, что ему нужно, потом получить не то, что он просил и так по кругу. В результате, со временем тесты обрастают костылями, становятся неподдерживаемыми и превращаются в тот самый чемодан без ручки, который и выбросить жалко и тащить тяжело.
Таким образом, самые надежные и легко поддерживаемые тесты получаются, когда их делает команда продуктовых разработчиков. Но данный вариант также не лишен недостатков. Эти недостатки хорошо известны и благодаря им вообще существуют тестировщики. Все в конечном итоге сводится к тому, что тестировщики лучше умеют находить ошибки.
Поэтому оптимальным является некоторый промежуточный вариант, когда автотесты пишутся и разработчиками и тестировщиками. При таком комбинированном подходе удается объединить сильный стороны тех и других. Разработчики закладывают грамотную архитектуру автотестов, адаптируют продукт и обеспечивают покрытие тестами продуктового кода. Тестировщики, со своей стороны, обеспечивают покрытие тест-кейзов, используя в качестве базы автотесты разработчиков.
Разработка автотестов является у нас неотъемлемой частью общего процесса разработки продукта. При планировании итерации для каждой пользовательской истории мы обязательно закладываем время на подготовку автотестов для неё. Трудоемкость автотестов обычно составляет 10-20% от трудоемкости истории, но потраченное время потом многократно окупается.
При внедрении такого подхода к разработке автотестов могут быть проблемы с мотивацией разработчиков, но преодолеть эти проблемы не сложно. Надо сделать так, чтобы прогон автотестов (по крайней мере, части из них) стал внутренним делом команды программистов. Это означает, что тестировщики получают в тестирование только работоспособные сборки, на которых полностью прошли автотесты. При этом, на сломанный функционал, который был обнаружен автотестами, не заводятся баги, так как тестировщики про этот позор ничего не знают.
После этого происходит удивительное – программисты внезапно замечают, что автотесты экономят им кучу времени:
- При внесении очередного изменения в код продукта разработчик не тратит свое время на проверку того, что он ничего не поломал. Разработчик просто делает PR, а проверку выполняет автоматика.
- Работающий код гораздо легче модифицировать, чем неработающий. Автотесты подтверждают работоспособность продукта перед тем, как программист приступает к очередной задаче, что дает ему твердую почву под ногами.
- Известно, что чем раньше ошибка обнаружена, чем легче её локализовать и исправить. Автотесты во многих случаях помогают сократить время обнаружения ошибки до минимума, благодаря чему ошибка исправляется по горячим следам.
- Автотесты позволяют эффективно проводить рефакторинг кода, так как у программиста появляется возможность автоматически проверить корректность проведенного рефакторинга. Благодаря этому рефакторинг перестает быть хождением по минному полю и становится рутинной рабочей процедурой.