Andrei Solntsev
ОБО МНЕ
Программер
Codeborne

DevClub.eu
организатор
Selenide.org
автор
ОБО МНЕ
О НАС
TDD

Парное программирование

Чистый код
KISS

Прогеры пишут и код, и тесты
АГЕНДА
•Selenide
•Проблемы UI
тестов
•Примеры Selenide
Selenide
=
лаконичные и стабильные
тесты
(на Selenium WebDriver)
SELENIDE
•Лаконичные
•Читаемые
•Без мусора

Сконцентрируйся на бизнес-логике!
SELENIUM+API=SELENIDE
selenide.org

@Test
public void userCanLogin() {
open("/login");
$("#username").setValue ("john");
$(by("type", "submit")).click();
$(".menu").shouldHave (text("Hello, John!"));
}
Типичные проблемы UI-тестов
•Нестабильные (Чёртов Ajax!)
StaleElementException
ElementNotFoundException

•Поддержка
•Архитектура
Решения: Ajax
Все should-методы ЖДУТ при необходимости.

$(".loading_progress").shouldBe(visible);
$("#menu").shouldHave(text("Hello,
John!"));
$(By.name("sex")).shouldNotBe(selected)
;
РЕШЕНИЯ: ПОДДЕРЖКА
Ищите элементы по тексту

import static com.codeborne.selenide.Selectors.*;
$(byText("Hello, braza!")).shouldBe(visible);
$(withText("raza"))
.shouldHave(text("Hello, braza!"));
РЕШЕНИЯ:АРХИТЕКТУРА

ПАЦАН НАКОДИЛ
---

ПАЦАН ПРОТЕСТИЛ!
ЗАЛОГ УСПЕХА
ant test
Юнит-тесты
Быстрые & стабильные -- МНОГО

ant uitest
UI тесты
Медленные & капризные -- МАЛО
SELENIDE
VS
SELENIUM WEBDRIVER
WEBDRIVER
DesiredCapabilities cap = htmlUnit();
cap.setCapability(INVALIDSELECTIONERROR, true);
cap.setCapability(INVALIDXPATHERROR, false);
cap.setJavascriptEnabled(true);
WebDriver driver = new HtmlUnitDriver(cap);

•firefox
•chrome
•htmlunit
•phantomjs
•ie
open("/my-application/login");
FIND ELEMENT
WebElement customer =
driver.findElement(By.id("customerContainer"));

WebElement customer = $("#customerContainer");
TEXT CHECK
assertEquals("Customer profile",
driver.findElement(
By.id("customerContainer")).getText());

$("#customerContainer").shouldHa
ve(
text("Customer profile"));
MULTIPLE CHECKS
$("#customerContainer").shouldHa
ve(
text("Customer profile"),
text("John"),
cssClass("active-profile"));
AJAX SUPPORT
FluentWait<By> fluentWait = new FluentWait<By>(By.tagName("TEXTAREA"));
fluentWait.pollingEvery(100, TimeUnit.MILLISECONDS);
fluentWait.withTimeout(1000, TimeUnit.MILLISECONDS);
fluentWait.until(new Predicate<By>() {
public boolean apply(By by) {
try {
return browser.findElement(by).isDisplayed();
} catch (NoSuchElementException ex) {
return false;
}
}
});
assertEquals("John",
browser.findElement(By.tagName("TEXTAREA")).getAttribute("value"));
AJAX SUPPORT
$("TEXTAREA").shouldHave(value("John"));
$("#location").shouldHave(text("Riga"));
$(".logout").shouldNotBe(visible);
$(".logout").should(disappear);
MORE CHECKS
$("#customerContainer").shouldHa
ve(
text("Customer profile"),
attribute("title", "Profile"),
attribute("readonly"),
cssClass("active-profile"));
COLLECTIONS
$$("#boys tr").shouldHave(size(1));
$$("#girls tbody tr").shouldHave(
texts("Angelina", "Veronika", "Darlene"));
SCREENSHOTS
public class MyTest {
@Rule
public ScreenShooter
photographer =
ScreenShooter
.failedTests()
.succeededTests();
}
SCALA
class CampaignsListSpec extends
BeforeAndAfter {
"User" can "see existing campaigns" in {
$(".header").shouldHave(
text(Labels.get("campaigns.title")))

}

$$("#existingCampaignsList tbody tr")
.shouldHaveSize(2)
}
GROOVY
ДЕМО
http://github.com/codeborne/selenide_examples
ПОЖАЛУЙСТА!
Q&A

http://selenide.org
andrei.solntsev@gmail.com

Selenide