diff --git a/case-study.md b/case-study.md new file mode 100644 index 0000000..4d0eed8 --- /dev/null +++ b/case-study.md @@ -0,0 +1,79 @@ +# Оптимизация test-suite и сбор DX-метрик + +## Проблема + +У нас в проекте всеь сьют тестов прогоняется за 6,5 минут. Мы уже используем библиотеку test-prof, для оптимизации производительности, но начали использовать ее относительно недавно, так что есть простор для оптимизаций. Также у нас отключено логирование в тестовом окружении. + +## Подготовка + +### Step 1. Подключение influxdb + +1. Подключил гем 'influxer' +2. Поднял в докере `git@github.com:influxdata/TICK-docker.git` +3. Настроил influxdb.yml файл + +### Step 2. Настройка сбора метрики + +1. Создал рейк задачу, которая будет запускать тесты, замерять их время выполнения и отправлять данные в хронограф. +2. Создал класс в проекте, отнаследованный от Influxer::Metrics через который будет осуществляться управление метрикой. + +### Step 3. Первичная прогонка тестов + +Прогнал весь сьют. + +### Оптимизация + +### Step 1. FactoryDoctor + +Я раньше не использовал этот инструмент. Решил посмотреть на его отчет +Прогнал с этой настройкой на всем сьюте, и нашел в отчете самую жирную тест группу `(161 records created, 00:01.224)` +Это были тесты на возможности пользователя с определенной ролью (cancancan), посмотрев внутря я увидел конечно же `FactoryBot.create` внутри `let` +Но для тестирования abilite, совсем не нужно создавать запись в базе. Поэтому я заменил все `FactoryBot.create` на `FactoryBot.build`, а также модифицировал один трейт в одной из фабрик, и там также изменил create association на build association. +FactoryDoctor сказал что все теперь хорошо с этими тестами. Секономили чуть больше секунды времени, и перестали дергать базу без необходимости. + +### Step 2. Rspec --profile + +Позапускал тесты с семплированием и профилированием. Нашел медленный тест, выполняющийсей стабильно примерно за 0.7 сек. +Выяснилось, что это совсем устаревшее апи (которое пока еще не выпилили), для которого мы зачем-то до сих пор гоняем тесты. +Нужно будет обсудить с командой, что делать с этими тестами. Старое АПИ пока выпилить не можем (только через 2-3 месяца). С одной стороны уменьшать покрытие не хорошо, с другой стороны, зачем нам покрытие кода, которым сейчас практически никто не пользуется, и который уже точно не будет меняться. +В любом случае оптимизировать уже почти мертвые тесты наверное не стоит. + +### Step 3. parallel_tests + +Установил гем parallel_tests. Настроил на 3 потока прогона и получил wow-эффект. Уменьшение времени с 378 сек до 137 секунд. Офигительный эффект в скорости! +Жаль только что часть тестов попадало. При ближайшем рассмотрении оказалось, что это из-за конфликтов имен под разными неймспейсами :( +Пример: +``` + +module Module1 + module Module2 + class Class1 + def some_method + SomeClass.call(...) + end + end + end +end + +module Module1 + module Module2 + class SomeClass + end + end +end + +class SomeClass +end +``` + +В Class1 вызывается SomeClass, который очевидно что должен быть зарезолвлен изначально в том же самом неймспейсе Module1::Module2::SomeClass, однако при прогоне через parallel_tests класс резолвится от корня ::SomeClass. Причем от прогона к прогону с такой ошибкой могут свалиться разные тесты. + +При прогонке через RSpec такого небыло. + +Скриншот с хронографа [прилагаю](http://joxi.ru/brR9nKjIOyzG0A) + +### Результаты. + +Прочитал наконец полностью документацию к test-prof. Потрогал FactoryDocktor - вещь хорошая, буду смотреть его отчеты и лечить. +Узнал как делать семплирование и профилирование rspec. +Познакомился с parallel_tests, крутой эффект в производительности по времени, но к сожалению получили рандмно падающие тесты и ошибки с неймспейсингом. К сожалению, с таким поведением, врядли удастся затащить его на CI :(