Best practices по написанию автотестов. Как стоит делать

Всем привет.

Давно интересуют всевозможные best practices по написанию автотестов.
К примеру, что тесты должны быть атомарными и выполнение тестов не должно зависеть от предыдущих.
А какие еще Вы используете у себя на проектах ?

тестирование - представление информации о качестве продукта заинтересованным людям

у вас есть заказчик, как ему надо - так и делаете

а, то, что тесты должны быть атомарные, независимые друг от друга, быстрые, модные, молодёжные - само собой разумеется, вот только жизнь вносит свои коррективы

5 лайков

Вах, как красиво и правильно написано!
Добавлю — по книгам тесты очень много чего должны, но реалии и особенности проекта вносят свои коррективы. Бывают случаи, когда тесты зависят друг от друга по тем или иным причинам. Просто пишите тесты, как умеете, как знаете, как считаете правильным. Главное — чтобы они выявляли ошибки, действительно тестировали состояние и работу системы. В процессе будете править архитектуру. Увы, тут нет серебряной пули.

1 лайк

В моем случае, я стараюсь следовать практикам чистого кода. Например, SOLID принципы.

@Valentin_G по поводу SOLID, процентов 95 автоматизации UI - это Page Object в том или ином виде, который грубо нарушат два первых принципа…

Я не говорю, что я полностью следую им, я стараюсь следовать. PageObjects - один из тех случаев, когда такой возможности нету. А так, в этих классах я храню минимум информации - веб элементы и методы, которые задействуют несколько элементов. С остальными элементами я взаимодействую напрямую из степов.

тестирование - представление информации о качестве продукта заинтересованным людям

Именно так.

у вас есть заказчик, как ему надо - так и делаете

А вот это - неверно. Заказчику обычно малоинтересно, что Вы используете в своих тестах. Это - Ваша ответственность. Соответственно, оправдывать написание зависимых тестов или тестов, сляпанных на тяп-ляп в рекордере пожеланиями заказчика - неправильно. Заказчик может предъявлять требования разве что к кол-ву написанных за день тестов - но тут надо объяснять, что тест, слепленный из г-на и палок за 5 мин, вызовет постоянную боль с его поддержкой, на которую будет тратиться время, что в конце концов приведёт к проигрышу в перспективе.

Добрый вечер, ща бы от заказчика в виде задачи количество тестов в день получать :rofl::rofl::rofl:

в вопросе было написано про изолированные тесты, атомарные и вот это всё; но если заказчик хочет супер интеграционное тестирование, в котором если не выполнится первый тест, то вся пачка за ним не нужна - что в этом плохого?
я лично на первой айтишной работе написал цепочку тестов, которая шла в районе 40 минут (это было в 2017 году, и эти тесты до сих пор ходят и находят ошибки); на это был заказ с пониманием, что наверно это не круто, но оно ведь работает и помогает, и иначе никак

Что плохого? Та дохрена всего…

  1. Такие тесты невозможно запустить параллельно. Будем иметь тесты, бегающие 40 мин вместо нормальных 5…10.
  2. Если тест в цепочке упал - все последующие тоже упали. Соответственно, задача

представление информации о качестве продукта

по сути не выполнена. Из данного прогона можно точно сказать, что в системе (ну или в тесте, хехе :slight_smile: ) есть 1 баг. Но вот сколько их там ещё - сказать невозможно, поскольку результат остальных тестов нерелевантен.

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

а вот и нюансы подъехали: оказывается, тесты могут быть разными

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

и я ровно это имел в виду в первом сообщении: если нужна цепочка зависимых тестов, и падение любого из неё критично - то делайте цепочку тестов

если вы тестируете только свой функционал в составе кучи интеграций - пишите набор тех самых системных тестов, которые скажут, что ваша система работает плюс не ломает наружные интерфейсы

Зависимые тесты конечно зло, проблема в том что некоторые понимают атомарность совсем буквально как описано в юнит тестировании, но это совсем не подходит к ui тестам, в ui тестах единица измерения это сценарий бизнес логики. Вот, если вы сценарии в один объединяете, тогда уже проблема. И то бывают исключения, например когда, сгенерировать прекондиционные шаги не возможно и тогда делать атомарные сценарии нет смысла, так как будет дублирование, мы нарушим другой закон) + добавится время за которое все борются

В тестах нужно избегать ветвлений IF условий, если есть ветвления в логике тестов, значит тест написан неправильно

По-хорошему, атомарной должна быть проверка (или группа проверок, если относятся к 1 бизнес-сущности).
Например: сценарий:
ввести правиный логин, ввести правильный пароль, нажать кнопку, убедиться, что юзер смог залогиниться - это 1 тест. Отваливание любой его части гарантированно локализует ошибку и делает бессмысленным его дальнейшее прохождение.
А сценарий: залогиниться под юзером Вася с такими-то правами, пройтись по всем страницам и убедиться, что все элементы на всех страницах соответствуют его правам - должен быть разбит на группу атомарных тестов по 1 странице (ну или по группе, в случае, если переход на страницу 2 возможен только при заполнении чего-нить на странице 1), поскольку отвал теста на 3-й, к примеру, по счёту странице не даёт никакой информации о том, есть ли ошибка на 5-й.
А то потом возникают темы про “софт ассерты” :slight_smile:
Ну или такой сценарий: зайти под юзером Вася, выбрать предмет, добавить в корзину, нажать “купить”, оплатить и убедиться, что заказ перешёл в статус “оплачено” - прекрасный пример приёмочного теста, но как фукнциональный должен быть разбит на группу атомарных тестов с прекондишенами, поскольку отвал теста, например, на добавлении в корзину, не скажет, сломана ли оплата. Таким образом, критический баг с невозможностью оплатить товар может быть замаскирован мелким багом, к примеру, не добавилась “1” над корзиной после добавления туда товара.
Я бы сказал, эмпирическое правило такое: если возникает желание поставить в тесте софт ассерт для его большей информативности - тест необходимо разбить.

Они не только “могут быть”, они и “должны быть” разными. Тот же ISTQB чётко делит тесты на 4 группы: модульные, интеграционные, системные, приёмочные. Ну и пирамида тестов как бы намекает на то же самое. Как по мне, писать приёмочные тесты при отсутствии наличия системных (остальные 2 уровня по ISTQB на команде разработки) как бы не оч круто. Разве что ими занималась другая команда, о чем Вы нам не поведали тут.
Почему не оч круто - потому что чем выше уровень тестов по пирамиде, тем менее они быстры, менее надёжны и требуют больше времени на поддержку. Соответственно, перекидывать тест на уровень вверх необходимо только в том случае, когда его невозможно написать на данном уровне, иначе можно легко упереться в maintenance hell и 24 часа в сутках при nightly run :slight_smile:

конечно нужно разбить, если прекондишины можно нагенерить через апи или базу, в ином случае это будет один тест с мултипл асертом или несколько зависимых, какое из зол хуже выбирайте сами)

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

System testing is most often the final test to verify that the system to be delivered meets the specification and its purpose

Так вот в том-то и дело, что их должно быть меньше. Но это будет так в случае, если готов слой системных тестов. В этом случае приемочные тесты фокусируются на бизнес- сценариях, игнорируя уже покрытые системными тестами кейсы типа “ввести -1 в поле, которое принимает только позитивные значения”. Если же этого слоя нет - то системные тесты пи сути замещаются приемочными, что приводит к их неконтролируемому расползанию и, как следствие, описанным выше проблемам со скоростью и надёжностью. Для описанного мной кейса тест может выглядеть, к примеру, так: “бла-бла-бла, затем ввести -1, получить ошибку, закрыть ошибку, ввести правильное значение и продолжить выполнение по бизнес-сценарию”. Как поддерживать такие вот кейсы - можете себе представить сами :slight_smile:

апеллирование к istqb в изначально заданном контексте, что в книжках может быть одно, а в жизни совсем иначе, выглядит не очень.
на хабре статья недавно вышла Эффективное тестирование верстки / Хабр с очень интересной интерпретацией пирамиды тестирования

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

ну и чтоб внести ясность: пример, который я привел, был про feature-сценарии на, внезапно, 1с платформе. естественно, разработчики писали и юнит-тесты (тоже внезапно на 1с есть и юнит-тесты); а мне дали задачу взять условно ТЗ, в котором есть поток, начиная от базового пользователя заводить дальше пользователей, раздавать им права и далее тестить работу уже этих пользаков. И в начале фичи падали, потому что механизмы раздачи прав и валидации всего этого дела не работали, но с течением разработки сценарии проходили все дальше и дальше. При этом всегда есть возможность условно за час проверить, что в системе работает ролевая модель и механизм распределения прав с самого начала

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

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

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

Нет. И я вот этим самым “диким сценарием” показал, что будет, если так думать.
Приёмочные тесты - по большей части позитивны по своей природе, поскольку приложение задумывается для того, чтобы сделать что-то полезное. Таким образом, негативные сценарии в данных тестах зачастую игнорируются, поскольку не входят в бизнес-флоу. Значит, автоматизация данных сценариев ничем не поможет в контексте мануальной регрессии, основанной на системных тестах. Если же системных тестов нет - тестировщик, подменяющий приёмочными тестами системные, станет перед выбором: игнорировать негативные сценарии, полагаясь на обученность пользователей и игнорировать потенциальные баги, находящиеся в негативных сценариях, либо включать дополнительные проверки в приёмочные тесты. Чтобы не получить в 2 часа ночи звонок с воплями от начальства “всё пропало, ничего не работает” - обычно выбирают последний вариант и тесты становятся похожими на мой пример выше.
Данный пример, кстати, не какой-то edge case, доведённый до крайности - это обобщённый пример ошибочной композиции тестов, основанной на идее “сначала бизнес-сценарии, а потом - всё остальное”. Лично наблюдал такое неоднократно ещё в бытность мануальщиком.