Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

Wagby Testing Framework

3 168 vues

Publié le

WTF (Wagby Testing Framework) overview material.

Publié dans : Logiciels
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Wagby Testing Framework

  1. 1. Wagbyが提供する E2Eテストのための フレームワーク
  2. 2. E2Eテスト • End To End テスト。 • ユーザインタフェーステストと呼ぶこともある。 • ユーザ操作と同じようにWebブラウザを操作し、挙動を確 認する。 • デグレードテストを含む、利用者目線でのテストとしての ニーズがある。 • ユニットテストより(テストコード作成の)難易度は高い。つ まり作成コストも高い。
  3. 3. 誰が用意するのか? • テストシナリオは、業務担当者が用意する必要が ある。 • E2Eテストは「プログラム」である。よってテストプロ グラム自体は、エンジニアが作成する必要がある。
  4. 4. いつテストするのか? • 理想はアプリケーションに変更が発生したタイミン グでの、自動実行。 • ミドルウェアのバージョンアップでも、回帰テストと して、自動実行。 • 自動実行環境 = CI ツールとの連携。 • Continuous Integration
  5. 5. よく知られている E2E テスト作成の知見 • ブラウザ自動操作は Selenium を使う。 • [注] SeleniumはE2Eテストツールではなく、ブラウザ操作の ためのツール。 • Selenium をラップして UI テスト作成に特化したフレー ムワークを使う。 • Selenide なら、Java で UI テストを作成できる。 • 他にも JavaScript ベースのフレームワークいろいろ。
  6. 6. Selenium の例 public static void main(String[] args) { WebDriver driver = new ChromeDriver(); driver.get(“http://localhost:8080/index.html"); driver.findElement(By.cssSelector("input[name=¥"organization¥"]")) .sendKeys("ジャスミンソフト"); driver.findElement(By.cssSelector("input[name=¥"name¥"]")) .sendKeys(“ジャスミン太郎); driver.findElement(By.cssSelector("input[name=¥"dept¥"]")) .sendKeys("営業部"); driver.findElement(By.cssSelector("input[name=¥"title¥"]")) .sendKeys(“なし); driver.findElement(By.cssSelector("input[name=¥"tel¥"]")) .sendKeys("000-111-2222"); driver.findElement(By.cssSelector("input[name=¥"mailaddress¥"]")) .sendKeys("taro@example.com"); driver.findElement(By.cssSelector("input[name=¥"agreement¥"]")) .click(); driver.findElement(By.id(“apply”)).click(); driver.close(); }
  7. 7. Selenide の例 • jQuery ライクな記述で、Seleniumよりも簡潔なコードが書ける。 public static void main0(String[] args) { open(“http://localhost:8080/index.html"); $("input[name=¥"organization¥"]").val("ジャスミンソフト"); $(“input[name=¥”name¥“]”).val(“ジャスミン太郎); $("input[name=¥"dept¥"]").val("営業部"); $(“input[name=¥”title¥“]”).val(“なし); $("input[name=¥"tel¥"]").val("000-111-2222"); $("input[name=¥"mailaddress¥"]").val("taro@example.com"); $("input[name=¥"agreement¥"]").click(); $("#apply")).click(); }
  8. 8. 課題 JavaScriptフレームワークとの連携 • Selenium/Selenideいずれも、標準HTML要素を使うだ けなら簡単に利用できる。 • しかし今日のWebアプリケーションはリッチな JavaScriptフレームワークを使うことが多い。(Wagbyは Dojotoolkitを使う。) • 一般にHTMLが複雑で、spanの入れ子になっている。 • このためセレクタの指定が行い難い。
  9. 9. Dojotoolkitのボタンの例 <div class="action_button"> <span class="..." role="presentation" widgetid="btnSend"> <span class="..." data-dojo-attach-event="ondijitclick:__onClick" role="presentation"> <span class="..." role="button" id="btnSend" style="user-select: none;"> <span class="..." data-dojo-attach-point="iconNode"></span> <span class="...">●</span> <span class=“...” id=“btnSend_label”>保存</span> </span> </span> <input name="btnSend" type="button" value="" class="..."> </span> </div> 保存ボタンのHTML <button id=“btnSend” data-dojo-type=“dijit/form/Button” type=“button” name=“btnSend”> 保存 </button>
  10. 10. Dojotoolkit + Selenide の例 //開始時刻の選択。「6:30」を指定する。 //時間の選択。STEP1:▼をクリックしてプルダウンを表示 $("#customer_p¥¥$002fstart_hour") .find(byValue("▼ ")).click(); //時間の選択。STEP2:プルダウンから時間を選ぶ $$("#customer_p¥¥$002fstart_hour_menu td") .filter(exactText("6")).first().click(); //分の選択 $("#customer_p¥¥$002fstart_minute") .find(byValue("▼ ")).click(); $$("#customer_p¥¥$002fstart_minute_menu td") .filter(exactText("30")).first().click(); 時間型リストボックス
  11. 11. Wagby Testing Framework • Wagby テストに特化したフレームワーク。 • E2Eテストの作成から自動実行までをサポート。 • ベースは Selenide。 • Wagbyが生成した HTML 構造を前提に、Dojotoolkit の記述方式をラップする。 • PageObjectパターンを進化させた記述方法を提供する。[後述] • 必要なもの。 • Wagby。 • Eclipse。 • Google Chrome 用の WebDriver。
  12. 12. はじめてのテストクラス [1] /** テストの前処理を行います。 */ @BeforeClass public static void setUpBeforeClass() { Configuration.baseUrl = "http://localhost:8921/wagby"; // 利用するブラウザ Configuration.browser = WebDriverRunner.CHROME; // Selenium(WebDriver) 用ドライバファイル System.setProperty("webdriver.chrome.driver", "customize/chromedriver.exe"); } • JUnitテストクラスとして作成 • ソースフォルダ : customize/test/java • パッケージ名及びファイル名は任意。 • setUpBeforeClass()でselenide用の初期設定を記述
  13. 13. はじめてのテストクラス [2] • test()メソッドにテストを記述する。 • 多用するクラスは事前に import を記述しておく。 import static com.codeborne.selenide.CollectionCondition.*; import static com.codeborne.selenide.Condition.*; import static com.codeborne.selenide.Selenide.*; import static jp.jasminesoft.jfc.test.support.selenide.Operations.*; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; … @Test public void test01_シンプルなテスト() { logon("admin", "wagby"); // ログオン処理を行う。 pageTitle().shouldHave(exactText("メニュー")); // ページタイトルを確認 logoff(); // ログオフ処理を行う。 // HTMLのタイトルを確認 assertThat(title(), is("Wagby アプリケーション ログオン")); }
  14. 14. Page Object パターン • 1つの「画面(ページ)」をクラス化する。 • ページの構造(HTML要素)は、ページオブジェクトに押し 込める。 • テストコードは、このページを操作するようになる。 • WTFはさらにこれを発展させた。 • ページ内に用意される「モデル」の「項目」の型や入力 ルールは、すでにわかっている。 • モデルを操作することでテストコードを書けるのがもっと も理想的。
  15. 15. 顧客モデルのテスト [1] public class Customer extends WebModel { public Customer() { super("customer"); } /* customer/id */ public final WebModelitem<?> id = new WebModelitem<>(this, "id"); /* customer/name */ public final WebModelitem<?> name = new WebModelitem<>(this, "name"); /* customer/phone */ public final WebModelitem<?> phone = new WebModelitem<>(this, "phone"); /* customer/address */ public final WebModelitem<?> address = new WebModelitem<>(this, "address"); } • WebModel, WebModelitem は WTF が提供するクラス。 • id, name などは Wagby で設計した項目名をそのまま使う。
  16. 16. 顧客モデルのテスト [2] @Test public void test03_InsertCustomer() { selectMenu("サービス", "顧客検索"); pageTitle().shouldHave(exactText("顧客情報 検索")); clickNewButton(); pageTitle().shouldHave(exactText("顧客情報 新規登録")); Customer customer = new Customer(); customer.name.val("ジャスミン太郎"); customer.phone.val("090-9999-8888"); customer.address.val("宜野湾市宇地泊902-1"); save(); pageTitle().shouldHave(exactText("顧客情報 詳細表示")); } • selectMenu, clickNewButton, save は WTF が提供するメソッド。 • 画面からの入力操作を、モデルオブジェクトの操作として実現。この記述で実際に Web ブラウザからの入力が行われる。HTMLのノードを選択するコードは見えない。 (セレクタ、ロケータを意識しない。)
  17. 17. valメソッド/shouldHaveメソッド 項目への入力 : val() メソッド 入力値の確認 : shouldHave() メソッド // モデルの情報を保持するインスタンス WebModel model = new WebModel("customer"); // customerモデルのname項目への入力 new WebModelitem<>(model, "name").val("ジャスミン太郎"); // 「ジャスミン太郎」と入力されていることを確認 new WebModelitem<>(model, "name").shouldHave("ジャスミン太郎");
  18. 18. リストボックス ListBoxクラスを利用 通常項目と同様に val() メソッドでも 値のセットは可能。 // リストボックス:「地方公共団体」を選択する new ListBox(model, "customertype") .dropdown() .select("地方公共団体"); // こちらでも可(内部処理は同じ) new ListBox(model, "customertype") .val("地方公共団体"); リストボックス
  19. 19. ラジオボタン、チェックボックス それぞれの型に応じたクラスを利用 // ラジオボタン:「地方公共団体」を選択する new RadioButton(model, "customertype").val("地方公共団体"); // チェックボックス:「民間企業」と「地方公共団体」を選択する // チェックボックスは複数の値の指定が可能 new CheckBox(model, "customertype") .val("民間企業", "地方公共団体"); ラジオボタン
  20. 20. DatePickerも操作できる // DatePickerを操作するオブジェクトを取得する DatePicker datePicker = new DateTextBox(model, "startdate").datePicker(); datePicker.nextMonth(); // 翌月へ datePicker.prevMonth(); // 前月へ datePicker.nextYear(); // 翌年へ datePicker.prevYear(); // 前年へ datePicker.selectDate(1); // 1日を選択
  21. 21. Wagbyがサポートする入力をカバー val() で入力、shouldHave()で確認という統一操作 項目の種類 対応するJavaクラス 入力フィールド WebModelitem リストボックス ListBox ラジオボタン RadioButton チェックボックス CheckBox 検索画面(サブウィンドウ) SearchList 日付入力フィールド(DatePicker) DateTextBox 日付リストボックス DateListBox 時間リストボックス TimeListBox 追記型リストボックス ComboBox 郵便番号 Postcode 繰返し項目 WebMultiModelitem
  22. 22. Operationsクラス メソッド名 処理内容 save() 「保存」ボタンをクリックする。 cancel() 「キャンセル」ボタンをクリックする。 clickButton(“ボタン表示名”) 指定のボタンをクリックする。 clickNewButton() 「登録画面へ」ボタンをクリックする。 clickEditButton() 「更新画面へ」ボタンをクリックする。 clickDeleteButton() 「削除」ボタンをクリックする。 clickCopyButton() 「コピー登録へ」ボタンをクリックする。 clickSearchPageButton() 「検索画面へ」ボタンをクリックする。 pageTitle() ページタイトルを取得する。 search() 検索画面の「検索の実行」ボタンをクリックする。 selectMenu(“タブ名”, “メニュー名”) 指定のメニューを選択する。
  23. 23. 異常系のテスト import static com.codeborne.selenide.CollectionCondition.*; … // 複数エラーメッセージの完全一致チェック。 errors().shouldHave(exactTexts( "エラーメッセージ01", "エラーメッセージ02", "エラーメッセージ03")); // 複数エラーメッセージの部分一致チェック。 errors().shouldHave(texts( "メッセージ01", "メッセージ02", "メッセージ03"));
  24. 24. ワークフローのテスト workflow().participants_id.val("年休申請フロー"); // 申請状況一覧の1行目のデータを確認。 JfcworkstateLp record01 = workflow().getWorkstate(1); record01.username.shouldHave("申請ユーザー"); // 処理者 record01.event.shouldHave(“新規登録”); // 処理内容 record01.comment.shouldHave(empty); // コメント workflow().comment.val("年休申請します。"); // コメント workflow().application(); // 申請ボタンをクリック。
  25. 25. その他の特徴 • E2Eテストコードは高度に抽象化されている。 例 Wagby R8.1.0 で、郵便番号から住所を求めるインタ フェースが Ajax 化された。これによってHTMLの出力が変 わったが、WTFがこの変化を吸収したため、テストコードは そのまま利用できた。 • スクリーンキャプチャなど、Selenideが提供する機能 はそのまま使える。
  26. 26. テスト開発者からの視点 • Selenium/Selenideは自由度が高いゆえに… 開発者によって異なるテストコードを書けてしまう。 大規模アプリケーションでは、標準化のためのルールを別 途、定める必要があるのではないか。 • WTFの提供するWebModelクラスは形式が定まって いる。 そのため自由度が抑えられ、安定したテストコードを少な い記述量で実装できる。 大規模アプリケーションに向いている。
  27. 27. まとめ • WTFは業務アプリケーションに特化したE2Eテストコードの理 想を追求したものになっている。 • CIツールとの連携により、自動ビルド、自動回帰テストを毎 日行うことが可能になった。 • E2Eテストにより、Windowsやブラウザの自動アップデートの 影響を把握しやすくなる。パブリッククラウドのような PaaS 環境では Java やミドルウェアもアップデートするが、これに も対応できるようになる。

×