Pull to refresh

Comments 16

А можно общую информацию, сколько у вас примерно обычных тестов, в штуках, сколько человек пишет код и тесты, сколько времени (месяцев, лет) вы используете мутационное тестирование?

Тесты пишут те же люди, что и код - тесты у нас идут как часть решения задачи. На моей основной работе разработка заказная, и поначалу мы пытались выбить время на покрытие тестами у бизнеса - это почти невозможно :)

Поэтому сейчас тесты пишутся как часть решения задачи. Тесты стараемся писать на каждый метод API. Обычные тесты пишем очень давно, но серьезный подход сформировался года 3 назад. И когда у команды есть опыт - тесты не только не замедляют разработку, а значительно ее ускоряют за счет минимизации багов и регрессии. А так тесты набросать занимает не более 10% времени от задачи, это окупается даже на мелких проектах.

Про мутационное тестирование давно слышал, игрался на локалке, но только недавно внедрили его на бой. И эта статья родилась как раз от того, что меня они вдохновили, что на самом деле в первом приближении их внедрение не такое уж и дорогое.

под сколько человек я имел ввиду количество коммитеров всего, за последний год например. Просто команды на 3 человека и на 30 совершенно по-разному управляются и требования разные. Я погладываю на мутационное тестирование уже лет 6 наверно, но так и не подвернулось места где хотелось бы включить его в пайплайн. Сейчас в моём проекте под 4 тысячи тестов и под десяток коммитеров, и я точно знаю что включив эту штуку найду тонну вещей которые не стоят и грамма внимания, и совершенно непонятно что с этим делать, установить метрику что процент выживающих мутантов должен, в среднем, падать? Мотивировать команду работать над этим? Точно ли я получу хоть какую-то пользу от того что количество выживающих мутантов упадёт с 90% до 85% например.

Я вам могу предложить выбрать самый важный модуль вашей системе и через --filter прогнать по нему мутационные тесты. Если после изучения отчета вы найдете интересные ошибки в тестах или в коде, тогда точно есть смысл.

ну у меня другая теха и так просто и быстро не получится прикрутить, но мысль понятна. В целом у меня и так уже есть понятие важного кода и он покрыт дополнительными тестами. Кстати, у меня есть ещё и performance тесты, это такие тесты которые замеряют количество аллокаций и скорость работы, и в случае деградации падают, вы такое не пробовали? У меня правда самопальный фреймвёрк.

По факту это тесты для тестов

Объясните джуну, пожалуйста, почему такая вещь не overkill? Наличие самих тестов понятно, они проверяют качество написанного кода, если разработчик где-то не доглядел.
Но тесты тестов? Т.е., получается, что мы написали тесты, которые тестируют тесты, которые тестируют код. Мне кажется, так можно делать до бесконечности

Не совсем, внедрение мутационных тестов не требует написания еще тестов. Мутационный фреймворк запускает ваши существующие тесты и ищет в них недостатки, проверяя ими измененный код приложения. Тем самым вы просто улучшаете свои тесты :)

Я конечно не автор топика, но понаписал всякого, включая проприетарный тестовый фреймвёрк и проекты на нём. Всегда можно сделать тест который просто ничего не делает. Как понять, что тест действительно проверяет функционал? Есть подход когда измеряется code coverage, т.е. проверяется какие строки кода были выполнены в ходе тестирования, но из за ошибки, или сознательных действий, тест может некорректно проверять результат или вообще не проверять. Получится что тесты есть, они все зелёные, code coverage 90% и всё казалось бы ок, а на самом деле ничего не проверяется. Мутационное тестирование позволяет убедиться, что тест есть, и что он именно проверяет результат, т.к. если код изменился, а тест всё ещё проходит, значит тест это (то, что изменилось) не проверяет (что кстати тоже не всегда так, могут быть мутации приводящие к эквивалентному коду). А оверкилл это или нет, зависит от ситуации, ответственности и маркетинговой стратегии. Вообще, есть очень простое правило, как определить сколько тестов нужно писать: столько чтобы команда чувствовала себя уверенно для внесения изменений и не боялась. У одних команд это очень много тестов, у других мало, у третьих ноль. В каждом проекте я руководствуюсь этим соображением и всё в порядке уже второй десяток лет.

какая-то очень странная концепция

если твои тесты не работают - это не тесты, нужно написать тесты

если они работают плохо - это плохие тесты, нужно написать хорошие тесты

Разработчики склонны писать “позитивные” тесты

ну да, так называемый "идеальный" сценарий, проверять core functionality. Всё равно все кейсы не покрыть, для пользовательского ввода есть валидация.

И тоже странно, что это начинает работать эффективно, когда условно тестами покрыто больше 70% кода - ничего себе, этом как бы единичные проекты могут похвастаться.

Такое ощущение, что эти "мутационные" тесты больше косвенно проверяют некую "устойчивость" проекта, что ли - один "мутант" - это какие-то однородные изменения в проекте.

Как вообще это должно работать? Какой реальный сценарий?

Вот есть условный проект и его кодовая база. Берём и условно покрываем проект на 80% тестами (что само по себе близко к нереальному сценарию). Но, так как у нас нету уверенности в тестах, как могло так получиться? Эти тесты сгенерированы автоматически или как так получается, что тесты написаны, но могут проверять "ничего"?

И когда мы имеем массив покрытия такими тестами, чтобы не ворошить руками тесты, выявляя нерабочие, мы натравливаем ещё "мутационные" тесты, которые делают в коде однородные изменения, чтобы выявить какие-то тесты, которые отвалились. Но такое ощущение, что на этом этапе могут отвалиться и рабочие тесты и наоборот - выжить нерабочие тесты. Получается, всё равно нужен какой-то контроль - или не нужен?

Как глобально работает сценарий? Мы пишем код проекта, генерируем тесты (чтобы не писать тесты), затем загоняем "мутационный" модуль, от которого часть тестов повалится. И мы их удаляем (?) и генерируем новые? Или пишем руками? Просто если руками - почему сразу не проверять работоспособность тестов?

В общем, немного странно выглядит и люто оверкилово. Такое ощущение, что это попытка исправить проблему плохих тестов и тестового покрытия не на этом же уровне, а сделав "финт ушами", что ли.

Возможно, это действительно как-то работает, но на первый взгляд выглядит супер-странно.

Я позволю себе сослаться на хороший комментарий от @Aquahawk выше.

Как я и писал в статье, мутационное тестирование - это тяжелая артиллерия, и далеко не всем она нужна.

Не совсем понял, почему вы пишете "генерируем тесты", тесты пишут живые люди пока что (по крайней мере я пока не видел штуку, которая бы по бизнес-требованиям могла создать тест для кода). В этом и есть проблема, что в них тоже могут быть ошибки, они могут не покрывать что-то, или проверять неправильно. Глазами такое почти нереально отловить.

Да, отчет по выжившим мутантам придется смотреть вручную, и думать, делать с ними что-то или не делать.

Ну и не соглашусь насчет нереалистичности покрытия в 70%+, для этого чаще всего достаточно писать по тесту на каждую ручку API, чтобы проверяла основной сценарий.

то есть живые люди пишут тесты и в них могут быть ошибки - ну окей, а после написания этих тестов эти люди разве их не проверяют? с покрытием то же самое - ну не покрывает тест заданное - ну так, в теории, человеку, который написал этот тест должно бы это быть очевидно

про "нереалистичность" написал всего лишь в контексте того, что, к сожалению, очень редко встречалось покрытие тестами хотя бы на треть, как правило, тестов или нету, или есть сугубо на "идеальные сценарии" критичного функционала, финрасчёты, вот такое. Да, возможно, я не там работал, с этим и спорить не буду, но пока не видел ни одного проекта, где хотя бы 50% покрытие было

про "тяжёлую артиллерию" - это понятно, просто сама концепция "мутантов" попалась впервые и попытался её осмыслить с позиции своего опыта и практики, скорее всего если грамотно использовать - возможно, это и профитно.

Соответственно мой комментарий был попыткой поразмыслить - какой нужен проект, условия, покрытие тестами, чтобы "мутационные" проверки имели коммерческий смысл.

Много раз сталкивался с тестами, если их было мало или они были недостаточны или плохи - как правило, давался фидбек их автору или ответственному человеку, который исправлял оговоренные моменты и в теории кажется, что так и должно происходить. Но вот, оказывается, можно и ещё что-то делать, пытаться выловить "мутантов" и без какого-то внятного примера это всё выглядит несколько странно. Что-то вроде "проверять вёрстку нагрузочным тестированием" или ещё что-то в этом роде, даже не могу метафору подобрать.

Вы не так поняли - мутационные тесты никто не пишет, это запуск тех же самых ваших тестов просто на измененном коде приложения.

Код приложения меняется мутационным фреймворком и на этом коде запускаются ваши тесты. Если тесты проходят, значит тесты не покрывают измененную строку (это может быть условие, вызов метода и тп, вот список мутаций). И так тысячи раз на разные изменения в разных местах.

По факту это единственный способ формально убедиться, что тесты действительно что-то проверяют, не просто работают.

ага, кажись, теперь понял

по сути, мутационка - это не похоже на "тесты" для тестов - это, скорее, похоже на диагностику, даже на один из способов найти плохие или слабые тесты.

а можно ещё по вот этому моменту ясности - почему при ручном создании тестов человек, написавший тесты, не проверяет их? Ну, должны же быть какие-то причины, по которым тесты "слабые", а тем более - нерабочие, в теории, нерабочий тест невозможно написать - потому что если тест "не работает", это вроде как видно и очевидно.

Или это такой себе способ подстраховать квалификацию тех, кто такие тесты пишет? Или тесты пишутся на "идеальные" сценарии? Типа есть проект, 70% функционала которого покрыто тестами на идеальные сценарии - тогда натравить мутационку и выделить заведомо слабые. Это как-то так работает?

Насчет того, почему разработчик не может проверить сам - по той же причине, почему не может написать код без багов :)

Особенно сложно хорошо написать тесты на свой же код, потому что ты заранее знаешь как он работает и думаешь только о тех моментах, которые запрограммировал и не думаешь о сценариях, которые забыл продумать.

В итоге картина получается такая: разработчик написал тесты, они работают, все зелененькое, все хорошо. Даже покрытие может быть очень высоким, код приложения в тесте вызывается. Но в тесте может быть допущена ошибка, или пропущен какой-нибудь assert, из-за чего в результате тест не проверяет какую-то важную деталь или сценарий.

Спасибо за статью.

Мне не хватило open-source примера на GitHub.

P.S. Рекомендую посмотреть в сторону Stryker-mutator и их дашбордов по мутационным тестам

Sign up to leave a comment.

Articles