Продолжаю серию конспектов с HL2018. В проверке этого конспекта мне помогали ребята из Badoo (Владимир Янц vyants и Николай Крапивный), за что им большой спасибо. Надеюсь, это положительно сказалось на качестве донесения идеи доклада.
Особенности процесса разработки:
Ответственность разработчика не заканчивается релизом бэкенда. Он отвечает до реализации на платформах.
Есть ручное тестирование, но клиент не готов к моменту релиза и выпускается с (непредсказуемой) задержкой. Мы чаще всего не в курсе когда клиенты начнут это имплементировать. Иногда (не часто) фичи начинают делать через большой срок. Поэтому тестировать руками тяжело и не все можно. Поэтому нужны автотесты.
Тесты
Unit тесты
Пишутся на phpunit.
Тестируют малую единицу. Не ходят ни в базу, ни в сервисы (не должны ни с чем взаимодействовать).
Легаси до сих пор есть и усложняет процесс тестирование.
Разработали библиотеку softMocks — перехватывает все include / require и подменяет на изменённый.
Можно мотать любые методы: статические, приватные, финальные.
Библиотека доступна в опен сорс.
Проблема: softmocks расслабляют и дают писать не тестируемый код (и все аврно покрыть его тестами).
Приняли правила:
- Новый код должен быть легко тестируем phpunit
- SoftMocks — крайний случай (старый код /долго / дорого / сложно)
На эти правила смотрим на код ревью
Качество тестов
Мутационное тестирование
- Берём код
- Берём code coverage
- Парсим код и применяем мутации (меняем + => -; true => false и тп.)
- Для каждой мутации прогоняем сюит (набор) тестов.
- Если тесты упали, то ок. Если нет — они недостаточно эффективны. Разбираемся, меняем / дописываем тесты.
Есть готовые решения (Humbug, Infection), но они не подошли (не совместимы с softmocks, есть сложности с code coverage). Поэтому написали свое.
Мутационное тестирование пока недоступном для ручного теста. Доступно для запуска в ручную, из консоли. Сейчас внедряем в CI pipeline, выстраиваем процесс. Результат будет на хабре.
Интеграционные тесты
Тестируем работу нескольких компонентов в связке; проверяем работу с базой и/или сервисами.
Стандартный подход к тестированию БД (DBUnit):
- Поднимаем тестовую БД
- Заполняем ее
- Запускаем тест
- Очищаем БД
Проблемы:
- Нужно поддерживать datatables и dataset (актуальность содержимого БД)
- Требуется время на подготовку бд
- Параллельные запуски делают тесты нестабильными и порождают дедлоки
Решение: библиотека DBMocks (своё решение)
Принцип работы:
- Методы драйверов dB перехватываются с помощью SoftMocks на setUp теста
- Из запроса парсим db + table
- В tmpfs создаются временные таблицы с такой же схемой
- Все запросы ходят только во временные таблицы
- На TearDown они удаляются
Библиотека небольшая, но пока не запушена в опен сорс
Результаты:
- Тесты не могут повредить данные в оригинальных таблицах
- Тесты изолированы друг от друга (можно запускать параллельно)
- Тестируется совместимость запроса с версией MySQL
API тесты
- Имитируют клиентскую сессию
- Умеют слать запросы к бэкенду
- Бэкенд отвечает почти как реальному клиенту
Обычно такие тесты требуют авторизованного пользователя. Его нужно создать перед тестом и удалить после. Это вносит дополнительные риски (репликация, фоновые задачи).
Решение: Сделали пул тестовых пользователей. Научились их очищать.
Тестовые пользователя находятся в одном окружении с реальными, потому что devel != prod. Нужно изолировать тестовых и живых пользователей.
Для изоляции добавили флаг is_test_user у пользователя. И эти пользователи также исключаются из аналитики и результатов a/b тестов.
Можно сделать дешевле — отправить тестовых пользователей «в Антарктиду», где их никто не увидит (кроме пингвинов).
QA API
Инструмент для подготовки окружения в api тестах, по сути бекдор в бэкенде для быстрого изменения параметров пользователя / среды.
- Хорошо документированные апи методы
- Быстро и легко управляют данные
- Пишут backend разработчики
- Можно применять только к тестовым пользователям
Позволяют изменить пользователю неизменяемые данные (например, дату регистрации).
Требуется защита:
- На уровне сети (доступно только из офисной сети)
- С каждым запросом передаётся secret, валидность которого проверяется
- Методы работают только с тестовыми пользователями
Есть BugsBounty программа на HackerOne. Платят за найденные уязвимости. Один косяк с QA API нашли с ее помощью.
Remote mocks
Моки для удаленного бэкенда.
Работают на Базе soft mocks. Тест просит backend инициализировать для сессии mock. При получении запроса бэкенд проверяет список моков для сессии и применяет их при помощи SoftMocks.
Пример теста:
API тесты слишком удобны. Есть соблазн писать их вместо Unit. Но API тесты сильно медленее.
Приняли набор правил:
- Цель АПИ тестов — тестировать протокол и правильность интеграции
- Допустимо проверять сложные флоу
- Нельзя тестировать мелкую вариативность
- На code review проверяем тесты тоже.
Ui тесты
Не пишет бэкенд команда.
Фича покрывается Ui тестами когда стабилизируется.
Используется selenium для веб. Для мобильных calabash.
Прогон тестов
100 000 юнит тестов. 6 000 интеграционных, 14 000 апи тестов.
В 1 поток время 40 мин / 90 мин / 10 часов.
Сделали TestCloud — облако для запуска тестов.
Распределение теста между потоками:
- Можно поровну (плохо, все тесты разные, получается неравные по времени части)
- Запустить несколько потоков и последовательно скармливать тесты phpunit по одному (накладные расходы на инициализацию. Долго!)
Решение:
- Сбор статистики по времени прогона.
- Компоновка тестов так, чтобы чанк прогонялся не больше 30 секунд
Проблема с апи тестами — долго, много ресурсов и не дают выполнится другим.
Для решения разбили cloud на 2 части:
- Запускает только быстрые тесты
- Запускает оба типа тестов.
Результат — ускорение времени до:
- Unit — 1 мин
- Интеграционные — 5 мин
- API — 15 минут.
Прогон по code coverage
Какие тесты выполнять? Покажет code coverage.
- Получаем branch diff
- Формируем список изменённых файлов
- Получаем список тестов для этих файлов
- запускаем прогон сюита только из этих тестов.
Coverage формируется раз в сутки, ночью, для master-ветки. Результаты (diff) складываем в базу.
Плюсы:
- Меньше тестов прогоняем: меньше нагрузка на железо и обратная связь от тестов быстрее
- Можно запускать тесты для патчей. Это позволяет быстро выкатить хотфикс. В патчах скорость важнее всего.
Минусы:
- Релиз бэкенд 2 раза в день. После обеда coverage менее актуален (но при выкате била всегда гоняем полный сьют).
- Апи тесты генерируют обширный coverage. Для них этот подход не дает большой экономии.
Если разработчику нужно сразу посмотреть code-coverage, то есть тулза которую можно запустить в консоле и сразу получить свежую метрику по coverege конкретного файла/компонента.
Считается хитро: берется данные по coverege мастера, добавляются все измененную тесты, получается маленький сьют по которому уже и считается покрытие.
Итоги
- Нужны все уровни тестов
- Количество != качество. Делайте Code review и мутационное тестирование
- Изолируйте тестовых пользователей от реальных
- Бэкдоры в бэкенде упрощают и ускоряют написание тестов
- Собирайте статистику по тестам.
Ссылки
- Слайды: bit.ly/yants-HL18
- Наш протокол: «Как мы поддерживаем 100 разных версий клиентов в Badoo» / Ярослав Голуб
- SoftMocks: «SoftMocks: наша замена runkit для PHP 7» / Юрий Насретдинов, github.com/badoo/soft-mocks
- Badoo BugsBounty
- UI тесты: «Cross Platform Mobile Test Automation and Continuous Delivery» / Sathish Gogineni
- TestCloud: «Оптимальная параллелизация юнит- тестов или 17000 тестов за 4 минуты» / Илья Кудинов
- QAAPI: Взгляд на тестирование с другой стороны баррикад. / Доклад Дмитрия Марущенко на LoveQA
- Backend: Badoo. Все о бекенде мобильных приложений Badoo / Николай Крапивный
Автор: yushkevichv