Java Selenide 介紹&使用

Juno3550發表於2022-01-20


Selenide 介紹

image

Selenide 是對 Selenium 的一個封裝,其語法更加簡單。其優點如下:

  • 程式碼簡單、易讀
  • 內建隱式等待(無需考慮元素的等待時間)
  • 用例執行完後自動關閉瀏覽器
  • 自動對失敗用例截圖
  • 由於是對 Selenium 的封裝,所以可以和 Selenium 一起使用
  • ...

Selenide 的團隊自詡它是一個測試工具而不是一個測試框架,因為它只是 Webdriver 的一個封裝(目前只有 Java 版本),其底層的實現還是 Webdriver。所以他們認為並沒有偉大到開發了一個測試框架,而僅僅是個測試工具(很謙虛的說)。

所以一切 Webdriver 能做的,Selenide 都能做。Webdriver 做不到的,也別指望 Selenide 能做到。

就像團隊人員說的“Selenide is just a wrapper”,如果你不想使用 Selenide 了,或者 Selenide 滿足不了你的需要,你大可以通過以下方式獲取一個 Webdriver,直接操作 Webdriver 的 API 。

driver = WebDriverRunner.getWebDriver();

所以如果有小夥伴擔心這個新興的工具沒有強大到滿足你的專案需求怎麼辦?大可以放心,最壞的情況也就是直接用 Webdriver 去做就好了。


官方快速入門

Maven 依賴

  • 不同版本的 Selenide 所相容的 selenium 版本不同(如 Selenide 5 對應 selenium 4)。
  • 不同版本的 Selenide 所預設支援的瀏覽器版本範圍也不同。
        <dependency>
            <groupId>com.codeborne</groupId>
            <artifactId>selenide</artifactId>
            <version>5.25.1</version>
        </dependency>

測試程式碼

@Test
public void testBaiduSearch() {
   open("https://www.baidu.com");
   $(By.name("username")).setValue("johny");
   $("#submit").click();
   $(".success-message").shouldHave(text("Hello, Johny!"));
}

前面說了 Selenide 致力於封裝更簡單好用的 API,所以開啟和關閉瀏覽器這些東西它都幫你做好了。

Selenide 預設使用 Firefox 瀏覽器,如果你要使用其他瀏覽器可以手動設定:

Configuration.browser="chrome";
// 如果預設chrome版本不相容,可以在環境變數中設定 chrome 瀏覽器的路徑
System.setProperty("webdriver.chrome.driver", Constant.getChromeDriverPath());
// 手動設定 chrome 瀏覽器的路徑
System.setProperty("webdriver.chrome.driver", "e:\\chromedriver.exe");

元素定位

Selenide 使用$符號定位一個元素,使用 IDEA 時只要輸入“$(by”就可以通過程式碼提示來找到我們想要的方法。如下圖:

image

// $ 符號預設引數是 CSS 定位表示式,返回 SelenideElement 類的物件,SelenideElement 繼承 WebElement,該物件表示頁面上 CSS 選擇器找到的第一個元素
$(String cssSelector)

// 輸出的元素: "<option value=livemail.ru checked=true selected:true>@livemail.ru</option>"
System.out.println($("#customerContainer"));

// 通過元素 id 定位
$("#id")
$(byId("id"))

// 通過 class 定位
$(".className")
$(byClassName(".className"))

// 通過 name 定位
$(byName("name"))

// 通過 text 定位。如果使用 selenium 的話只能用小 path 的寫法,如 driver.findElementByXpath(“//*[text()=‘Sign in’]”)
$(byText("Sign in"))

// 通過Xpath定位
$(byXpath("//*[text()='Sign in']"))

// 通過元素的屬性定位
$(byAttribute("placeholder", "房源編號"))

// $$ 用於定位一組元素(返回 ElementsCollection 型別的元素集合),且可以再在集合中繼續定位元素
$$("#search-results a").findBy(text("selenide.org"))

元素操作

元素操作

click()  // 點選
doubleClick()  // 雙擊
contextClick()
hover()
setValue(String)/val(String)  // 文字輸入
pressEnter()  // Enter鍵
pressEscape()
pressTab()
selectRadio(String value)
selectOption(String)
append(String)
dragAndDropTo(String)

獲取元素狀態和屬性值

getValue()/val()
data()
attr(String)
text()  // 返回頁面上的可見文字
innerText()  // 返回 DOM 中元素的文字
getSelectedOption()
getSelectedText()
getSelectedValue()
isDisplayed()  // 如果元素被隱藏(不可見)或者 DOM 中不存在元素,則返回 false
exists()  // 如果 DOM 中存在元素,則返回 true

瀏覽器操作

// 開啟瀏覽器(如果尚未開啟)並載入URL
open(String URL);

// 切換瀏覽器視窗
switchTo().window(1);

// 重新整理
refresh();

// 執行緒等待
sleep();

// 操作 alert
confirm();  // 確定 alert
confirm("exceptionText");  // 判斷alert的文字是否是期望的那個,如果是則接收 alert
dismiss();  // 取消 alert

斷言

Selenide 通過 should 來進行斷言,相當於 Assert 。

示例如下:

$("input").should(exist);  // 驗證元素應該存在

$("input").shouldBe(visible);  // 驗證元素應該可見

$("input").shouldHave(exactText("Some text"));  // 驗證元素的 text 是否包含 Some text

$("input").shouldHave(value("John"));  // 驗證元素的 value 屬性等於 John

$("#input").shouldHave(id("myForm"));  // 驗證元素的 id 屬性等於 myForm

$("#btn-Search").shouldHave(text("搜尋"));  // 驗證元素是否包含“搜尋”文字

$("#btn-Search").shouldNotHave(text("搜尋"));  // 驗證元素不包含“搜尋”文字

$("#customerContainer").should(matchText("profile"));  // 使用正規表示式:是否包含“profile”文字

還可以使用斷言來做顯示等待,等待的狀態(visible、enabled、text(“some text”))是否滿足,直到超時達到的值(預設設定為 4000 毫秒),例如:

$("#submit").shouldBe(enabled).click();

還可以明確設定超時:

waitUntil(條件, 毫秒)
waitWhile(條件, 毫秒)

常用配置

// 把 webDriver 傳給 selenide
setWebDriver(driver);

// 獲取當前 driver
WebDriverRunner.getWebDriver();

// 設定瀏覽器執行完不關閉
Configuration.holdBrowserOpen = true;

// 修改報告預設生成路徑
Configuration.reportsFolder = "target/reports/test"+Configuration.browser;

// 設定遠端伺服器(如selenium Grid Hub)
Configuration.remote = "http://xxxxxxx";

// selenide 預設使用 Firefox 瀏覽器,可以手動設定使用其他瀏覽器
System.setProperty("webdriver.chrome.driver", chromeDriverPath);
Configuration.browser = "chrome";

// selenide 自動對於失敗用例進行截圖,預設儲存在 build/report 裡面

Selenide 和 Webdriver 對比

建立 webdriver 的方式

// webdriver
DesiredCapabilities desiredCapabilities = DesiredCapabilities.htmlUnit();
desiredCapabilities.setCapability(HtmlUnitDriver.INVALIDSELECTIONERROR, true);
desiredCapabilities.setCapability(HtmlUnitDriver.INVALIDXPATHERROR, false);
desiredCapabilities.setJavascriptEnabled(true);
WebDriver driver = new HtmlUnitDriver(desiredCapabilities);

// selenide
open("/my-application/login");

Selenide 直接在open 這個 API 裡就啟動瀏覽器了,當測試結束時就會關閉瀏覽器。


查詢頁面元素

// webdriver
WebElement customer = driver.findElement(By.id("customerContainer"));

// selenide
WebElement customer = $(By.id("customerContainer"));

這方面倒沒有什麼特別簡化的,但是 selenide 有其他更靈活的方式搜尋控制元件,例如 byText、byValue 等等,這些在 webdriver 中除非用 xpath,否則是做不到的。

// selenide
WebElement customer = $(byText("Customer profile"));
WebElement temp = $(byValue("不使用")).click();
WebElement temp1 = $(byAttribute("data-name",“test name”)).click();

再看看下面一個,如果返回多個元素,取其中一個:

// webdriver
driver.findElements(By.tagName("li")).get(5);

// selenide
$("li", 5);  // 取一個元素:取所有標籤為li的元素中的第5個
$$("#multirowTable tr").filterBy(text("Norris"));  // 取一個集合:取特定的集合後再去搜尋text為期望值的元素

斷言控制元件

// webdriver
assertEquals("Customer profile", driver.findElement(By.id("customerContainer")).getText());

// selenide
$("#customerContainer").shouldHave(text("Customer profile"));

Selenide 提供一系列 should 標籤幫我們做斷言的工作,而且有一批text()的這種選擇器來幫助我們斷言各種型別。上面的例子就是斷言控制元件是否有期望的 text 。

Selenide 專門有一個 condition 包,裡面有各種各樣的 condition,這些 condition 就是 should 標籤的引數。上面的例子 text 就是一個 condition,其他的還有 id、value、attribute、readonly 等等。


等待控制元件

有些時候為了增加穩定性,我們需要增加等待一個控制元件出現的機制。因為控制元件可能不是立刻出現的,或者說等待一個控制元件的某個屬性變成一個特定值。

// webdriver
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"));

// selenide
$("TEXTAREA").shouldHave(value("John"));

可以看到 Selenide 一個 should 的 API 搞定了。它預設 4s 超時,4s 內會迴圈 check 控制元件的 value 是否變成了期望值。同樣的還有 text、attribute 等選擇器。


正規表示式

// webdriver
WebElement element = driver.findElement(By.id("customerContainer"));
assertTrue(Pattern.compile(".*profile.*", DOTALL).matcher(element.getText()).matches());

// selenide
$("#customerContainer").should(matchText("profile"));

關於 alert

// webdriver
try {
     Alert alert = checkAlertMessage(expectedConfirmationText);
     alert.accept();
   } catch (UnsupportedOperationException alertIsNotSupportedInHtmlUnit) {
     return;
   }
   Thread.sleep(200); // sometimes it will fail

// selenide
confirm("Are you sure to delete your profile?");
// 或者
dismiss("Are you sure to delete your profile?");

相關文章