Работая с автотестами на разных проектах, я часто сталкивалась с тем, что к коду тестов люди относятся не так, как к продуктовому. Причем это касается и разработчиков, и тестировщиков, и менеджеров. Коду тестов прощаются грехи, недопустимые в продуктовом коде. Хорошо это или плохо? Зависит от ситуации. В этой статье – сборник больных антипаттернов из моего опыта.
-
Комментарии в тестах. Они в заголовке, с них и начнем. В какой момент эти ребята перестают помогать и начинают сильно мешать? В первую очередь, когда позволяют кому-то в команде лениться. Например, автору кода тестов. Или читателям кода тестов. Или тем, кто будет вносить изменения. Примеры из реальной жизни:
-
Тестировщики не знают язык программирования, поэтому автор тестов дополняет шаги теста комментариями. Как это выглядит:
На лицо ситуация, когда реальная проблема (тестировщики не умеют программировать, хотя это нужно проекту) скрывается за фейковым решением (BDD на минималках).
-
Правильное решение какой-то задачи откладывается на потом, алгоритм пишется в лоб. Как правило, код теста от этого становится непонятным и появляется жгучее желание объяснить, почему
не дописано нормальносделано так. Самодокументируемый код? Не, не слышали, это же просто тесты. На практике может выглядеть примерно так:
-
-
Сильно упрощенный код, отсутствие паттернов. Причины часто такие же – отсутствие навыков и/или спешка. Это ж тестировщики, печатать код умеют – уже молодцы. Да? Нет.
-
Удивительно, но не все применяют Page object в UI тестах, даже когда прям напрашивается. Вместо этого пишутся стандартные портянки кода с локаторами, ожиданиями и т.д.
Нарушается принцип Single responsibility. Вместо маленьких специализированных классов для работы с базой, драйвером и т.д. появляются монстры с общим названием
TestHelper
. Найти там что-то довольно затруднительно, поэтому часто в таких монстрах методы почти (или не почти) дублируют друг друга.Игнорируется принцип DRY – пишутся одинаковые действия в тестах или идентичные на 99% методы. Например, два метода
RaisePriceBy10Dollards()
иRaisePriceBy20Dollars()
вместо методаRaisePriceBy(int countOfDollars)
.
-
-
Невнимательное ревью тестов. Здесь примеры разные:
Тесты написаны разработчиком – другой разработчик и тестировщик просто смотрят, что тесты есть, не разбирая покрытие. Потому что автор кода ведь лучше всех покроет его тестами.
Тесты написаны тестировщиком – аналогично, другой тестер или разработчик, делающие ревью, проверят код, но не покрытие. Потому что мы этому тестировщику доверяем, он же знает тест-дизайн.
-
Для экономии времени часто проверяется правильность конструкций, а не логики. В итоге получаются тесты, которые не проверяют то, что заявляют. Или проверяют не так, как надо. Один из классических примеров – когда в UI тестах проверяется только сообщение об успехе на тестируемой странице, и упускаются проверки изменений на сервере.
Вместо заключения
Конечно, примеры пренебрежительного отношения к тестам этим не ограничиваются.
Чем в итоге плохо такое отношение? Ну тесты ведь и правда не продуктовый код, что плохого случится?
Со временем проблемы накапливаются как снежный ком (да простит меня бог литературы за такие выражения), и тесты превращаются в спутанный, пахнущий проблемами кусок кода, куда никто не хочет заглядывать. Тесты стали нестабильными? Непонятно реальное покрытие? Ой, долго разбираться, давайте просто протестируем это руками.
В итоге тесты из инструмента быстрой обратной связи превращаются в развлечение для тестировщиков (чтобы не уставали от ручного тестирования) и источник раздражения для разработчиков.
Автотесты – это прежде всего код, и их написание безусловно требует навыков программирования и внимательного отношения.
Комментарии (4)
egusinets
24.01.2025 07:55Эльвира, спасибо за статью! Вы подняли очень важные и актуальные проблемы, с которыми сталкиваются многие команды, работающие с автотестами. Действительно, отношение к тестовому коду как к чему-то второстепенному — это распространённая ошибка, которая приводит к серьёзным последствиям. Ваши примеры антипаттернов очень наглядны и, к сожалению, знакомы многим из нас.
Хочу добавить несколько мыслей:
Комментарии в тестах: Вы правы, что комментарии часто маскируют проблемы, вместо того чтобы их решать. Однако, если комментарии используются для объяснения сложной бизнес-логики или неочевидных решений, они могут быть полезны. Главное — не злоупотреблять ими и не заменять ими качественный код.
Самодокументируемый код: Это идеал, к которому стоит стремиться. Если тестовый код написан чисто и понятно, он не только упрощает поддержку, но и становится частью документации. Это особенно важно для новых членов команды.
Page Object и DRY: Полностью согласен, что пренебрежение этими принципами приводит к хрупким и трудно поддерживаемым тестам. Page Object — это must-have для UI-тестов, а DRY — это основа любого качественного кода, будь то продукт или тесты.
Ревью тестов: Очень важный момент. Ревью тестов должно быть таким же тщательным, как и ревью продуктового кода. Покрытие, логика, корректность проверок — всё это должно проверяться. Иначе тесты теряют свою ценность.
Последствия пренебрежения: Вы абсолютно правы, что проблемы с тестами накапливаются, как снежный ком. В итоге это приводит к тому, что тесты перестают быть инструментом, а становятся обузой. И тогда команда возвращается к ручному тестированию, что сводит на нет все преимущества автоматизации.
Спасибо за ваш опыт и примеры! Думаю, многим командам будет полезно задуматься над тем, как они пишут и поддерживают свои тесты.
А, что вы думаете по поводу внедрения code style и линтеров для тестового кода? Это могло бы помочь избежать некоторых проблем, которые вы описали.
Scarethebear Автор
24.01.2025 07:55Спасибо за поддерживающий комментарий!
Опыта с линтерами у меня нет, но я отношусь к ним как и к остальным инструментам - при умелом применении могут быть полезны, при бездумном могут и навредить) Как минимум, на первых этапах такие инструменты наверняка помогают команде быстрее адаптироваться и привыкнуть к новым правилам.
Code style, конечно же, поддерживаю. Это одно из обязательных условий для поддерживаемости тестов.
NeoNN
Вообще в тестах принято прописать стандартный комментарий AAA - arrange, act, assert, чтобы разделить секции с разными операциями. Ну и часто тесты действительно могут копипаститься и писаться гораздо менее продуманно, чем основной код, но у них чисто утилитарная цель, непонятны цели инвестиций в код, кроме тех, где они реально оправданы.
Scarethebear Автор
Где-то принято, а где-то нет. Я не против всех-всех-всех комментариев, хотите так разделять секции - да пожалуйста. Тут важно, почему вы это делаете. Если ради психологического комфорта, и всем в команде это ок, то и ладно. А если это делается, потому что без такого разделения не разберешься, чё где происходит - вопросики.
Касательно инвестиций. Хорошие тесты должны работать долго. Чтобы они работали долго, нужна постоянная поддержка. Чтобы поддержка не сопровождалась болью в эээ сердце, код тестов должен быть написан чисто и понятно. Есть некая грань между "менее продуманно" и "недопустимо безответственно", я за то, чтобы её не пересекать.