Какие способы разбивать тесты по джобам в GitLab CI
Что проверяют
Умеете ли вы сократить время пайплайна, не превратив его в хаос, и понимаете ли, как GitLab раздаёт работу между джобами. Частый уточняющий вопрос: как вы делите тесты, чтобы шарды заканчивались примерно одновременно.
Как отвечать
- по типу тестов: отдельные джобы для unit, integration и e2e, выбор через маркеры pytest (
pytest -m "not slow") или каталоги. Быстрые идут первыми и дают обратную связь за минуты; parallel: N: GitLab создаёт N копий джобы и выдаёт каждойCI_NODE_INDEX(счёт с единицы) иCI_NODE_TOTAL. Сами тесты делит плагин, напримерpytest-split:pytest --splits $CI_NODE_TOTAL --group $CI_NODE_INDEX. Он балансирует по файлу.test_durations, который пишется флагом--store-durations;parallel:matrix: одна джоба с разными переменными, например две версии Python илиSUITEсо значениями unit и api;- внутри джобы:
pytest-xdistс-n autoраскладывает тесты по ядрам раннера, это дополняет шардинг, а не заменяет; rules:changes: джоба стартует, только если менялись нужные пути, аcompare_toзадаёт ветку для сравнения;needs: граф зависимостей вместо стадий, тесты стартуют сразу после своей сборки, не дожидаясь всей стадии;- дочерние пайплайны: скрипт генерирует YAML, а
trigger:include:artifactего запускает, когда набор джоб зависит от изменений.
Результаты шардов надо собрать: каждый публикует artifacts:reports:junit, и GitLab показывает их вместе в merge request. Покрытие каждый шард пишет в свой .coverage.*, а отдельная джоба делает coverage combine.
Где спотыкаются
Пишут parallel: 5 и считают, что тесты разделились. Без использования CI_NODE_INDEX все пять джоб гоняют один и тот же полный набор, пайплайн становится только дороже.
Путают tags джобы с маркерами pytest. tags выбирают раннер, на котором выполнится джоба, к отбору тестов они отношения не имеют.
Делят тесты поровну по количеству файлов. Один шард получает медленные интеграционные тесты и идёт десять минут, остальные заканчивают за одну, а общее время определяет самый долгий. Параллельные шарды к тому же нельзя пускать в одну тестовую базу без изоляции.