Pull to refresh
2
15
Anatoly Bobunov@wildbob

SDET / Senior AQA Engineer with 7+ YoE

Send message

Так это не unit тесты.
Это больше smoke и integration - так как все бизнес сущности крутятся на одном тест стенде. На данный момент нет тест окружений где поднята одна БД или какой либо микросевис от бекенда, и мы его полноценно тестируем.

Сам сервис который тестируем изначально тоже был по большей части монолитом.

Мы пока только начали двигаться в сторону распиливания монолоитов и изоляции каждого сервиса, что позволит тестирования микросервисов в отрыве от других сущностей. Вот тогда и можно будет применить моки и тп

Отчасти с вами согласен. Многие моменты можно было описать подробнее.

В случае наших тестов большую часть тест даты не получиться генерировать в сессионных фикстурах. Создание некоторых сущностей требует ожидания раскатывания изменений на несколько инстансов и запускает апдейт данных в других сервисах. Это может занимать до нескольких минут если считать полноценное обновление от отправки запроса до возможности работать с сущностью. Именно поэтому был создан Presetup который ночью производит преднастройку тест данных.

Почему тесты работали так медленно. Вот именно из тех причин что описаны: практически везде использовались sleep вместо ожиданий, все тесты гонялись в один поток, и фикстуры которые создавали тест данные которые требуют долгого ожидания (см. абзац выше). Это странно но исправление всего 3 этих пунктов серьезно улучшило скорость прогона авто тестов

Самое простое это запуск нужного вам кода в pytest hooks (там есть набор хуков который запускается до того как pytest передаст управление в отдельные сессии воркеров).

В этом хуке вам нужно будет проверить что вы находитесь в main воркере. Для этого у xdist есть набор переменных которые он устанавливает в окружение - https://pytest-xdist.readthedocs.io/en/stable/how-to.html

Дополнительный момент будет в том что созданное подключение вам нужно будет пробросить в ново-созданные сессии. Вот тут сходу не найду пример кода. Если не забуду завтра попробую накидать минимальный пример кода.

Плюс посмотреть/проверить как у вас обрабатываются множественные обращения к вашей базе.

Согласен с вами что наш подход не идеален.
То что вы описываете требует перестройки процессов в компании на всех уровнях( Начиная с самого верха и заканчивая рядовыми сотрудниками. А если добавить сюда десятки репозиториев и десятки команд....

На это никто не пойдет. Почему и другие подобные моменты - это тема достойна отдельной статьи))

Я могу обсуждать и рассказывать/пропагандировать "Как правильно". Но откровенно говоря это не входит в уровень моих обязанностей)

По поводу "как выбирать тесты". Вопрос очень сложный потому что у нас моно репозиторий в котором находятся авто тесты для десятков сервисов (это только бэкенд / АПИ).

Сложность в том что для запуска Сервис1 могут понадобиться подключение к Сервис2 и Сервис3, а потом еще и данные из других сервисов.
Или к примеру, создание какой либо сущности может потребовать ожидания в 5-10 секунд, потому то эти изменения расскатываются по всей системе и там задействованы много других сервисов. При этом мы хотели бы проверить что изменения расскатились корректно и проверить их на критичных нам сервисах - для этого нужно сделать к ним запросы.

Пока мы пришли к тому, что сделали связь Service: test_folder + src_folder. Какждый сервис это отдельная цепочка гитлаб джоб: healthcheck -> smoke -> tests ->. Если в папке с авто тестами или в папке с исходным кодом были изменения - то запускается вся цепочка. Таким образом мы покрыли 85-95% случаев.

Есть пробел что папки которые содержат какие либо base tools или более низкие уровни фреймворка не покрыты подобными правилами. Но в подобных случаях мы просто руками запускаем критичные наборы тестов.

Чтобы втащить асинхронный код в старый репозиторий придется много чего переписать. Команда и бизнес не готовы были на это тратить время.

Но... Недавно все пришли к решению, что в старом репозитории много плохого кода и туда стало трудно вносить большие изменения. Поэтому решили написать с нули новый репозиторий согласно слоеной архитектуры и мигрировать в него.

Репозиторий и код уже готов, сейчас начинаем в нем работать. Думаю что через месяц или два напиши статью о том что получилось. Но там будет больше про архитектуру.

Я смотрел библиотеки которые реализовывают retry, но после обсуждения с командой решили от них отказаться. Тот пример что в статье, это самый простой вариант которые удобно показывать в статье.

На самом деле у нас много кастомных retry функций которые основаны на какой либо логике сервиса. Да получается много костылей и самописного кода, но это удобнее чем пытаться делать override или как то обойти узкие места внешних библиотек.

Из плюсов, такой код как в примере - очень легко пишется

Добрый день.
1. sleep() - зло. Наверное у меня проф деформация, но я как только вижу в коде sleep() сразу задаю вопрос зачем и почему.
2. Почти сразу запускать тесты в параллель. В нашем случае через xdist. Это сразу будет приучать как удобнее и корректнее разделять тестовые данные, как правильно прописывать фикстуры для pytest и тп

Добрый день. Могли бы вы немного развернуть свою мысль из предыдущего сообщения.

У нас докер image создается только в том случае если были изменения в устанавливаемых библиотеках: обновление линуксовых библиотек или python. У джобы стоит блок changes который проверяет несколько файлов на изменения.

# Файлы, при изменении которых должна запускаться сборка docker образа
.changes_def:
 changes: &changes-def
   - Dockerfile
   - requirements.txt
   - .dockerignore
   - .gitlab/rebuild-docker-stage.yml

Если в триггерных файлах не было изменений, то джоба для создания докер image пропускается в пайплайне и используется образ master или dev.

Information

Rating
502-nd
Registered
Activity

Specialization

Инженер по автоматизации тестирования, Инженер по обеспечению качества
Старший
From 5,000 $
Python
Linux
Docker
CI/CD
Golang
gRPC
Английский язык