Насколько вы уверены в своих тестах? Покрывают ли они все ветки выполнения ваших функций? Можем ли мы доверять Code Coverage? Ответы на эти вопросы дает мутационное тестирование. Для того чтобы пролить свет на самые темные его уголки, мы поговорили с PHP девелопером Itransition Максом Рафалко. Макс — разработчик фреймворка для мутационного тестирования в PHP, который называется Infection. А на конференции PHP Russia 2021 он будет выступать с докладом, который познакомит слушателей с методологией мутационного тестирования. Расскажи немного о себе. Чем сейчас занимаешься? Я работаю в аутсорс-компании в Минске уже более десяти лет, преимущественно занимаюсь PHP, но не только.  На работе я и мои коллеги пытаемся вывести качество разработки на более высокий уровень. Постоянно добавляем какие-нибудь новые тулы для анализа кода, всевозможные проверки, которые вырастают из устных договоренностей и конвенций. Статический анализ в широком его проявлении, функциональные и юнит тесты, или например тесты, которые проверяют, что все API эндпоинты покрыты тестами, общие JSON схемы между Backend и Frontend приложением, проверяющие ответы API и интерфейсы TypeScript и многое другое. При наличии CI заниматься этим — одно удовольствие, ты просто возвращаешь non-zero return code, и красный билд заставляет разработчика исправить замечания до вмешательства человека в процесс Code Review. В свободное от работы и воспитания двух дочек время занимаюсь опенсорсом и изучением новых технологий. Преимущественно это, конечно, Infection — библиотека для мутационного тестирования. Что такое мутационное тестирование? Сможешь сформулировать в одном приложении? Мутационное тестирование — это проверка качества тестов. Делается это так: в исходный код приложения автоматически пошагового вносятся изменения: туда внедряются дефекты и проверяется, как тесты реагируют на такие изменения. Как возник проект Infection? В 2017 году у нас в компании проходил митап, где один из докладчиков рассказывал про мутационное тестирование на примере языка Ruby. Мне очень понравилась идея, и я решил посмотреть, какие библиотеки существует в PHP. На тот момент из более-менее серьезных был только Humbug. Главным недостатком этой библиотеки было то, что «мутаторы» (это операторы, которые изменяют/мутируют исходный код) работали с кодом путем разбиения его на токены, а не построения абстрактного синтаксического дерева (AST). Это очень мешало мне добавлять новые операторы. Как раз в то время после долгой паузы проект Humbug ожил и искал новых мейнтейнеров.  Я предложил свою помощь, так как очень сильно горел идеей. Попасть туда не получилось, и я решил в качестве эксперимента сделать что-то похожее, легковесный аналог Humbug, только с мутаторами, построенными на AST. К большому удивлению, повторить функционал уже существующих мутаторов в Humbug, но работающих с абстрактными синтаксическими деревьями, получилось довольно быстро, также как и добавить новые мутаторы. Потом все это попало на GitHub, я написал пару постов, в том числе на Хабре и Medium, подключились другие ребята и пошло-поехало. Одним из ключевых моментов считаю активное распространение информации в твиттере: там PHP-сообщество особенно активно. Это дало серьезный толчок в популяризации проекта и в целом мутационного тестирования. О нем опять заговорили. Знаешь какие-нибудь большие проекты, которые постоянно пользуются Infection? Приведу несколько примеров из OSS: doctrine/collections ocramius/proxy-manager  roave/better-reflection  yiisoft/* пакеты Тут надо отдать должное Marco Pivetta. Он добавляет Infection во все репозитории, которые сам поддерживает или которым помогает. Это, опять-таки, очень повлияло на распространение идеи мутационного тестирования в PHP-комьюнити. Также, мы стали внедрять Infection на свои проекты на работе.  Хорошим примером можно считать внедрение мутационного тестирования в Badoo — они написали свой раннер, но взяли мутаторы из Infection. Ты улучшаешь и поддерживаешь свой проект уже довольно давно. Что тобой движет? Здесь собралось много факторов. Во-первых, это действительно крутая идея, придуманная десятки лет назад, которую я хотел бы донести до бОльшего количества людей. Во-вторых, мне интересна тема качества кода и качества тестов. В-третьих,  приятно иметь за плечами библиотеку, которой пользуются тысячи проектов,  которая имеет миллионы установок, и которая, де-факто, является единственной в PHP достойной реализацией. Это помощь в Code Review. Когда ты видишь, что билд зеленый, а там стоит --min-msi=98  (это значит, что 98% мутантов убиты тестами), ты точно знаешь, что код покрыт тестами качественно. И, наконец, это нескончаемая возможность совершенствоваться и учиться новому у других контрибьюторов. В нашей core-команде сейчас шесть человек, каждый из них — несомненно талантливый разработчик со своим опытом, взглядами, идеями. Большинство крутых вещей, которые появились в Infection — результат работы этой команды, результат обсуждений, экспериментов, сотен часов разработки. Многие из этих ребят контрибьютят или являются мейнтейнерами других популярных тулов (WebMozart/Assert, PHP-CS-Fixer, Symfony, Doctrine, Box, Api-Platform и др.). Считаешь ли ты создание Infection своего рода волонтерской деятельностью в мире php? Ведь, насколько я понимаю, это бесплатная библиотека. Абсолютно. И Infection, и многие другие библиотеки, которыми мы привыкли пользоваться ежедневно или чуть реже, все это делается на энтузиазме людей, готовых развивать экосистему PHP, готовых тратить свое личное время бесплатно на развитие библиотек, поддержку документации и т.д.  Но в то же время приятно видеть, что все больше проектов начинают спонсироваться, появляются всякие Sponsorware-стратегии, когда продукт становится публично доступным для всех только после того, как набирает достаточное количество «спонсоров».  Для меня в Open Source есть несколько моментов, которые до сих пор заставляют заниматься им. Первое — это развитие существующих решений, направленных на увеличение качества кода. Будь это Infection или любая другая библиотека или фреймворк — так или иначе они разрабатываются, чтобы сделать жизнь разработчиков легче, сконцентрироваться на решении проблемы качественно и предоставить профессиональный инструмент. Второе — это опыт, который ты получаешь, общаясь с другими людьми, просматривая их пул-реквесты, обсуждая новый функционал. Например, слежу за библиотеками для мутационного тестирования в других языках, как они развиваются, какие фичи добавляют. Все это постоянно расширяет горизонт твоих знаний. Откуда силы и ресурсы? Как у тебя хватает на все времени? Не очень хватает. Постоянно приходится чем-то жертвовать, тратя, например, вечер или выходной на Open Source. Но это работа на будущее. Есть разные способы улучшить ситуацию, и о них надо говорить. Например: Помощь компаний в предоставлении возможности сотрудникам участвовать в Open Source в рабочее время. Все компании любят использовать бесплатный софт, но не все готовы тратить свои деньги на развитие этого бесплатного софта. Надо менять это. Финансовая помощь OSS-контрибьюторам. Такие вещи как Patreon, OpenCollective, GitHub Sponsors — имеют огромное влияние на силы и ресурсы, которых постоянно не хватает. Поэтому если у вас есть желание и возможность, то участвуйте и спонсируйте тех людей, или те организации, которые помогают сделать вашу жизнь, как разработчика, лучше. Infection тоже можно поддержать :) О чем будет доклад, который ты представишь на конференции PHP Russia 2021? Мой доклад называется «Мутационное тестирование в PHP».  Автоматические тесты помогают нам быть уверенными, что код работает и будет работать, как ожидается. И одной из метрик автоматического тестирования является Code Coverage — процент покрытия кода. Но насколько хорош этот показатель? Можем ли мы ему доверять и имеет ли он хоть какой-то практический смысл? Насколько вы сами уверены в своих тестах? Покрывают ли они все ветки выполнения кода? Доклад отвечает на все эти вопросы и знакомит с методологией Мутационного Тестирования, описывает, как она может быть использована в повседневной работе и как контролировать качество тестов программно. В своем выступлении я рассмотрю проблемы показателя Code Coverage, каким образом они решаются с помощью Мутационного Тестирования. Кроме того, у слушателей будет возможность познакомиться с  Infection. Главная цель доклада — показать разработчикам идею Мутационного Тестирования. Заставить их прийти домой и запустить Infection на своем проекте. Показать, что МТ-тестирование может быть использовано на проектах любой величины и сложности, развеять миф о том, что оно неприменимо на средних и больших проектах из-за долгой работы. Дать еще одну возможность писать более качественный код, встроив Infection в CI. Ты часто выступаешь как спикер? Есть ли у тебя секреты успешного выступления?  Не очень. На серьезных конференциях выступал дважды, это были fwdays'2019, fwdays'2020 в Украине, и сейчас предстоит выступить на PHPRussia 2021. По поводу успешных выступлений — в сети есть целые лекции по тому, как правильно готовиться. Если в нескольких словах, секретом хорошего выступления является многократная репетиция доклада и доступные для понимания слайды, запись себя на камеру и просмотр со стороны. Но самое главное, что я рекомендую всем, у кого есть экспертиза — рассказывать. Начиная с митапов внутри компаний, городских митапов и так далее. Многие знаменитые спикеры именно так отфильтровывают свои доклады — если они успешно принимаются публикой на более мелких встречах, то идут с ними дальше, параллельно получая фидбек. На какие доклады ты бы сам пошел на конференции? Очень много заявлено интересных докладов, поэтому буду смотреть офлайн и потом онлайн записи :) Особенно меня интересуют доклады про отказоустойчивость приложений и распределенные Workflow. Чего ждешь от конференции в этом году? Общения офлайн, хороших докладов, встречи со знакомыми и новыми людьми! PHP Russia 2021 пройдет 28 июня в Москва, Radisson Slavyanskaya. Но уже сегодня можно ознакомиться с расписанием и присмотреть доклады, которые вы точно не захотите пропустить. А еще вы можете выбрать формат участия: онлайн или офлайн. Не забудьте купить билеты уже сегодня: с 1 июня цены станут выше.  PHP, Yii