领域特定语言

领域特定语言 (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)