Selenide: удобные тесты на Selenium WebDriver

  • Tutorial
Многие слышали про Selenium WebDriver — один из самых популярных инструментов для написания приёмочных/интеграционных тестов.


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

Поэтому мы решили выделить этот повторяющийся код в отдельную библиотеку. Так на свет появился Selenide.


Что такое Selenide


Selenide — это обёртка вокруг Selenium WebDriver, позволяющая быстро и просто его использовать при написании тестов, сосредоточившись на логике, а не суете с браузером.

Вот пример теста. Как видите, код минимален. Вызвал «open» — и браузер открылся.

@Test
public void testLogin() {
  open("/login");
  $(By.name("user.name")).sendKeys("johny");
  $("#submitButton").click();
  waitUntil(By.id("username"), hasText("Hello, Johny!"));
  $("#username").shouldHave(cssClass("green-text"));

  assertThat($("#insuranceDetailsHeader").getText(), equalTo("Страховые полисы"));
  assertThat($$("#paymentScheduleTable tr").size(), equalTo(7));
}


При вызове метода open Selenide сам запускает браузер и открывает страницу localhost:8080/login (порт и хост конфигурируется, естественно). А также заботится о том, чтобы в конце браузер закрылся.

Дополнительные вкусности Selenide


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

@Test
public void canFillComplexForm() {
  open("/client/registration");
  setValue(By.name("user.name"), "johny");
  selectRadio("user.gender", "male");
  selectOption(By.name("user.preferredLayout"), "plain");
  selectOptionByText(By.name("user.securityQuestion"), "What is my first car?");
  followLink(By.id("submit"));
  takeScreenShot("complex-form.png");
}

@Before
public void clearCache() {
  clearBrowserCache();
}


И особняком стоит вопрос Ajax: при тестировании приложений, использующих Ajax, приходится изобретать код, который чего-то ждёт (когда кнопка станет зелёной). Selenide предоставляет богатый API для ожидания наступления различных событий:
@Test
public void pageUsingAjax() {
  waitFor("#username");
  waitUntil("#username", hasText("Hello, Johny!"));
  waitUntil("#username", hasAttribute("name", "user.name"));
  waitUntil("#username", hasClass("green-button"));
  waitUntil("#username", hasValue("Carlson"));
  waitUntil("#username", appears);
  waitUntil("#username", disappears);
}


Я хочу попробовать, с чего начать?


1. Добавь в свой проект зависимость Selenide:
<dependency>
    <groupId>com.codeborne</groupId>
    <artifactId>selenide</artifactId>
    <version>1.6</version>
</dependency>


2. Импортируй парочку классов:
include static com.codeborne.selenide.Navigation.*
include static com.codeborne.selenide.DOM.*

Готово! Пиши тесты, едрён-батон!

Кто-нибудь это реально использует?


Да, мы в нашей фирме используем Selenide в нескольких реальных проектах:
  • Java + ANT + JUnit
  • Java + Gradle + JUnit
  • Scala + ANT + ScalaTest


Так что можете быть уверены, проект не сырой, реально используется и поддерживается.
Есть ещё небольшой эталонный open-source проект, в котором используется Selenide: игра Виселица.

Откуда такое название — Selenide?


Библиотека Selenium взяла своё название от химического элемента (Селен). А селениды — это соединения селена с другими элементами.

Вот и у нас:
  • Selenide = Selenium + JUnit
  • Selenide = Selenium + TestNG
  • Selenide = Selenium + ScalaTest
  • Selenide = Selenium + что угодно


Химичьте на здоровье!

UPD. В марте 2013 выпущена версия Selenide 2.0, в которой сильно обновился API. Теперь использование Selenide ещё проще и удобнее.

И ещё мы запустили сайт на русском языке: ru.selenide.org

Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 33
  • +2
    А селениды — это соединения селена с другими элементами.
    Да только большинство программистов прочтут Selenide не как селениды, а как Selen IDE.
    ИМХО.
    • +1
      Спасибо за наводку, попробую.
      • 0
        Молодцы, парни!

        Насколько я понял, пока реализовано только соединение с JUnit, планируете сделать варианты с другими тестовыми фреймворками?
        • 0
          Спасибо!
          На самом деле логика работы Selenide напрямую с JUnit не связана. Её можно использовать и с любыми другими фреймворками, ничего не мешает. Мы же использовали с ScalaTest, например. Едиственное, что Selenide в случае падения теста выкидывает org.junit.Assert#fail, то есть всё-такие требует наличия JUnit в classpath. Но это вроде не должно создавать проблем.
          • 0
            Я имею в виду, что в дополнение к TestWatcher'у, который снимает скриншоты, было бы хорошо сделать аналоги для других тестовых фреймворков.
            • 0
              А, да, конечно, такие планы есть.
              Для TestNG можем и сами сделать, а сколько ещё этих фреймворков?
              Проще всего будет, если каждый, кому это надо, сделает Pull Request для поддержки своего любимго фреймворка.
        • 0
          Интересный проект!
          А не сталкивались ли вы с проблемой тестирования загрузки файлов?
          Вот тут действительно кроссбраузерная реализация одной функцией пригодилась бы!
          • 0
            Вопрос не в бровь, а в глаз.
            Загрузка файлов — это геморрой тот ещё. В самом Selenium нет такой функциональности. Насколько я понимаю, совсем уж кроссбраузерной реализации пока не может быть, во всех браузерах это по-любому будет реализовано по-разному.

            У нас есть опыт, когда мы подкюлчали в проект ещё и AutoIT и с помощью него делали загрузку файлов. Но это всё так сложно и ненадёжно, что в Selenide я решил пока это не включать. Загрузку файлов тестируем пока вручную. :(
            • +1
              Рекомендую ознакомиться вот с этой статьёй: How To Download Files With Selenium And Why You Shouldn’t, в ней обсуждаются различные варианты решения этой задачи.

              Я иногда использую ещё один подход, не описанный в этой статье — прокси между браузером и тестируемым приложением, который перехватывает запросы на загрузку файлов и сам их загружает, а в браузер отдаёт страничку «файл загружен, находится тут».
              • 0
                Кстати, да, спасибо за подсказку.
                Я сделал как описано в этой статье. Теперь в Selenide есть метод download для скачивания файла:

                File file = $("#download_button").download();
            • 0
              Сам бодался с селениумом очень долго. Почти весь код его тоже запроксировали, в основном, правда, использовали PageObject.
              Понравилась Ваша обёртка над waitUntil, так держать, если ещё раз столкнусь, обязательно попробую Selenide
              • 0
                Селениум — морально устаревший инструмент. Попробуйте: Sahi, и пишите взрослые тесты без костылей. Очень советую
                • 0
                  500 баксов за штуку?
                  • +1
                    Бесплатный пакет покрывает потребности более чем полностью. Реализуется любая логика, поддерживаются циклы и тп. При небольшом умении и желании результаты тестов сыпятся на почту.

                    Поднимаются виртуалки, на них конфигурируется среда. И хоть по каждому коммиту гоняй тесты. Тесты можно писать на джаве, руби, питоне. Есть еще много всяких плюшек. Силениум нервно курит со своей дебильной ломоватостью и описанием действий в таблице через xslt. Они бы ещё в цсс выражали бы действия

                    И если перед вами стоит серьезная задача по тестированию серьезного проекта, то да, 500 за штуку. Для серьезной организации это не деньги.
                    • 0
                      ок, спасибо за ответ!
                      • 0
                        Пожалуйста, если будут вопросы, пишите в личку, сориентирую как смогу)
                      • 0
                        Опа-опа. Какой ещё xslt? Какой ещё css?
                        Вы, наверное, путаете Selenium WebDriver с чем-то другим. В Selenium WebDriver как раз-таки тесты можно писать на джаве, руби, питоне.
                        Виртуалки поднимать с разными средами можно с помощью Jenkins или ещё чего-нибудь — одним словом, это не задача Selenium.
                        • 0
                          Про цсс — стёб.

                          Возможно, возможно, я давно пробовал Селениум в качестве средства тестирования, наверное мы говорим о разных вещах :(
                          • 0
                            Если учесть, что Selenium 2.0 (aka WebDriver) релизнулся впервые всего полтора года тому назад — сложно было его «давно пробовать», так что — наверняка о разных :)
                            • 0
                              Да, вы правы, это было около 3х лет назад. Тогда тесты на нём писались просто ужасно.
                              Судя по тому, как он реализован сейчас они много заимствовали у Sahi за это время)
                              • +1
                                Я понимаю, что Вам очень хочется похвалить Sahi? :)
                                Хороший инструмент, кто же спорит.
                                Но всё-таки расскажите, в чём состоят заимствования?
                  • 0
                    А в чём прикол-то? Половина описаного в 20 строк:
                    protected WebElement $(String selector) { return driver.findElement(By.cssSelector(selector)); } protected WebElement csswait(String selector) { return waitElement(By.cssSelector(selector)); } protected WebElement waitElement(final By selector) { return new WebDriverWait(driver, 10) .until(new ExpectedCondition<WebElement>() { public WebElement apply(WebDriver d) { return d.findElement(selector); } } ); }
                    • 0
                      Простите, не ожидал, что <code> не сработает.

                      	protected WebElement $(String selector) {
                      		return driver.findElement(By.cssSelector(selector));
                      	}
                      	
                      	protected WebElement csswait(String selector) {
                      		return waitElement(By.cssSelector(selector));
                      	}
                      	
                      	protected WebElement waitElement(final By selector) {
                      		return new WebDriverWait(driver, 10)
                      			.until(new ExpectedCondition<WebElement>() {
                      				public WebElement apply(WebDriver d) {
                      					return d.findElement(selector);
                      				}
                      			}
                      		);
                      	}
                      
                      • –1
                        Ну так наш вариант гораздо короче. В этом и прикол.
                        • 0
                          Вы не поняли, это выдержка из базового класса, который предоставляет наследникам такие же возможности, как ваша библиотека.
                          Пример использования:

                          public class Users extends Base {
                          		
                          	@Test public void listsUsers() {
                          		$("a.users").click();
                          		assertEquals("Users", $wait("h1.user").getText());
                          		assertEquals("Users", driver.getTitle());
                          		assertEquals("All Users", $("#content h2").getText());
                          		$("#content .results #spaceList .result");
                          ...
                          

                          • 0
                            Так что это за базовый класс? Где его найти?
                            • 0
                              Вот в этом комментарии представлена немалая его часть. Обладая даже базовым знанием java всё остальное можно дописать, причём очень быстро. В чём прелесть описанной библиотеки относительно голого Selenium, я не ощутил.
                              • 0
                                Эээ… Так-то это можно про любую библиотеку сказать.
                                В том-то и прелесть, что этот код не надо дописывать. Зачем писать то, то уже написано?
                                • 0
                                  Этот вопрос до сих пор задаёт себе John Resig, вспоминая Prototype.js.

                                  Просто можно понадеятся на чужую библиотеку, но если работы на час или меньше, то проще написать. А когда уже всё написано самостоятельно, то переписывать весь код тестов под синтаксис новой библиотеки смысл есть только, если что-то радикально сильно улучшается.
                                  В данном случае оба предположения не верны. Можно и написать подобное за час, и ничего радикально не улучшается.
                                  Однако всё равно спасибо, что поделились. Синтаксис выглядит приятно.
                                  • +2
                                    Если такой код у вас уже написан, то конечно нет смысла переписывать.
                                    Однако этот факт говорит о том, что библиотека востребована.

                                    Одно предположение у вас неверно: код, который написан в библиотеке, всё-таки не написать за час без ошибок. И даже если написать, зачем каждый раз тратить этот час?

                                    Насчёт «понадеяться»: поскольку исходный код открытый, вы можете сами его посмотреть и убедиться, что там примерно то же, что вы сами бы и написали, а стало быть, можно библиотеке доверять и не тратить в следующий раз своё время.
                    • 0
                      Как создать драйвер с определенным профилем через вашу обертку?
                      • 0
                        Можно даже несколькими способами.

                        Самое простое — создать свой объект WebDriver, какой душе угодно, и приказать Selenide его использовать:
                        WebDriverRunner.setWebDriver(myWebDriver).

                        Таким образом можно запускать Selenide вместе с уже существующими тестами, которые используют голый Selenium WebDriver или любой другой фреймворк.

                        Более продвинутый способ — запустить тесты с параметром "-Dbrowser=com.mycompany.CustomWebDriverProvider". Пример кода см. в Wiki: github.com/codeborne/selenide/wiki/How-Selenide-creates-WebDriver

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