Выполняется через System.setProperty();
mvn -Dselenide.timeout=8000
$ - возвращает первый элемент
‘‘‘java```java
$$("#employees tbody tr").shouldHave(
tests(
"John Belushi",
"Bruce Willis",
"John Malkovich"
)
);
$$("#employees tbody tr")
.filter(visible)
.shouldHave(size(4));
$("#loginBtn") = $(By.id("loginBtn"));
$(".active") = $(By.className("active"));
$("[name=username]") = $(By.name("username"));
$x("//div//h1") = $(By.xpath("//div//h1"));
$(by("type", "checkbox"));
$(by("readonly", "readonly"));
$(byTitle("Login form"));
$(byValue("Alert button"));
$(by("data-test-id", "alert-button"));
$(byText("Hello"));
$(withText("ello"));
open("url");
$(By.name("user.name")).setValue("john");
$("#submit").click();
$(".menu").shouldHave(text("Hello, John!"));
public class GooglePage {
public void search(String queue){
$(By.name("q"))
.val(queue)
.pressEnter();
}
}
Можно вынести локатор в поле класса:
```java
public class GooglePage {
private By query = By.name("q");
public void search(String queue){
$(query)
.val(queue)
.pressEnter();
}
}
@Test{
var page = new GooglePage();
}
Можно вынести в поле весь элемент, но тогда нужно инициализировать класс страницы через специальный Factory метод.
public class GooglePage {
private SelenideElement query = $(By.name("q"));
public void search(String queue){
query
.val(queue)
.pressEnter();
}
}
@Test{
var page = page(GooglePage.class);
}
public class HtmlElementsPage {
SelenideElement container = $("...");
SelenideElement username = container.$("...");
SelenideElement password = container.$("...");
public void login(String un, String pwd){
username.val(un);
password.val(pwd);
}
}
Или другой вариант:
public class HtmlElementsPage {
@FindBy(id="status")
StatusBlock status;
}
class StatusBlock extends ElementsContainer {
@FindBy(className="username")
SelenideElement username;
@FindBy(className = "password")
SelenideElement password;
}
$.parent()
$.closest("table")
$("table td[data-foo='bar']")
.closest("table")
.find("tr", 4)
.find(byText("text"));
java -Dselenide.browser=chrome
java -Dselenide.browser=firefox
java -Dselenide.browser=ie
java -Dselenide.browser=cy.test.MyWebDriver
Эти параметры удобно использовать когда в gradle.build мы создаем разные tasks или в pom.xml создаем разные profile
task chrome(type: Test){
systemProperties['selenide.browser'] = 'chrome'
}
task firefox(type: Test){
systemProperties['selenide.browser'] = 'firefox'
}
Jenkins
Job 1: ./gradlew chrome
Job 2: ./gradlew firefox
или можно задать браузер прямо в коде
@Before
public void setUp(){
Configuration.browser = "chrome";
// or Configuration.browser = "firefox";
// or Configuration.browser = "cy.MyWebDriver";
}
@Before
public void setUp(){
this.browser = new ChromeDriver(........);
WebDriverRunner.setWebDriver(browser);
}
@Before
public void setUp(){
Configuration.browser = MyWDProvider.class.getName();
open("https://google.com");
}
static class MyWDProvider implements WebDriverProvider{
@Override
public WebDriver createDriver(DesiredCapabilities capabilities){
ChromeOptions options = new ChromeOptions();
options.setHeadless(true);
options.setArguments("--proxy-bypass-list=<-loopback>");
options.merge(desiredCapabilities);
return new ChromeDriver(options);
}
}
var b1 = new SelenideDriver();
b1.open("http://some.site.com");
b1.$("#username").val("petja").pressEnter();
b1.$("#name").shouldHave(text("Hello, Petja!"));
var b2 = new SelenideDriver();
b2.open("http://some.site.com/admin");
b2.$(".block[data-username='petja']").click();
b1.$("#name").shouldHave(text("Goodbye, Petja!"));
При вызове браузеров можно также передавать разные настройки:
var b1 = new SelenideDriver(
new SelenideConfig()
.timeout(6000)
.browser("chrome")
.headless(true)
);
var b2 = new SelenideDriver(
new SelenideConfig()
.timeout(90_000)
.browser("firefox")
.proxyEnabled(true)
);
Есть два варианта:
@Test
public void userCanViewTerminalDetailsAsPDF() throws FileNotFoundException {
File detailsAsPdf = $("#print-pdf").download();
PDF pdf = new PDF(pdfFile);
assertThat(pdf, containsText("PP028004"));
assertThat(pdf, containsText("Торговый терминал"));
assertThat(pdf, containsTextCaseInsensitive("VeriFone VX 810"));
}
Проверить pdf и xls можно с помощью:
- github.com/codeborne/pdf-test
- github.com/codeborne/xls-test
Он умеет:
По умолчанию он отключен так как если тесты запускаются на машине A а браузер на машине B и с машины B не видна машина A, то могут быть проблемы.
@Before
public void setUp() {
Configuration.proxyEnabled = true;
open("https://google.com");
}
@Test
void canAddInterceptorsToProxyServer() {
SelenideProxyServer proxy = getSelenideProxy();
proxy.addRequestFilter("proxy-usages.request", (request,
contents, messageInfo) -> {
String url = messageInfo.getUrl();
log(url + "nn" + contents.getTextContents());
return null;
});
}
Проблемы которые могут возникать:
Лучше запускать тесты в N процессов(forks).
pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkCount>3</forkCount>
<reuseForks>true</reuseForks>
</configuration>
</plugin>
test {
maxParallelForks = 5
}
void setDateByName(String name, String date) {
executeJavaScript(
String.format("$('[name=\"%s\"]').val('%s')",
name, date));
}
@Test {
setDateByName("recurrent.startDate", "16.01.2009");
}
void selectBS(WebElement select, String value) {
executeJavaScript(
"$(arguments[0]).val(arguments[1]).trigger('change')",
select, value);
}
@Test {
selectBS($(By.name("operationCode")), "11100");
}
void setMaxYearlyFee(int value) {
executeJavaScript(
"$('#sld').data('slider').value[0] = arguments[0];" +
"$('#sld').triggerHandler('slide');"
);
}
@Test {
setMaxYearlyFee(100);
}
public static void mockConfirm() {
executeJavaScript(
"window.confirm = function() {return true;};"
);
}
Эмуляция функции.
private void mockCordovaContactsAPI(String number) {
executeJavaScript(
"window.plugins = {" +
" contactNumberPicker: { " +
" pick: function(callback) {" +
" callback({" +
" phoneNumber:\"" + number + "\"""
});}}}");
}
@Test {
mockCordovaContactsAPI("+79110080075");
}
Селениум не умеет искать по jquery локатору.
@Test {
$$(".offer:visible").shouldHave(size(3));
}
@Test {
$$(".offer").filter(visible) .shouldHave(size(3));
} // это может быть медленно если на странице много элементов
Через JavaScript в разы быстрее:
int sizeOf(String cssSelector) {
Number count = executeJavaScript(
"return $(arguments[0]).length", cssSelector);
return count.intValue();
}
@Test {
assertEquals(1, sizeOf(".offer:visible"));
}
Задача: найти страны из excel и страны на странице и найти те которые есть на странице но нет в excel.
List<String> страныИзЭксельки = ...;
List<String> страныСоСтраницы = $$(“td:nth-child(3)”)
.excludeWith(text(“text”))
.stream()
.map(el -> el.getText())
.collect(toList()); // Это м.б. медленно :(
List<String> страныИзЭксельки = ...;
List<String> страныСоСтраницы = executeJavascript(
"return Array.from(" +
" document.querySelectorAll('td:nth-child(3)')"
+ ").map(x => x.textContent)"
); // А вот это быстро
Проблема:
На помощь приходит JavaScript!
Режим “fast set value” - значение не вводится по одному символу, а вставляется сразу через JS.
Для того чтобы включить этот режим нужно:
Установить системную переменную:
mvn -Dselenide.fastSetValue=true
или
Вызвать метод:
@Before public void setUp() {
Configuration.fastSetValue = true;
}
В этом случае setValue функция начинает работать через JS.
Такде в любой момент можно выбирать:
Имеем функцию для установки значения слайдера:
@Test {
setMaxYearlyFee($(“#slider”), 100);
}
void setMaxYearlyFee(WebElement slider, int value) {
executeJavaScript(...);
}
Но вместо этой записи иногда удобнее иметь такую:
@Test {
$(“#slider”).setMaxYearlyFee(100);
}
А ещё круче вот так:
@Test {
$(“#slider”)
.setMaxYearlyFee(100)
.setMinYearlyFee(15)
.selectFee(50)
}
Так можно в Kotlin и Groovy Но не в Java!
Но можно так:
@Test {
$(“#slider”)
.execute(setMaxYearlyFee(100))
.execute(setMinYearlyFee(15))
.execute(selectFee(50))
}
Command<SelenideElement> setMaxYearlyFee(int fee) {
return (proxy, locator, args) -> {
executeJavaScript(".... " + fee);
return proxy;
};
}
См. https://ru.selenide.org/2019/09/02/selenide-5.3.0/
Можно без аннотаций:
@Test public void mobileCalculator() {
$(By.name("2")).click();
$(By.name("+")).click();
$(By.name("4")).click();
$(By.name("=")).click();
$(By.className("android.widget.EditText"))
.shouldHave(text("6"));
}
https://github.com/selenide-examples/selenide-appium
А можно и с аннотациями:
class MobileCalculatorPage {
@AndroidFindBy(id = "op_add")
@iOSFindBy(id = “op_add”);
SelenideElement plus;
}
https://github.com/selenide/selenide-appium
Стандартного браузера нет поэтому нужно задавать класс своего драйвера.
Используется для открытия приложения метод open()
без параметра.
public class CalculatorTest {
@Before
public void setUp(){
Configuration.startMaximized = false;
Configuration.browserSize = null;
Configuration.browser = MyAndroidDriver.class.getName();
open();
}
}
public class MyAndroidDriver implements WebDriverProvider {
@Override
public WebDriver createDriver(DesiredCapabilities caps){
caps.setCapabilities("version" ,"4.4.2");
caps.setCapabilities("automationName" ,"Appium");
caps.setCapabilities("platformName" ,"Android");
caps.setCapabilities("deviceName" ,"0123456789ABCDEF");
caps.setCapabilities("appPackage" ,"com.android.calculator2"); // т.к. калькулятор приложение Android по умолчанию, то достаточно указать только package
caps.setCapabilities("appActivity" ,"com.android.calculator2.Calculator"); // запустится сразу указанное Activity
return new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), caps); // URL запущенного Appium Server
}
}
public class MyIOSDriver implements WebDriverProvider {
@Override
public WebDriver createDriver(DesiredCapabilities caps){
caps.setCapabilities("platformName" ,"iOS");
caps.setCapabilities("deviceName" ,"iPhone 11");
caps.setCapabilities("platformVersion" ,"13.0");
caps.setCapabilities("app", resourcePath("apks/Wikipedia.app"));
caps.setCapabilities(MobileCapabilityType.NEW_COMMAND_TIMEOUT, "16");
caps.setCapabilities("autoAcceptAlerts", true);
return new IOSDriver("http://127.0.0.1:4723/wd/hub", caps); // URL запущенного Appium Server
}
}
class MobileCalculatorPage {
@FindBy(id="op_add")
@AndroidFindBy(id="op-add")
@iOSFindBy(id="operandAdd");
private SelenideElement plus;
}
для инициализации класса для web используется метод page, для mobile метод screen
CalculatorPage calculator = page(CalculatorPage.class);
CalculatorPage calculator = screen(CalculatorPage.class);
calculator.number2.click();
calculator.plus.click();
calculator.number4.click();
calculator.equal.click();
calculator.result.shouldHave(text("6"));