Золотой Selenide. Мои лучшие практики по тестированию

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Golden selenide. My best testing practices

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

Тестирование для меня как целая наука, имеющая множество направлений.

Что такое тест?

Тест - это проверка сценария, expected === actual result.

Какие тесты бывают?

  • Unit (юнит) тесты (их пишут разработчики)

  • UI тесты (их пишу я, и мы остановимся на этом)

Кратко про пирамиду тестирования

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

Как я разделяю типы UI тестов

  • Пользовательские сценарии (шаги в системе, приводящие к определенному результату)

  • Сочетания настроек (уместно применить - техники тест дизайна)

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

DOM - document object model. Древовидная иерархия тегов, расположения веб элементов на странице

Распределение локаторов

Локатор - адрес/путь веб элемента на странице

  • храните в отдельном файле, так и назовите, Локаторы

  • для каждой страницы отдельный файл с локаторами - забудьте про это. Вам запарится разделять локаторы по страницам, веб элементы состоят из идентичных форм, css классов, и один локатор часто будет повторяться на разных страницах приложения. Думаете что файл взорвется? Нет, благо в современном мире есть мощные IDE, упрощающих поиск. Около 500 локаторов достаточно покрывают многие потребности по нашему проекту

Интуитивно понятные локаторы

Для объявления локаторов лучше всего подходят идентификаторы. Либо писать интуитивно понятные локаторы. Прощупайте разницу если написать:

.top-header  # Какой то класс
div.top-header  # Блок, но таких блоков может быть много
input.top-header  # Ага, поле ввода
div.top-header.logo  # Ага, сразу понятно, логотип на вверхем хэдере

Длинный локатор не проблема когда они вынесены в отдельный файл с локаторами:

// WebElementLocators.java

public class ElementLocators {
  
  public static final String HEADER = "div.top-header-block";
  public static final String RED_COLOR = "rgba(248, 248, 248, 1)";
  ...
}

Мне-тебе не по душе. Какой ЯП выбрать для авто тестов?

Есть три популярнейших ЯП упрощающих жизнь автоматизаторам своими фреймворками и широким комьюнити,

  • Python (Selenium, Unittest/Pytest),

  • Java (Selenide, testNG/JUnit),

  • C# (тут я не знаю что нужно для .NET-щиков)

Да, еще можно писать на чистом JS. Хотя считаю это прошлым веком, но понимать его особо необходимо. На конференции QA от Kolesa Group узнала, что там используют PHP :D

Итог: выбирайте язык на котором пишут разработчики. Будет у кого спросить в тупиковой ситуации. (Возможно, язык на котором вы сейчас пишете, содержит скелеты в шкафу)

Паттерны? не, не слыхал

Но возникает еще одна проблема, нагромождение текста, кода, обернутых шагов (лишних действий специфичных для системы), локаторов в самих тест кейсах. Решение: POM, POM, POM... Page Object Model - standard test automation pattern. Паттерн это набор практик, проверенных временем, и прошедших множество костылей. Нельзя просто так взять и понять POM. Напишите свою первую, вторую, третью сотку тестов (я внедрила после четырехсотки), и вы поймете что в них что-то не так, придя к моменту изучите POM.

P.S. сначала нужно наступить на грабли, перед тем как поДнять их

Из чего состоит проверка сценария?

Каждый тестируемый случай в моих авто тестах состоит из:

TEST ID (идентификатор теста)
Name (название)
Description (описание)
Steps to reproduce (шаги воспроизведения)
Expected result (ожидаемый результат)
Actual result (фактический результат)

Подробнее разберем состав тест кейса:

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

  • Фактический результат - что случилось, на каком моменте сломалось, что произошло

  • Шаги воспроизведения - самая нужная часть тест кейса, приводящая к конечному тестируемому случаю. Мастерство тестировщика в ясности и четкости (краткости) этих шагов. Не пренебрегайте этим пунктом. Без этого тест кейс не тест кейс.

  • Описание - слово само за себя, сюда можно уместить сжатую композицию шагов воспроизведения

  • Название - название функции автотеста, упрощает поиск. Рекомендую использовать или заканчивать название глаголом. SomethingShouldExist. SomethingOfTestingCase.

  • TEST ID - использую для подсчета кол-ва написанных тестов

Лайфхак. Когда падает тест, я просто копирую тест-кейс и вставляю в тикет. Хорошо когда у разработчиков развернут репо с тестами, где они сами могут запустить тест. Рядом пахнет TDD - (selenide) test driven development. В этом случае вы пишете тест до момента UI ошибки, и передаете разработчикам. Думаю это удобно. После фикса дописываете автотест и закрываете кейс.

TDD - это когда тесты написаны до реализации чего либо (функции, модуля, класса, объекта). Таким образом помогает собрать мысли и сконцентрироваться на задачи, понимая, что должен делать и какой результат должен давать код.

Что такое веб элемент?

Это все блоки, точки, кнопки, div-ки из которых состоит веб страница. Откройте devtools (F12 для Chrome браузера) Все что имеет визуально-функциональный блок. Все это WEB ELEMENT-ы. Других названий не поощряю.

Явные (explicit waits) VS Неявные (implicit waits) ожидания

  • Явные ожидания - ждем хардкодно, программа спит и ничего не делает. Это тот самый sleep(1_000); // msec

  • Неявные ожидания - ждет в течение заданного промежутка, каждый раз пингуя элемент. Сразу пойдет дальше при положительном условии. Так мы экономим время прогона тестов. Каждый should содержит в себе неявное ожидание

$(HEADER).shouldBe(exist, enabled, visible); 
/*
Состояния:
enabled - активный, в основном применяю для проверки кликабельных элементов
visible - элемент виден на странице
exist - элемент сущетсвует в DOM-е
*/

Complex Conditions

Selenide очень удобен написанием однострочников, которые на голом селениуме загромождают тестовый код. Под капотом используется обычный while loop. Selenide ждет 4 секунды, каждый раз пингуя элемент. Конфиг таймаута можно установить через Configuration.timeout=10_000;. Это то самое неявное ожидание.

$(HEADER).shouldBe(exist, enabled, visible)
  .shouldHave(attribute("title", "myTitle"), text("TEXT"));

Разница между should, shouldBe, shouldHave - абсолютно никакой. Используйте для визуально приятного восприятия (читабельности)

Палитра на любой вкус. Проверка по цвету - check webElements color

Селенид краток, лаконичен и удобен, проверка наличия атрибута или сss класса? - не беда

$$(DANGER_BTN).shouldHave(size(1)).first()
  .shouldBe(visible)
  .shouldHave(cssValue("background-color", RED_COLOR), cssClass("danger-btn"));

Борьба с флоки тестами

Must have решения для минимизации flaky тестов. Данные решения помогут минимизировать их количество, но никак не избавиться от них полностью

  1. Перезапустить тест. Самый оптимальный вариант при крайних сроках и жестких дедлайнах.

  2. Стереть и переписать тест. Вероятность написать шаги воспроизведения теста немного иным способом высока. Следовательно тест может стать стабильнее. Также подумайте о лишних шагах.

  3. Test retrier - повторитель тестов. Must have штука. Обязательно научитесь. RetryAnalyzer-у (ссылочка). Очень полезная штука, проигрывается N раз, пока тест не загорит зеленым или останется красным. Минусы: действительно упавший тест будет перезагружаться N раз (суммарно займет N * times времени)

  4. UI Trigger - некий UI WebElement, настоящий delay триггер (триггер задержки) на странице, явно дающий понять что событие произошло. Наверняка большинство тестов имеют особенность падать при клике на определенный элемент. Проблема в том что не всегда ясно, завершило ли событие свое действие или имеет не тот атрибут. Например, загрузка файлов, с помощью всемогущего Селенида скачали файл, но как понять что файл был полностью передан с сервера? Поставить sleep на 10 секунд - не вариант. Нужно явно настоять программистам установить спинер или индикатор загрузки на web странице.

  5. JS Injection - об этом напишу словечко. На практике не использовала. Можно внедрить веб элементу css класс или изменить значение атрибута. Для особо отчаянных случаев.

Флоки тесты - нестабильные тесты. Временами падают, давая ложно-положительный результат. Влияют много факторов, javaScript (не до конца отрисован, всплывающие окна, возникновение скроллинга, перекрытие другим слоем или веб элементом), фреймворк, скорость работы железа, сбой в системе, маленький/fullscreen экран, сеть.

Отключить выполнение скриптов

Иногда очень полезно отключить выполнение js кода в скрипте (слишком быстрая анимация или исчезновение элемента). Сделать это можно прямо с devtools.

F12
Ctrl+Shift+P (Cmd+Shift+P)
disable JavaScript

Базовый помощник. Hot keys for IDE

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

# Переход между вкладками
ALT + (->, <-)

# Чтобы открыть любой файл
CTRL + SHIFT + N

# Find in files
CTRL + SHIFT + F

# Format current page
CTRL + ALT + O
CTRL + ALT + L

Генераторы локаторов. Useful webElement Locator generators

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

  public static String insertIntoTitleStartsWith(String textInTitle) {
    return String.format("*[title^='%s']", textInTitle);  // ^ нужно для поиска элементов, которые содержат атрибут начинающийся с переданного текста
  }

  public static String insertIntoTitle(String textInTitle) {
    return String.format("*[title='%s']", textInTitle);
  }

  public static String insertIntoAttribute(String attribute, String value) {
    return String.format("*[%s='%s']", attribute, value);
  }

Еще немного плюшек

Текст с пробелами, фильтрация коллекции и псевдоклассы

/* Java Core. Разница в проверке пробела: */
StringUtils.isBlank(" ") = true
StringUtils.isEmpty(" ") = false
  
/* Коллекция элементов, не входящих в заданный класс */
ElementsCollection notCheckedCheckboxes = $$("div.checkboxes").filterBy(not(cssClass("checked")));

/* Проверка что чекбокс включен */
$("input:checked").should(exist)

Напоследок

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

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

Источник: https://habr.com/ru/post/687246/


Интересные статьи

Интересные статьи

Известный профессор МТИ Гарольд Абельсон сказал: «Программы нужно писать для того, чтобы их читали люди, и лишь случайно — чтобы их исполняли машины». Хотя он намеренно преуменьшил важн...
Накануне, в рамках технологической выставки CES 2021, исполнительный директор AMD Лиза Су представила новую серию мобильных процессоров Ryzen 5000. Новая линейка включает CPU с низким T...
Наш новый рассказ о выпускных проектах студентов наших учебных проектов — последний в этом году. На этот раз мы познакомим вас с тремя работами студентов Технопарка, Технополиса и Техно...
Есть несколько способов добавить водяной знак в Битрикс. Рассмотрим два способа.
Лучшие практики Kubernetes. Создание небольших контейнеров Лучшие практики Kubernetes. Организация Kubernetes с пространством имен Лучшие практики Kubernetes. Проверка жизнеспособно...