Skip to content

Latest commit

 

History

History
79 lines (55 loc) · 5.77 KB

case-study.md

File metadata and controls

79 lines (55 loc) · 5.77 KB

Оптимизация test-suite и сбор DX-метрик

Проблема

У нас в проекте всеь сьют тестов прогоняется за 6,5 минут. Мы уже используем библиотеку test-prof, для оптимизации производительности, но начали использовать ее относительно недавно, так что есть простор для оптимизаций. Также у нас отключено логирование в тестовом окружении.

Подготовка

Step 1. Подключение influxdb

  1. Подключил гем 'influxer'
  2. Поднял в докере [email protected]: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 такого небыло.

Скриншот с хронографа прилагаю

Результаты.

Прочитал наконец полностью документацию к test-prof. Потрогал FactoryDocktor - вещь хорошая, буду смотреть его отчеты и лечить. Узнал как делать семплирование и профилирование rspec. Познакомился с parallel_tests, крутой эффект в производительности по времени, но к сожалению получили рандмно падающие тесты и ошибки с неймспейсингом. К сожалению, с таким поведением, врядли удастся затащить его на CI :(