Как стать автором
Обновить

Комментарии 11

Хорошая статья, больше похожая на отчёт) Если не секрет - почему используете виртуалки, а не какой-нибудь selenoid например?

Мы пробовали перейти на selenoid/zalenium еще в 2017 году. Я тогда услышал про них на одной из конференций и вдохновился идеей.

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

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

В нашей команде автоматизации сформировалась высокая культура программирования. Мы не используем thread.sleep в коде, только явные ожидания

Тут вы особо не выиграли. За wait-ерами все-равно спрятаны Thread.Sleep(к примеру https://github.com/SeleniumHQ/selenium/blob/trunk/dotnet/src/webdriver/Support/DefaultWait%7BT%7D.cs) А так у вас была возможность использовать await Task.Delay и освободить поток для других тестов, но тут придется очень сильно переделывать тесты. Если у вас тесты и тестируемый объект находятся на одной физической машине, возможно удастся еще чуть-чуть увеличить количество выполняемых тестов в единицу времени.

Но чем ниже был уровень параллелизации, тем меньше было ложных падений.

Я же правильно понимаю, что в системе с тестами только api и ui шаги. Если это так и с увеличением уровня параллелизации увеличивалось количество падений, то у вас проблема с атомарностью кейсов. Обычно в этом случае мы в командах начинали с выпиливания всех статических методов(за исключением чистых функций), после этого смотрели на бизнес сценарии и, либо выделяли соответствующие категории сценариев, либо делали тест атомарным. Скорее всего вам не надо было уменьшать количество потоков, а необходимо было править тесты.

Мы пошли дальше и сделали сортировку по строкам — названиям тестов. Тестам, которые длятся более 25 минут, мы присваиваем букву А вначале. Тестам от 20 до 25 минут — букву B, от 17 до 20 — букву С, от 14 до 17 — D и от 10 до 14 — букву E.

Не очень понял, чего вы хотели добиться? Есть тесты, которые:

  • могут исполняться параллельно;

  • должны запускаться последовательно относительно друг друга и могут запускаться параллельно относительно других тестов;

  • не могут исполняться одновременно с другими.

Зачем вводить категории по продолжительности? По бизнес value - логично, по продолжительности не очень вижу логику. Они же все равно все должны пройти.

Тут вы особо не выиграли. За wait-ерами все-равно спрятаны Thread.Sleep(к примеру https://github.com/SeleniumHQ/selenium/blob/trunk/dotnet/src/webdriver/Support/DefaultWait%7BT%7D.cs

Понятно, что магии нет и все равно где то приходим к использования Thread.Sleep, но речь про совсем грязный код вида thread.sleep(TimeSpan.FromSeconds(30)), вместо явного ожидания появления элемента.

Я же правильно понимаю, что в системе с тестами только api и ui шаги.

В наших тестах есть все виды взаимодействия: api, ui, запросы к базе через драйверы и т.д. Атомарность кейсов соблюдена настолько, насколько это возможно. Но, как я писал ранее, мы решили придерживаться парадигмы автоматизации пользовательских кейсов, а не проверки кнопок и менюшек в вакууме. Мы пишем приемочные тесты, а они, по своему определению, не могут состоять из одного шага и проверки. Да, какие то шаги пересекаются, но они максимально упрощены.
Еще раз отмечу, что при высоком уровне паралеллизации - большое число ложных срабатываний связано с максимальной загрузкой железа виртуалок из-за огромного количества запросов. Думаю, вам не нужно объяснять, что если cpu и диск под 100%, то о стабильности автотестов можно не мечтать.

Зачем вводить категории по продолжительности? По бизнес value - логично, по продолжительности не очень вижу логику. Они же все равно все должны пройти.

Идея была реорганизовать все кейсы таким образом, чтобы они запускались от наиболее долгого к наиболее быстрому. Когда речь про 1 поток, то разницы нет. А когда речь про многопоточность - появляются нюансы.
Представьте ситуацию, когда у вас 10 тестов и 5 потоков. Из этих 10 тестов есть 3 теста, которые выполняются 15 минут каждый, остальные 7 тестов выполняются по 2 минуты.
И в нашем случае получалось, что 2 из 3 долгих тестов попадали в один поток, что делало минимальное время прохождения запуска: 15+15 = 30 минут. Как бы быстро остальные тесты не бежали - все равно запуск будет ждать этот долгий поток с двумя тестами по 15 минут.
После наших преобразований у нас в каждый поток попадает только 1 долгий тест, и получается что минимальная продолжительность тестового запуска уже 15+2=17 минут.

Думаю, вам не нужно объяснять, что если cpu и диск под 100%, то о стабильности автотестов можно не мечтать.

Приложение, БД и тесты деплояться на один хост для запуска тестов? Просто есть подозрение, что cpu 100% при запуске в 30 потоков вам обеспечили тесты. На вряд ли приложение захлебнеться от 30 одновременно работающих пользователей. А вот если у вас синхронные тесты, то неосвобождение потока:

  • пока вы ждете элемент на странице(см. await Task.Delay(...));

  • пока вы ждете ответ от http сервера, сериализуете его;

  • пока исполняется скрипт в БД.

Будет приводить к тому, что cpu будет захлебываться при 30+ потоках. Ваши тесты в 99% случаях просто ждут и при этом не освобождают ресурсы.

Тестам, которые длятся более 25 минут, мы присваиваем букву А вначале. Тестам от 20 до 25 минут — букву B, от 17 до 20 — букву С, от 14 до 17 — D и от 10 до 14 — букву E.

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

В наших тестах есть все виды взаимодействия: api, ui, запросы к базе через драйверы и т.д.

Соответственно привести систему к любому состоянию - дело десятка секунд.

  • "тестирование патча в среднем на 8 часов". Я правильно понимаю, что придумали довольно хитрую систему с A, B ..., чтобы сэкономить максимум 25 минут из 8 часов? Но ведь для этого достаточно им приоритет поднять и все, плюс минус 15 минут относительно 8 часов, уже допустимая погрешность.

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

Как я уже писал в самой статье мы сознательно отказались от использования моков и костылей в автотестах, и решили тестировать только пользовательские сценарии. В наших приложениях есть пользовательские сценарии, которые занимают столько времени. Другими словами - событие "B" происходит через 20 минут после события "А". Мы не пробрасываем сообщение в шину, не используем бэкдоры, а проверяем саму систему. Сама система это делает. Поэтому вопрос о плохом тестдизайне не стоит.

Соответственно привести систему к любому состоянию - дело десятка секунд.

К сожалению, нет. Система очень сложная, с кучей микросервисов (речь уже о тысячах). Подсунуть побыстрому что-то в базу не получается по многим причинам, в том числе и потому, что система живая и поддерживать такие костыли очень сложно. Запросы к базе у нас, по большей части, это SELECT, для каких-то очень важных точечных проверок.

 Я правильно понимаю, что придумали довольно хитрую систему с A, B ..., чтобы сэкономить максимум 25 минут из 8 часов?

 В среднем у нас происходит 8 запусков автотестов на одну публикацию. До всех преобразований 1 запуск длился около 2-х часов. Мы обратили внимание на эту проблему, когда заметили, что последний тест завершается через 15-20 минут после всех остальных. Сейчас в каждом запуске у нас не остаются длинные автотесты в конце, а значит тестировщик раньше увидит результат.
Под поднятием приоритета, вы, наверное, имеете ввиду [Order()]. К сожалению, он действует только в рамках одного неймспейса. Организовать 2к+ тестов в одном неймспейсе чисто семантически не очень правильно.

 "B" происходит через 20 минут после события "А"

Интересный кейс, job scheduler так настроены? Или реально 20 минут процессинга? Видимо у меня просто личный опыт наложился, где я видел сценарии которые 20-25 минут кликают по экрану. Там были крайне сложные сценарии, где настраивались визарды, дублировались сложные логики, чтобы сделать тест атомарным, было очень большое количество проверяемых действий. Я даже не подумал, что у вас сценарий просто 20 минут ждет...

Организовать 2к+ тестов в одном неймспейсе чисто семантически не очень правильно.

Почему в один, вам главное значение order одинаковое проставить, количество namespace может быть разным.

Интересный кейс, job scheduler так настроены? Или реально 20 минут процессинга? Видимо у меня просто личный опыт наложился, где я видел сценарии которые 20-25 минут кликают по экрану. Там были крайне сложные сценарии, где настраивались визарды, дублировались сложные логики, чтобы сделать тест атомарным, было очень большое количество проверяемых действий. Я даже не подумал, что у вас сценарий просто 20 минут ждет

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

Понял, спасибо за разъяснения! Классная статья!

НЛО прилетело и опубликовало эту надпись здесь

Что вы называете автотестом? Такое ощущение, что говоря "автотест" вы подразумеваете "все 2000 автотестов".

Автотест - это автоматизированный тестовый сценарий. Абстрактный пример такого сценария

  1. Регистрируем пользователей А и B

  2. Заходим в приложением пользователем А

  3. Отправляем заявку от пользователя А к пользователю В

  4. Заходим в систему пользователем В и проверяем, что он получил заявку от А

Что значит "в среднем у нас происходит 8 запусков автотестов на одну публикацию"? Это 8 запусков одних и тех же тестов? Зачем?

Процесс тестирования у нас проходит несколько этапов. Условно, это может быть Stage1, Stage2, Stage3. На каждом из этих этапов мы запускаем наши автотесты. По различным причинам, отсутствие багов при тестировании на stage1 является необходимым, но не достаточным условием для отсутствия багов на stage2 и так далее. Каждое из окружение имеет свои особенности, поэтому для гарантирования качества мы не можем пропускать эти этапы.

Что такое "публикация"? Это релиз новой версии? Как часто происходят "публикации"?

Публикация это появление какого то изменения на продакшене. Новая функциональность, например. Мы не готовим релиз(большое количество новых фич) в течении нескольких месяцев. Мы делаем частые публикации(которые, необязательно маленькие). Количество публикаций - переменная величина, но в среднем их больше 10 в неделю

Зарегистрируйтесь на Хабре, чтобы оставить комментарий