最近做 UI 自动化,看到有人推荐 Selenide。于是试了试,确实好用,通过阅读部分代码和官方文档,看到了一些功能,正好总结总结。
通过 SelenideConfig 类我们可以看到 Selenide 支持的一些配置以及这些配置的默认值。
比如:浏览器,支持 headless,浏览器大小/版本,浏览器最大化,代理,通过 js 点击,baseUrl,超时等等。
private String browser = System.getProperty("selenide.browser", CHROME);
private boolean headless = Boolean.parseBoolean(System.getProperty("selenide.headless", "false"));
private String remote = System.getProperty("selenide.remote");
private String browserSize = System.getProperty("selenide.browserSize", "1366x768");
private String browserVersion = System.getProperty("selenide.browserVersion");
private String browserPosition = System.getProperty("selenide.browserPosition");
private boolean startMaximized = Boolean.parseBoolean(System.getProperty("selenide.startMaximized", "false"));
private boolean driverManagerEnabled = Boolean.parseBoolean(System.getProperty("selenide.driverManagerEnabled", "true"));
private String browserBinary = System.getProperty("selenide.browserBinary", "");
private String pageLoadStrategy = System.getProperty("selenide.pageLoadStrategy", "normal");
private DesiredCapabilities browserCapabilities = new DesiredCapabilities();
private String baseUrl = System.getProperty("selenide.baseUrl", "http://localhost:8080");
private long timeout = Long.parseLong(System.getProperty("selenide.timeout", "4000"));
private long pollingInterval = Long.parseLong(System.getProperty("selenide.pollingInterval", "200"));
private boolean holdBrowserOpen = Boolean.getBoolean("selenide.holdBrowserOpen");
private boolean reopenBrowserOnFail = Boolean.parseBoolean(System.getProperty("selenide.reopenBrowserOnFail", "true"));
private boolean clickViaJs = Boolean.parseBoolean(System.getProperty("selenide.clickViaJs", "false"));
private boolean screenshots = Boolean.parseBoolean(System.getProperty("selenide.screenshots", "true"));
private boolean savePageSource = Boolean.parseBoolean(System.getProperty("selenide.savePageSource", "true"));
private String reportsFolder = System.getProperty("selenide.reportsFolder", "build/reports/tests");
private String reportsUrl = new CiReportUrl().getReportsUrl(System.getProperty("selenide.reportsUrl"));
private boolean fastSetValue = Boolean.parseBoolean(System.getProperty("selenide.fastSetValue", "false"));
private boolean versatileSetValue = Boolean.parseBoolean(System.getProperty("selenide.versatileSetValue", "false"));
private SelectorMode selectorMode = CSS;
private AssertionMode assertionMode = STRICT;
private FileDownloadMode fileDownload = FileDownloadMode.valueOf(System.getProperty("selenide.fileDownload", HTTPGET.name()));
private boolean proxyEnabled = Boolean.parseBoolean(System.getProperty("selenide.proxyEnabled", "false"));
private String proxyHost = System.getProperty("selenide.proxyHost", "");
private int proxyPort = Integer.parseInt(System.getProperty("selenide.proxyPort", "0"));
Selenide 的打开浏览器特别简单,如下:
public static void open(String relativeOrAbsoluteUrl) ;
public static void open(String relativeOrAbsoluteUrl, String domain, String login, String password);
public static void open(String relativeOrAbsoluteUrl, AuthenticationType authenticationType, String login, String password);
public static void open(String relativeOrAbsoluteUrl, AuthenticationType authenticationType, Credentials credentials)
从以上方法可以看出 Selenide 支持 打开绝对路径或者相对路径的 url,以及支持基本验证的方式打开 url。
Selenide 和 Selenium 主要支持的元素定位方式相同。
和 Selenium 相似的:byName, byXpath, byLinkText, byPartialLinkText, byId, byCssSelector, byClassName 等。
Selnide 自己封装的:withText, byText,byAttribute, byTitle,byValue 等。
什么是软断言呢?软断言是硬断言的反义词。哈哈。那什么是硬断言呢?
硬断言:如果有多个断言,一旦一个断言失败,那么它之后的断言都不会执行。
软断言:如果有多个断言,如果一个断言失败,那么它之后的断言仍然会执行。
看看 TestNg 的例子:
@Listeners({ SoftAsserts.class})
public class Tests {
@Test
public void test() {
Configuration.assertionMode = SOFT;
open("page.html");
$("#first").should(visible).click();
$("#second").should(visible).click();
}
}
针对上面的测试测试用例,有两种结果
硬断言的测试结果:
Element not found {#first}
Expected: visible
Screenshot: file://build/reports/tests/1536060081565.0.png
Page source: file://build/reports/tests/1536060081565.0.html
Timeout: 4 s.
Caused by: NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#first"}
软断言的测试结果:
FAIL #1: Element not found {#first}
Expected: visible
Screenshot: file://build/reports/tests/1536060329615.0.png
Page source: file://build/reports/tests/1536060329615.0.html
Timeout: 4 s.
Caused by: NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#first"}
FAIL #2: Element not found {#second}
Expected: visible
Screenshot: file://build/reports/tests/1536060334390.1.png
Page source: file://build/reports/tests/1536060334390.1.html
Timeout: 4 s.
Caused by: NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#second"}
详见 SelenidePageFactory 类。
先看一个官方的一个例子
$(".username").shouldHave(text("John"));
Selenide 以 “should” 开头的方法都会等待元素的出现,默认是 4s(时间可以通过 Config 设置)。我们再来看看它的代码实现,Selnide 以 should 开头的方法都调用了 waitUntil 的方法,下面是 waitUntil 的代码
protected void waitUntil(CollectionCondition condition, long timeoutMs) {
Exception lastError = null;
List<WebElement> actualElements = null;
Stopwatch stopwatch = new Stopwatch(timeoutMs);
do {
try {
actualElements = collection.getElements();
if (condition.apply(actualElements)) {
return;
}
}
catch ...
}
sleep(driver().config().pollingInterval());
}
while (!stopwatch.isTimeoutReached());
condition.fail(collection, actualElements, lastError, timeoutMs);
}
通过 do...while 语句,当时间在 timeout 时间范围内,selenide 会不断重试。
Selenide 的东西还有很多,暂时写这么多吧。欢迎用过的小伙伴也 提出来你发现的 Selenide 的亮点哈。