Как начать дружбу с Selenide
30 марта 2022 г.Оглавление
Как я и обещал, мы начнем писать код в этом разделе как можно скорее. Если вы пропустили [мою предыдущую статью] (https://hackernoon.com/selenium-vs-selenide-what-is-the-better-ui-test-automation-framework), я настоятельно рекомендую прочитать ее заранее, так как я привели много причин, по которым вам стоит попробовать Selenide.
Настраивать
- Вам понадобится Java Development Kit. Я предлагаю получить последнюю версию [Open JDK 17] (https://mszeles.com/selenium-or-selenide).
- В качестве IDE я использую IntelliJ IDEA, но вы можете использовать что угодно. Помимо IntelliJ, наиболее популярными являются [Eclipse] (https://www.eclipse.org/downloads/) и [Visual Studio Code] (https://code.visualstudio.com/download).
- Для управления исходным кодом я использую Git, проект можно найти на GitHub.
- Обычно я использую Maven для проектов Java, но это прекрасная возможность узнать что-то новое, поэтому на этот раз я буду использовать Gradle. Если я совершу глупую ошибку с Gradle, не стесняйтесь сказать мне 😉
- В качестве среды тестирования Java наиболее популярны TestNG и JUnit. Я выберу TestNG, но я также предоставлю необходимую информацию для JUnit 5. Это все, что вам нужно для проекта.
Давайте продолжим создание проекта Gradle и открытие файла build.gradle. Добавим зависимости:
зависимости {
testImplementation 'org.testng:testng:7.5'
реализация 'com.codeborne:selenide:6.2.1'
реализация 'org.seleniumhq.selenium:selenium-java:4.1.1'
Для Юнит:
зависимости {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
реализация 'com.codeborne:selenide:6.2.1'
реализация 'org.seleniumhq.selenium:selenium-java:4.1.1'
Укажите для использования TestNG:
тестовое задание {
использоватьTestNG()
для JUnit:
тестовое задание {
использоватьJUnitPlatform()
Мы готовы идти. Остается только один вопрос. Какой сайт мы будем тестировать?
Вы когда-нибудь записывались на курс с высоким рейтингом, чтобы узнать об автоматизации тестирования, только для того, чтобы понять, что половина страниц, которые использовались в качестве примеров в курсе, больше не существуют или были полностью изменены?
Ну, это случилось со мной. Мой выбор (почти) второй любимый сайт всех разработчиков (сразу после Google) Stackoverflow. Мой третий фаворит — [Baeldung] (https://gradle.org/install/), если вам интересно 😊. Я почти уверен, что Stackoverflow не исчезнет в ближайшем будущем, но, конечно, я не могу гарантировать, что он не изменит свой дизайн.
Пришло время написать наш первый тест. Ура. Давайте начнем с чего-то простого.
Открыть Stackoverflow
Используя Selenide, вам не нужно использовать WebDriver напрямую, так как он автоматически открывает и закрывает браузер для нас, использующих Chrome по умолчанию. Мы можем открыть страницу одной строкой без дополнительной настройки.
@Тестовое задание
общественная пустота openPage () {
открыть("https://stackoverflow.com/");
Просто запустите тест, и вы увидите, что Stackoverflow открывается, а затем сразу же закрывается. Всякий раз, когда я разрабатываю и ищу DOM-элементы, я предпочитаю открывать ту же страницу в своем браузере в режиме инкогнито, чтобы видеть точно такой же результат, как и всякий раз, когда я открываю ее через Selenide. Давайте сделаем это сейчас.
Первое, что я заметил, это то, что на этой странице у нас есть баннер принятия файлов cookie. Поскольку в наши дни у нас есть что-то подобное на каждом веб-сайте, давайте примем файл cookie. Но перед этим давайте закончим наш первый тест. Каждый достойный тест должен проверять некоторые условия.
Проверка видимости и включенного состояния элементов
Конечно, мы могли бы выбрать множество условий для тестирования, но в данном случае я сосредоточусь на демонстрации различных способов проверки условий в Selenide. Давайте убедимся, что у нас есть видимые кнопки входа и регистрации.
Для этого, во-первых, мы должны найти элемент. Глядя на DOM в инструментах разработчика Chrome (или, конечно, вы можете использовать Firefox или другие инструменты, если хотите), мы видим, что кнопка входа на самом деле является ссылкой.
У него нет идентификатора, но есть класс ссылка для входа который кажется уникальным. Поэтому я мог бы использовать простой селектор CSS или даже селектор на основе идентификатора. Но действительно ли он уникален?
Если вы посмотрите внимательно, то заметите, что, несмотря на название, ссылка «Регистрация» имеет тот же ссылку для входа класс, что и кнопка «Вход», поэтому мне придется выбирать на основе индекса. . Для этой цели я использую XPath (в целом предпочитаю CSS, а не XPath, так как он быстрее).
Вы можете подумать, что мы должны использовать текст для поиска элемента, поскольку он уникален, но я не рекомендую, исходя из моего опыта, тексты меняются чаще, чем идентификаторы и классы , даже не говоря о тестировании на разных языках.
Напишем селектор:
$x("(//a[содержит(@class, 'логин-ссылка')])[1]");
Это очень просто, лаконично и понятно. Вы можете использовать $(String cssSelector), $$(String cssSelector), чтобы найти элемент ($) или элементы ($$) с помощью CSS. Точно так же вы можете использовать $x(String xpath) и $$x(String xpath) для поиска элементов с помощью XPath.
Конечно, вы также можете использовать встроенные команды Selenium By, используя $(By) и $$(By). Selenide даже предоставляет новые селекторы в дополнение к обычным селекторам Selenium, таким как byText, withText и byAttribute.
Если вы не знакомы с основными селекторами Selenium, я снова рекомендую [Курс Udemy Рахула Шетти] (https://www.udemy.com/course/selenium-real-time-examplesinterview-questions) по Selenium. Вы будете иметь хорошее представление о них после окончания курса. Еще один полезный ресурс для начинающих — [CSS Dinner] (https://www.udemy.com/course/selenium-real-time-examplesinterview-questions).
Теперь, когда у нас есть элемент SelenideElement (подкласс WebElement), мы можем проверить его видимость:
$x("(//a[содержит(@class, 'ссылка для входа')])[1]").shouldBe(visible) ; Этот код легко прочитать. На самом деле писать это также легко и весело. 😀 Вы можете спросить, что происходит, если элемент сразу не присутствует в DOM, или что, если он присутствует, но ему нужно некоторое время, чтобы стать видимым?
Selenide использует неявные ожидания как при поиске элементов, так и при оценке условий. По умолчанию 4 секунды, но его можно настроить. Функции должны (should, shouldHave, shouldBe, ShouldNot, shouldNotHave, shouldNotBe) даже имеют перегруженную версию, которая также принимает Duration для явного указания тайм-аута.
Вы можете запустить свой тест из своей любимой IDE или запустить его из командной строки с помощью Gradle:
тест градлью
Просто измените «видимый» на «включенный», чтобы проверить включенное состояние элемента:
$x("(//a[содержит(@class, 'логин-ссылка')])[1]").shouldBe(enabled);
На основе предыдущего примера довольно легко написать проверку для ссылки «Регистрация»:
$x("(//a[содержит(@class, 'логин-ссылка')])[2]").shouldBe(visible);
$x("(//a[содержит(@class, 'логин-ссылка')])[2]").shouldBe(enabled);
Проведем рефакторинг
Прежде чем двигаться дальше, давайте проведем рефакторинг, чтобы сделать код чище и приблизиться на один шаг к объектной модели страницы, о которой я напишу в следующей статье. Давайте сделаем 2 вещи. Во-первых, извлеките элементы входа и регистрации как константы, используя осмысленные имена.
Если вы беспокоитесь о том, чтобы найти элемент еще до того, как страница будет создана, у меня есть для вас хорошие новости. Selenium (а также Selenide) использует ленивую инициализацию, что означает, что элементы будут расположены только тогда, когда вы вызываете для них какие-либо методы.
Во-вторых, мы будем использовать цепочку методов, чтобы получить более краткий код. Мне очень нравится эта техника, как вы увидите в следующих статьях. Итак, вот код после рефакторинга:
открытый класс HomepageTest {
private final SelenideElement loginLink = $x("(//a[contains(@class, 'login-link')])[1]");
private final SelenideElement signUpLink = $x("(//a[contains(@class, 'login-link')])[2]");
@Тестовое задание
общественная пустота openPage () {
открыть("https://stackoverflow.com/");
loginLink.shouldBe(видимый).shouldBe(включен);
signUpButton.shouldBe(видимый).shouldBe(включен);
Поиск элементов по тексту
Как я и обещал, скоро мы доберемся до баннера cookie. Просто еще одна вещь перед этим. Как я уже сказал, находить элементы на основе текстов — не лучшая идея, но иногда у вас просто нет других вариантов (конечно, вы можете найти все с абсолютными выражениями XPath, но это ужасная идея, так как она сломает при малейшем изменении пользовательского интерфейса) или вы должны проверить, есть ли у элементов определенный текст.
На этот раз мы будем придерживаться английского, но позже я напишу статью об интернационализации.
Найдем ссылку с текстом «О программе» и проверим, указывает ли она на нужное место.
Здесь мы можем выбрать один из нескольких вариантов:
Поиск с использованием XPath
$x("//a[text()='О программе']");
$x("//a[содержит(text(), 'bout')]");
Вы можете проверить наличие точных или частичных совпадений с помощью XPath.
Поиск с использованием linkText или partialLinkText
$(By.linkText("О программе"));
$(By.partialLinkText("бой"));
Вы можете найти элемент, используя стандартные локаторы Selenium.
Найти с помощью byText и withText $(byText("О программе")) $(withText("bout"));; Вы также можете найти элемент с помощью локаторов Selenide. byText похож на linkText, так как находит элемент, используя точное совпадение с текстом, а withText похож на partialLinkText, поскольку проверяет, содержит ли текст элемента заданный текст или нет.
Но здесь у Selenide есть огромное преимущество: он работает со всеми типами элементов, а не только со ссылками.
Проверка ссылки на ссылку
Это довольно просто:
aboutLink.shouldHave(href("/company"));
Я настоятельно рекомендую ознакомиться с [документацией] класса Conditions (https://selenide.org/javadoc/current/com/codeborne/selenide/Condition.html), чтобы вы могли получить представление о различных условиях, предлагаемых Selenide.
Закрытие баннера
Наконец, мы подошли к последней теме сегодняшней статьи — приему файлов cookie. Давайте создадим еще один тест с именем acceptCookies. Во-первых, давайте найдем кнопку принятия:
![Часть исходного кода Stackoweflow для кнопки принятия файлов cookie] (https://cdn.hackernoon.com//images/GzgG671TbkZSBOpCWYJgJy5aIQp2-2022-03-21T23:04:45.561Z-cl11bfbw9008j0as62y7yedo2)
Глядя на исходный код страницы, мы видим, что это кнопка, которую мы должны нажать, и у нее есть класс js-accept-cookies, который может идентифицировать кнопку. Итак, мы можем легко найти его по имени класса:
$(byClassName("js-accept-cookies"));
Найдя кнопку, мы можем щелкнуть ее, просто используя для нее метод click(), поскольку мы могли бы уже изучить его с помощью Selenium.
acceptCookiesButton.click();
В случае, если тест не завершится неудачей, мы можем сказать, что смогли нажать кнопку «Принять cookie», но на всякий случай давайте проверим, действительно ли баннер исчез. Баннер — это div с классом js-consent-banner.
Чтобы убедиться, что его больше нет, мы можем использовать метод shouldNotBe:
частный финал SelenideElement acceptCookieBanner = $("div.js-consent-banner");
acceptCookieBanner.shouldNotBe(видимый);
или вы можете написать:
acceptCookieBanner.shouldBe(скрыто);
На самом деле должен, должен быть и должен иметь — синонимы, как и их аналоги должны не, должны не быть, должны не иметь. Они взаимозаменяемы, а также среди условий есть много синонимов, поэтому в основном вам решать, что вы считаете более читабельным. Эти примеры означают одно и то же:
acceptCookieBanner.shouldBe(скрыто);
acceptCookieBanner.shouldNotBe(видимый);
acceptCookieBanner.should(исчезнуть);
acceptCookieBanner.shouldNot (появляться);
Я предпочитаю не использовать отрицание, поэтому я использую shouldBe(hidden).
Последние штрихи
Прежде чем мы закончим, давайте сделаем еще 2 рефакторинга, чтобы уменьшить дублирование и сделать код еще проще.
Поскольку в этих тестах мы тестируем одну и ту же домашнюю страницу, мы можем переместить открытие страницы в общую часть, которая выполняется перед каждым тестом. В TestNG вы можете использовать @BeforeMethod для этого, используя JUnit 5, @BeforeEach будет вашим решением.
Чтобы получить хорошее сравнение использования двух фреймворков, проверьте [эту статью о Baeldung] (https://www.baeldung.com/junit-vs-testng).
При проверке ссылки для входа и регистрации мы использовали 2 связанных метода shouldBe, чтобы проверить, виден ли компонент и включен ли он. На самом деле вы можете объединить их в один вызов, так как методы должны принимать несколько условий.
Это окончательный код:
открытый класс HomepageTest {
private final SelenideElement loginLink = $x("(//a[contains(@class, 'login-link')])[1]");
private final SelenideElement signUpLink = $x("(//a[contains(@class, 'login-link')])[2]");
закрытый окончательный SelenideElement aboutLink = $(byText("About"));
private final SelenideElement acceptCookiesButton = $(byClassName("js-accept-cookies"));
частный финал SelenideElement acceptCookieBanner = $("div.js-consent-banner");
@BeforeMethod
настройка публичной пустоты () {
открыть("https://stackoverflow.com/");
@Тестовое задание
общественная пустота openPage () {
loginLink.shouldBe(видимый, включенный);
signUpLink.shouldBe(видимый, включенный);
aboutLink.shouldHave(href("/company"));
@Тестовое задание
public void acceptCookies () {
acceptCookiesButton.click();
acceptCookieBanner.shouldBe(скрыто);
Выглядит аккуратно, вам не кажется? 😊
И это все. Мы закончили сегодняшний урок. Я надеюсь, что вам понравилось. Не стесняйтесь поделиться своими мыслями об этой статье и предложить темы для будущих. В следующем посте я разработаю тесты для страницы вопросов Stackoverflow.
📚 Прежде чем мы закончим, я дам вам задание. Я использовал XPath, чтобы найти ссылку для регистрации. Напишите селектор CSS (не используя текст ссылки), чтобы найти ссылку для регистрации! Пожалуйста, не публикуйте свое решение сразу, дайте время другим. Поэтому я прошу вас опубликовать решение в понедельник❣️
До скорого...
Гитхаб: https://github.com/mszeles/selenide-tutorial
Если вы не хотите пропустить мои посты, просто подпишитесь на меня здесь, на Hashnode, на LinkedIn, в Twitter, в Medium.com, в dev.to и даже в Instagram. 😊
P.S.: Поддержите меня, поделившись этой статьей. 👍
📚Присоединяйтесь к сообществу Selenide на LinkedIn! ✌
Купи мне кофе! ❤️
Оригинал