Пользователь
0,0
рейтинг
19 сентября 2012 в 01:35

Разработка → 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

Андрей Солнцев @asolntsev
карма
100,0
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (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
      • 0
        Спасибо

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