PRO автотесты
Статистика- Последний пост
- 30 июл.
- Последнее чтение
- 12 авг.
- Постов за неделю
- 0
- Всего постов
- 20
- Тип
- открытый
- Язык
- русский
- В каталоге с
- 12 авг.
- 1/24сутки в ленте
- 211
- 1/48двое суток
- 241
- 1/72трое суток
- 260
Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.
Посты
видео или голосовое, без подписи
В субботу я читал лекцию об автотестах в Школе разработки интерфейсов Яндекса. В этом году я полностью переработал материал и собрал лекцию с нуля. Организаторы прислали инфографику с отзывами студентов — фидбек очень положительный! Рад, что лекция оказалась полезной. Запрос на рассказ о написании тестов с помощью ИИ — принят, добавлю эту тему в будущие лекции.
https://youtu.be/EZXj-bTG82w На прошлой неделе я был в гостях у Володи Гриненко и мы записали подкаст про автотесты и ИИ. Он уже опубликован и можно посмотреть.
Скоро начало 3 квартала и в Яндекс 360 идет квартальное планирование. Два сервиса запланировали в Q3 внедрение модульного тестирования и попросили описание типового рефакторинга для уменьшения связности компонентов приложения. Мы с ИИшкой запилили вот такой документ. Он не содержит специфики сервисов и, кажется, может быть полезен кому угодно. Если возникнут вопросы или фидбек — буду рад обсудить в комментариях.
видео или голосовое, без подписи
Еще один случай с участием #ии Мы сегодня обнаружили тест, который проходил успешно, но не проверял то, что указано в заголовке. Посмотрели историю VCS. Оказалось, изменения сделал ИИ, а разработчики не заметили их на код ревью из-за большого размера PR. Код на скриншоте должен проверять, что после применения фильтра в списке остаются записи, которые соответствуют его условиям. После обновления ui-kit изменилась структура вёрстки и перестал работать контрол выбора условий фильтра. Фильтрация в тесте перестала срабатывать и в списке начали отображаться все имеющиеся элементы. Тест стал падать. ИИ увидел, что тест падает и, вместо того, чтобы починить причину, исправил условие проверки. Мы использовали обычный процесс разработки и появилась ошибка, о которой мы не узнали. Мы, конечно, добавим в системный промпт ограничение для обработки подобных ситуаций и с помощью ИИ поищем другие тесты с некорректными проверками. Но, технически, могут возникнуть и другие ситуации, в другом контексте, в которых ИИ затупит и в проекте появятся скрытые ошибки. Это немного напрягает, пока не решили, что с этим делать.
видео или голосовое, без подписи
Только-что внезапно осознал крутой профит от полного покрытия автотестами — они дают возможность делать сложные рефакторинги при помощи ИИ. У нас в команде есть регулярные "архитектурные встречи" и только-что на одной из них мы попросили нейросеть выполнить рефакторинг. Нейросеть переписала большой кусок легаси. Мы запустили тесты, они показали несколько мелких ошибок. Мы их поправили и все тесты прошли! Часть проекта, которую изменила нейросеть, полностью покрыта автотестами. Если тесты прошли, то это значит, что для пользователя код работает полностью одинаково. Мы планируем провести код-ревью и влить эти изменения в основную ветку. Задача, на которую мы планировали 3 дня, сошлась за два часа! Я очень впечатлен! 🌟
Мне написали из программного комитета HolyJS и предложили повторить воркшоп по автотестам на конференции в мае. Осенью был хороший фидбек от участников, но сам воркшоп был без записи и количество мест было ограничено. Кажется, неплохая идея — повторить его еще раз. Уже добавили в программу: https://holyjs.ru/talks/85f07cd2a65844f391044d6a97e34c2a/
Привет! Наверно, вы заметили, что в этом канале два месяца не было новых постов. Дело в том, что в конце прошлого года у меня появилось хобби — разработка сюжетной 2D игры на движке Godot (на C#). Я никогда раньше не разрабатывал игры. Оказалось, это дивный новый мир с кучей нюансов и подводных камней. На это сейчас уходит много свободного времени, которое раньше тратил на написание постов в этом канале. Автотесты мне по-прежнему очень интересны. Есть несколько тем и заготовок постов для канала — рано или поздно я доберусь до них, допишу и опубликую. Также если у вас есть конкретные вопросы, то напишите их, обязательно отвечу. Я сделал еще один канал, чтобы писать туда апдейты статуса игры. Если интересно понаблюдать за разработкой, то заходите: https://t.me/+8LgS9kW40f83ZTcy
С Новым годом вас! 🎉 Пусть в следующем году вся работа приносит удовольствие! Пусть в работе будет больше автоматизации и меньше рутины! Пусть в команде будет взаимопонимание: идеи пусть встречают поддержку, а обратная связь — только конструктивная!
Сейчас был созвон, на котором обсудили вопросы, не поместившиеся в мастер-класс на HolyJS. Кто-то из учасников нажал запись и она сохранилась на его Яндекс Диск. Тот, кто это сделал, поделитесь, пожалуйста, записью. UPD: запись нашлась, доступна на Яндекс Диске
Вчера провёл мастер-класс по модульным тестам на HolyJS. На учебном проекте разобрали подходы к написанию тестов и рефакторингу, чтобы модульные тесты проверяли функциональные требования, а не только API внутренних компонентов. Два часа лайвкодинга пролетели незаметно. К сожалению, успел рассказать около 70% от запланированного, но зато обсудили много вопросов из зала. В конце голова кипела от большого количества информации, но кажется, многим участникам понравилось и было полезно. Весь код с мастер‑класса выложен на GitHub; в ключевых местах добавил комментарии. Если появятся вопросы, пишите мне — можно прямо в комментариях к этому посту. Хочу рассказать оставшуюся часть материала. Предлагаю созвониться в ближайший понедельник вечером: покажу несколько приёмов, как сделать код автотестов проще для восприятия. Приходите! Дата: понедельник, 24 ноября Время: 19:00 мск Ссылка: https://telemost.yandex.ru/j/4102903660
Уже в этот четверг я проведу мастер‑класс по модульному тестированию на HolyJS 2025 Autumn. Поговорим о том, что именно стоит тестировать в реальных проектах и зачем. Я покажу практические приёмы, которые вы сможете перенести в свой код. Формат мастер‑класса — лайв‑кодинг в духе парного программирования. Мы возьмём несколько сценариев, характерных для реальных проектов, напишем для них автотесты и проведём рефакторинг, чтобы сделать код более удобным для тестирования. Для демонстрации я подготовил приложение‑тренажёр с реалистичной предметной областью (интернет‑магазин). Код написан в упрощённом учебном стиле, чтобы сфокусироваться на сути: тестах и рефакторинге. Стек: TypeScript + React, есть SSR, используются популярные библиотеки React Router, React Query и Redux Toolkit. Проект будет полезен даже тем, кто не идёт на мастер‑класс. Попробуйте клонировать репозиторий, запустить приложение локально и покрыть автотестами функциональные требования, описанные в README. https://github.com/dima117/example-store#readme Если появятся вопросы — пишите в комментариях к этому посту или в личные сообщения. Буду рад обсудить ваши кейсы и идеи!
В продолжение темы о предупреждениях в тестах расскажу еще про сообщения вида: An update to <название_компонента> inside a test was not wrapped in act Это предупреждение возникает, когда после завершения теста React продолжает выполнять обновления компонентов. В интернете много информации на эту тему (например, здесь и здесь). Статьи по этим ссылкам, а также документация React, рекомендуют взаимодействовать с компонентами в тестах через какую-нибудь готовую библиотеку, которая обрабатывает эту особенность. Но дело в том, что при запуске тестов мы продолжали видеть предупреждения "... not wrapped in act", хотя на тот момент в проекте уже использовалась testing-library и обрабатывались краевые случаи, описанные в статьях. Предупреждений было очень много, несколько сотен 😱 Мы стали копать дальше и нашли обсуждение на GitHub. Оказалось, что логика обработки этой ситуации в @testing-library завязана на статический объект, создаваемый кодом библиотеки @testing-library/dom. Если в проекте содержится несколько разных версий этой библиотеки (например, установлены как транзитивные зависимости), то может оказаться, что разные вызовы API обращаются к разным экземплярам этого объекта и из-за этого они не понимают, что действие уже обернуто в act. В конфиге Jest мы настроили маппинг, чтобы при сборке все импорты из @testing-library/dom разрешались в одну версию библиотеки (в конкретную папку в node_modules на верхнем уровне). moduleNameMapper: { '^@testing-library/dom$': `<rootDir>/node_modules/@testing-library/dom` } Это помогло, предупреждения исчезли. Консольный вывод модульных тестов теперь короткий и понятный 😎
Channel photo updated
Во время прогона наших модульных тестов в консоли отображалось много предупреждений (сообщений, которые выводятся через console.error или console.warn). В основном это были предупреждения React, например об устаревших API, которые используются в компонентах. Из-за этих предупреждений консольный вывод превращался в простыню текста (как на картинке). Это усложняло работу с тестами, т.к. среди этих предупреждений трудно было заметить полезные сообщения об ошибках. Конечно же мы починили все предупреждения, которые возникали из-за кода, написанного в нашем проекте. Но часть ошибок возникало в коде сторонних библиотек, на которые мы не могли влиять. Получается, для решения проблемы нужно было либо внести изменения в код сторонних библиотек, либо отказаться от их использования. Но мы нашли еще одно решение. Пакет vitest-fail-on-console позволяет управлять выводом предупреждений в тестах. Для jest есть похожий пакет jest-fail-on-console. Мы настроили, чтобы заданные предупреждения сторонних библиотек не выводились на экран, а при возникновении любых других предупреждений тесты считались упавшими (чтобы разработчик не мог влить в основную ветку код, из-за которого возникают новые предупреждения в консоли). Теперь при запуске наших тестов в консоль не выводится ничего лишнего и сообщения об ошибках сразу видны.
Вчера на работе была встреча с QA, на которой обсуждали терминологию и подходы к автоматизации тестирования. Руководитель QA поделился интересной статьей Shift testing left with unit tests от Microsoft. Там описывается подход, с помощью которого команде огромного проекта удалось переработать свой набор тестов и сократить время от влития изменений в основную ветку до релиза с нескольких дней до 2 часов. Авторы статьи предлагают разделить тесты на слои на основе количества зависимостей и времени выполнения. Лёгкие и быстрые тесты нужно выполнять как можно раньше и чаще, например, на машине разработчика или при изменениях в pull request. Тяжелые медленные тесты можно выполнять позже и реже, например, после мержа изменений в основную ветку и при релизах. В статье выделены уровни автотестов: L1 — модульные тесты, которые зависят только от кода L2 — функциональные тесты, которые взаимодействуют с зависимостями вне кода (например, БД, файловая система) L3 — тесты, проверяющие задеплоенный сервис (при обращении к соседним сервисам использовать заглушки) L4 — тесты, максимально приближенные к контексту, в котором находится пользователь Ключевые принципы: - каждый тест должен быть написан на максимально простом уровне - при проектировании продукта нужно сразу учитывать возможность тестирования - код тестов настолько же важен, как и код продукта - инфраструктура для тестирования должна быть общей - за автотесты отвечают не только QA, но и разработка Этот подход близок к тому, что мы делаем в своих проектах внутри Яндекс. Круто, что статья коротко, но при этом понятно объясняет ключевые идеи. По ссылке вы можете прочитать полный текст статьи https://learn.microsoft.com/en-us/devops/develop/shift-left-make-testing-fast-reliable
В мире интеграционных тестов есть крутой паттерн Page Object. Суть его в том, что вы обращаетесь к тестируемому приложению не напрямую из кода тестов, а делаете слой абстракции — обертку, которая содержит логику работы с элементами вашего интерфейса. Вы сможете переиспользовать логику, помещенную в обертке, во всех местах, где она нужна, а код тестов станет проще и понятнее. Например, представьте, что у вас есть тест на Playwright, в котором написано: // кликаем по ссылке "Get started" await page.getByRole('link', { name: 'Get started' }).click(); Вы можете сделать PageObject class HomePage { // в конструкторе получаем page, // через который происходит // взаимодействие с браузером constructor(private page) {} // свойство для доступа к ссылке "Get started" get GetStarted() { return this.page.getByRole('link', { name: 'Get started' }); } } тогда код теста будет выглядеть примерно так: const homePage = new HomePage(page); await homePage.GetStarted.click(); Теперь во всех местах, где вам нужно кликнуть по ссылке "Get started", вам не нужно заново писать код, который обращается к ней. Вы можете просто создать Page Object и обратиться к его свойству. Очень удобно! А самое замечательное — этот подход применим и для модульных тестов. Отличие в том, что код интеграционных тестов выполняется вне браузера и отправляет команды через специальный API (Selenium или CDP), а код модульных тестов выполняется в одном контексте с кодом тестируемого интерфейса и может напрямую оперировать DOM элементами. class HomePage { constructor(private page: Element) {} get GetStarted() { // используем функцию getByRole из библиотеки @testing-library/dom return getByRole(this.page, 'link', { name: 'Get started' }); } } Я написал небольшую библиотеку jsdom-fragments. Она содержит API, с помощью которого можно легко описывать Page Objects для модульных тестов в jsdom. Похожий API мы используем в Яндексе уже 4 года и это очень удобно. Теперь вы тоже можете попробовать Page Objects в своих модульных тестах! https://www.npmjs.com/package/jsdom-fragments
сегодня на работе получил ачивку за 10 лет работы в Яндексе 😊