領域特定語言

領域特定語言 (DSL) 是一種系統,它為使用者提供了解決問題的表達方式。 它允許使用者以他們的方式與系統互動,而不僅僅是程式設計師的語言。

一般來說,您的使用者不在意您的網站外觀如何。 他們不在意裝飾、動畫或圖形。 他們希望使用您的系統,以便讓他們的新員工能夠輕鬆地完成流程;他們想要預訂前往阿拉斯加的旅行;他們想要以折扣價配置和購買獨角獸。 作為測試人員,您的工作是盡可能地「捕捉」這種心態。 考慮到這一點,我們著手「建模」您正在開發的應用程式,以便測試腳本(使用者唯一的預發布代理)能夠「代表」使用者發聲和呈現使用者的需求。

目標是使用通用語言。 應該可以使用諸如「建立新帳戶」或「按名稱排序顯示結果」之類的語言,而不是使用「將資料載入到此表格」或「點擊第三列」。

對於 Selenium,DSL 通常以方法表示,編寫這些方法的目的是使 API 簡單易讀——它們在開發人員和利害關係人(使用者、產品負責人、商業智慧專家等)之間建立了一份報告。

優點

  • 可讀性: 業務利害關係人可以理解它。
  • 可寫性: 易於編寫,避免不必要的重複。
  • 可擴展性: 功能可以(合理地)新增,而不會破壞合約和現有功能。
  • 可維護性: 透過將實作細節排除在測試案例之外,您可以很好地防止 AUT* 的變更影響。

延伸閱讀

(先前位置: https://github.com/SeleniumHQ/selenium/wiki/Domain-Driven-Design)

這裡有一本關於 Eric Evans 撰寫的領域驅動設計的好書 http://www.amazon.com/exec/obidos/ASIN/0321125215/domainlanguag-20

為了激發您的興趣,這裡有一本有用的較小書籍可線上免費下載 http://www.infoq.com/minibooks/domain-driven-design-quickly

Java

以下是 Java 中合理的 DSL 方法範例。 為了簡潔起見,它假設 driver 物件已預先定義且可供該方法使用。

/**
 * Takes a username and password, fills out the fields, and clicks "login".
 * @return An instance of the AccountPage
 */
public AccountPage loginAsUser(String username, String password) {
  WebElement loginField = driver.findElement(By.id("loginField"));
  loginField.clear();
  loginField.sendKeys(username);

  // Fill out the password field. The locator we're using is "By.id", and we should
  // have it defined elsewhere in the class.
  WebElement passwordField = driver.findElement(By.id("password"));
  passwordField.clear();
  passwordField.sendKeys(password);

  // Click the login button, which happens to have the id "submit".
  driver.findElement(By.id("submit")).click();

  // Create and return a new instance of the AccountPage (via the built-in Selenium
  // PageFactory).
  return PageFactory.newInstance(AccountPage.class);
}

此方法完全從您的測試程式碼中抽離了輸入欄位、按鈕、點擊甚至頁面的概念。 使用這種方法,測試人員只需呼叫此方法即可。 這為您帶來了維護優勢:如果登入欄位發生變更,您只需變更此方法,而無需變更您的測試。

public void loginTest() {
    loginAsUser("cbrown", "cl0wn3");

    // Now that we're logged in, do some other stuff--since we used a DSL to support
    // our testers, it's as easy as choosing from available methods.
    do.something();
    do.somethingElse();
    Assert.assertTrue("Something should have been done!", something.wasDone());

    // Note that we still haven't referred to a button or web control anywhere in this
    // script...
}

值得重申的是:您的主要目標之一應該是編寫一個 API,讓您的測試能夠解決手邊的問題,而不是 UI 的問題。 UI 是使用者的次要考量——他們不在意 UI,他們只想完成他們的工作。 您的測試腳本應該讀起來像使用者想要做的事情和他們想要知道的事情的清單。 測試不應關心 UI 如何要求您執行此操作。

*AUT:受測應用程式

上次修改時間 2021 年 12 月 13 日: 將 Wiki 內容移至文件 (#877) [部署網站] (aa6066432f5)