ドメイン固有言語
ドメイン固有言語 (DSL) は、ユーザーに問題を解決するための表現力豊かな手段を提供するシステムです。これにより、ユーザーはプログラマー用語だけでなく、自分の言葉でシステムと対話できます。
一般的に、ユーザーはサイトがどのように見えるかを気にしません。装飾、アニメーション、グラフィックには関心がありません。彼らはあなたのシステムを使って、新しい従業員を最小限の困難でプロセスを進めたいと思っています。アラスカへの旅行を予約したいと思っています。割引価格でユニコーンを構成して購入したいと思っています。テスターとしてのあなたの仕事は、この考え方を「捉える」ことにできるだけ近づくことです。それを念頭に置いて、テストスクリプト (ユーザーにとって唯一のリリース前のプロキシ) がユーザーを「代弁」し、ユーザーを代表するように、作業中のアプリケーションを「モデル化」することに着手します。
目標は、ユビキタス言語を使用することです。「このテーブルにデータをロードする」または「3 番目の列をクリックする」と言うのではなく、「新しいアカウントを作成する」または「表示された結果を名前で並べ替える」のような言葉を使用できるようにする必要があります。
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...
}
繰り返しますが、あなたの主要な目標の 1 つは、テストがUI の問題ではなく、当面の問題に対処できるようにする API を作成することである必要があります。UI はユーザーにとって二次的な関心事です。ユーザーは UI を気にせず、仕事を終わらせたいだけです。テストスクリプトは、ユーザーがやりたいこと、知りたいことのリストのように読む必要があります。テストは、UI がそれをどのように行う必要があるかに関与すべきではありません。
*AUT: テスト対象アプリケーション