Набор тестов идёт 1...
 
Уведомления
Очистить всё

Набор тестов идёт 14 минут. Замерил, куда уходит время

7 Сообщения
6 Пользователи
2 Реакции
352 Просмотры
TimurK62
Сообщения: 31
Автор темы
Читает чужие PR бэкенд-разработчик
Присоединился: 3 года назад
[#65]

Вечера в феврале длинные, дошли руки до того, что давно откладывал. Rails 8.0, Ruby 3.4, около 4100 примеров на RSpec, в CI набор идёт 14 минут 20 секунд, локально 11. Гадать надоело, повесил подписку на события factory_bot и посчитал, сколько раз и сколько по времени создаётся каждая фабрика:

# spec/support/factory_stats.rb
FACTORY_STATS = Hash.new { |h, k| h[k] = [0, 0.0] }

ActiveSupport::Notifications.subscribe("factory_bot.run_factory") do |event|
  key = "#{event.payload[:name]}:#{event.payload[:strategy]}"
  FACTORY_STATS[key][0] += 1
  FACTORY_STATS[key][1] += event.duration
end

at_exit do
  FACTORY_STATS.sort_by { |_, (_, ms)| -ms }.first(5).each do |key, (count, ms)|
    puts format("%-24s %7d %9.0f ms", key, count, ms)
  end
end

Результат: user:create вызывается 31 тысячу раз, хотя примеров 4100. Почти каждый create(:order) тащит за собой пользователя, компанию и ещё одного пользователя-менеджера через association. Время вложенных фабрик считается дважды, так что точный процент не назову, но по грубой оценке на фабрики уходит больше половины прогона. Дальше bundle exec rspec --profile 20 показал, что самые медленные группы те, где let! создаёт по десять заказов на каждый пример, а нужны они в двух примерах из пятнадцати.


6 ответов
Ксения 90
Сообщения: 18
Пишет тесты QA-автоматизатор
Присоединился: 4 года назад

let! на десять заказов это классика жанра. Посмотрите ещё, где можно build_stubbed вместо create: в тестах на методы модели, которые не ходят в базу, разницы никакой, а запись в базу не пишется вообще. В спеках сериализаторов и презентеров обычно половину можно перевести без потерь.


Ответ
artem_67
Сообщения: 18
Пишет тесты разработчик на Go
Присоединился: 4 года назад

14 минут на 4 тысячи тестов. на Go набор такого размера проходит секунд за сорок, просто к слову


Ответ
1 ответ
kostya.sokurov
Присоединился: 4 года назад

Держит прод бэкенд-разработчик, senior
Сообщения: 73

Автор: artem_67
на Go набор такого размера проходит секунд за сорок
Так там и тесты обычно без базы. Уберите базу из тестов моделей в Rails, тоже будут секунды. Вопрос в том, что именно проверяем: здесь половина тестов честно ходит в PostgreSQL, и в этом их смысл.


Ответ
Игорь 90
Сообщения: 4
Пишет в irb DevOps-инженер
Присоединился: 2 года назад

Со стороны CI: набор можно разбить на 4 параллельных джоба по времени выполнения файлов, а не по их количеству. Если сохранять время каждого файла из прошлого прогона, части выходят ровными, и 14 минут превращаются в 4-5 плюс время на подготовку окружения.


Ответ
TimurK62
Сообщения: 31
Автор темы
Читает чужие PR бэкенд-разработчик
Присоединился: 3 года назад

Отчитываюсь, две недели по вечерам. У заказа убрал association :manager, менеджер теперь создаётся только там, где он нужен. В 40 спеках сериализаторов create заменил на build_stubbed. В трёх самых медленных группах let! поменял на let и создаю данные внутри тех примеров, которым они нужны. user:create упал с 31 тысячи вызовов до 9400. Локально набор теперь 5 минут 10 секунд, в CI на одном джобе 6:40. Параллель ещё не включали, это следующий шаг. По флеймграфу около 40 секунд уходит просто на загрузку приложения перед первым тестом, но это уже отдельная история.


Ответ
pavel_1988
Сообщения: 8
Разобрался с блоками разработчик
Присоединился: 3 года назад

сохранил себе скрипт с подпиской, интересно, что он покажет на моём наборе


Ответ