Статьи

Эффективные тесты пользовательского интерфейса с Selenide

В ожидании чудес

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

Каждый Java-разработчик мечтает о чуде, которое позволит ему стать самым эффективным Java-разработчиком в мире.

Я хочу показать вам такое чудо.

Это называется автоматизированные тесты !

Тьфу, тесты?

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

Но разве тестирование не скучно?

О нет, поверь мне! Написание быстрых и стабильных автоматических тестов — сложная задача для самых умных руководителей. И это может быть очень весело и интересно. Вам нужно только использовать правильные инструменты.

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

селенида

Selenide — это библиотека с открытым исходным кодом для написания кратких и стабильных тестов пользовательского интерфейса.

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

Давайте посмотрим на простейший тест Selenide:

01
02
03
04
05
06
07
08
09
10
11
12
13
public class GoogleTest {
  @Test
  public void user_can_search_everything_in_google() {
    open("http://google.com/ncr");
    $(By.name("q")).val("selenide").pressEnter();
 
    $$("#ires .g").shouldHave(size(10));
 
    $("#ires .g").shouldBe(visible).shouldHave(
        text("Selenide: concise UI tests in Java"),
        text("selenide.org"));
  }
}

Давайте посмотрим ближе, что здесь происходит.

  • Вы открываете браузер одной командой open(url)
  • Вы находите элемент на странице с помощью команды $ .
    Вы можете найти элемент по имени, идентификатору, селектору CSS, атрибутам, xpath и даже по тексту.
  • Вы манипулируете элементом : вводите текст с помощью val() и нажимаете ввод с (сюрприз-сюрприз!)
  • Вы проверяете результаты : найдите все найденные результаты с помощью $$ (он возвращает коллекцию всех соответствующих элементов). Вы проверяете размер и содержание коллекции.

Разве этот тест не легко читать? Не легко ли написать этот тест?

Я верю, что это так.

Глубже в деталях

Ajax / проблемы со временем

В настоящее время веб-приложения являются динамическими. Каждая отдельная часть приложения может быть визуализирована / изменена динамически в любой момент. Это создает много проблем для автоматизированных тестов. Зеленый тест сегодня может внезапно стать красным в любой момент, просто потому что браузер выполнил некоторый JavaScript немного дольше, чем обычно.

Это настоящая боль в Ajjaxx .

Совершенно невероятно, но Selenide решает большинство из этих проблем очень простым способом.

Проще говоря, каждый метод Selenide ждет немного, если это необходимо . Люди называют это «умным ожиданием».

Когда вы пишете:

1
$("#menu").shouldHave(text("Hello"));

Selenide проверяет, существует ли элемент и содержит ли текст «Hello».

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

Богатый набор спичек

Вы можете проверить почти все с Selenide. Использование механизма «умного ожидания», упомянутого выше.

Например, вы можете проверить, существует ли элемент. Если нет, Selenide будет ждать до 4 секунд.

1
$(".loading_progress").shouldBe(visible);

Вы даже можете проверить, что элемент не существует. Если он все еще существует, Selenide будет ждать до 4 секунд, пока не исчезнет.

1
$(By.name("gender")).should(disappear);

И вы можете использовать свободные API и цепочечные методы, чтобы сделать ваши тесты действительно краткими:

1
2
3
$("#menu")
  .shouldHave(text("Hello"), text("John!"))
  .shouldBe(enabled, selected);

Коллекции

Selenide позволяет работать с коллекциями, таким образом проверяя множество элементов в одной строке кода.

Например, вы можете проверить, что на странице ровно N элементов:

1
$$(".error").shouldHave(size(3));

Вы можете найти подмножество коллекций:

1
2
3
$$("#employees tbody tr")
  .filter(visible)
  .shouldHave(size(4));

Вы можете проверить тексты элементов. В большинстве случаев достаточно проверить всю таблицу или строку таблицы:

1
2
3
4
5
6
7
$$("#employees tbody tr").shouldHave(
  texts(
      "John Belushi",
      "Bruce Willis",
      "John Malkovich"
  )
);

Загрузить / скачать файлы

Загрузить файл с помощью Selenide довольно просто:

1
$("#cv").uploadFile(new File("cv.doc"));

Вы даже можете загрузить несколько файлов одновременно:

1
2
3
4
5
$("#cv").uploadFile(
  new File("cv1.doc"),
  new File("cv2.doc"),
  new File("cv3.doc")
);

И это невероятно просто скачать файл:

1
File pdf = $(".btn#cv").download();

Тестирование «высокодинамичных» веб-приложений

Некоторые веб-фреймворки (например, GWT) генерируют HTML, который абсолютно нечитаем. Элементы не имеют постоянных идентификаторов или имен.

Это настоящая боль в xpathh .

Selenide предлагает решить эту проблему путем поиска элементов по тексту.

1
2
3
4
5
6
7
import static com.codeborne.selenide.Selectors.*;
 
$(byText("Hello, Devoxx!"))     // find by the whole text
   .shouldBe(visible);
 
$(withText("oxx"))              // find by substring
   .shouldHave(text("Hello, Devoxx!"));

Поиск по тексту совсем не плохая идея. На самом деле, мне это нравится, потому что оно имитирует поведение реального пользователя. Реальный пользователь не находит кнопки по ID или XPATH — он находит по тексту (или, ну, по цвету).

Еще один полезный набор методов Selenide позволяет вам перемещаться между родителями и детьми.

1
2
3
4
$("td").parent()
$("td").closest("tr")
$(".btn").closest(".modal")
$("div").find(By.name("q"))

Например, вы можете найти ячейку таблицы по тексту, затем по ближайшему ее потомку tr и найти кнопку «Сохранить» внутри этой строки таблицы:

1
2
3
4
5
$("table#employees")
  .find(byText("Joshua"))
  .closest("tr.employee")
  .find(byValue("Save"))
  .click();

… И много других функций

Selenide имеет много других функций, таких как:

01
02
03
04
05
06
07
08
09
10
11
12
13
$("div").scrollTo();
$("div").innerText();
$("div").innerHtml();
$("div").exists();
$("select").isImage();
$("select").getSelectedText();
$("select").getSelectedValue();
$("div").doubleClick();
$("div").contextClick();
$("div").hover();
$("div").dragAndDrop()
zoom(2.5);
...

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

Используйте силу IDE! Сконцентрируйтесь на бизнес-логике.

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

Сделай мир лучше

Я верю, что мир станет лучше, когда все разработчики начнут писать автоматизированные тесты для своего кода. Когда разработчики встают в 17:00 и уходят к своим детям, не опасаясь, что они что-то сломали с последними изменениями.

Давайте сделаем мир лучше, написав автоматизированные тесты!

Поставьте работающее программное обеспечение.