JaSSTソフトウェアテストシンポジウム-JaSST'15 Tokyo より
はじめに
JaSST'15のセッションの一つ『テストコードクリニック』に参加してきました。
このセッションでは、スライドに載っていない部分であるデモで多くの時間を割いていたので、そのデモでの修正方法なども紹介します。(記事の後半)
発表スライド
自己紹介
太田健一郎
プロセス改善などもやっている
Selenium Design Patterns and Best Practices
自動テストソフトウェアのアーキテクチャ
詳しくはシステムテスト自動化標準ガイド(ギア本)に載ってる
システムテスト自動化 標準ガイド CodeZine BOOKS
- 作者: Mark Fewster,Dorothy Graham
- 出版社/メーカー: 翔泳社
- 発売日: 2014/12/17
- メディア: Kindle版
- この商品を含むブログ (1件) を見る
あるある残念なコード
今回のサンプルは、商品のAdd Cartやコメントができるサイト
ただし、短時間に同じ内容コメントは投稿できない(弾く)仕組みになっている
サンプルコードはGithub上にある
dimacus/SeleniumBestPracticesBook · GitHub
今回は、以下の2つのテストケースが対象
- コメントを書き込む
- コメントを連続で書き込んで、弾かれる
修正前の時点のテストコードでは、以下のような問題点がある
- 同じテストケースを2回行うとテストが死んでしまう
- 1つ目のテストが前提で2つ目が必要になる(人手が介入。メンテナンスコストが高い)
残念なテストコードを生み出すデザインパターン
- アンチパターンはやっちゃいけないパターンではない
- ある時点では有効なものが多い
Record and playback pattern
特徴
利点
- テストコードを素早く作れる
欠点
- ソースコードが分からない限りは難しい
- ロケーターが分かりづらい
- テストデータが固定値(セッションクッキーぐらいだったら可変できるが…)
- テストコードが構造化されていない(コードが1000行ぐらいべたーっと書いてある)
- 重複している(同じデータなども書かれている)
Spaghetti pattern
特徴
- Record and playback patternのほとんどはこのパターンにも含まれる
利点
- テストコード自体が小さくなる
- スモークテストに向いているかもしれない
欠点
- テストコードが構造化されていない
- テストコードに依存関係がある
Chain Linked pattern
特徴
- ロケーターをオブジェクトパターンで隠している
欠点
- テストケース間に依存関係がある
Big Ball of Mud pattern
特徴
- テストコード自体は独立している ・あまり見かけないパターン
欠点
- テストコード全体は構造化されていない
テストコードを改善するデザインパターン
DRY testing pattern
特徴
- 重複を排除している
- SetUpなどを作成する
利点
- テストが失敗するとブラウザが終了しないといったことを無くすことができる
- 同じ動作を行う時のコードを局所化できる。(テストケースでは2回呼べば良い)
欠点
- プログラミングスキルが必要(オブジェクト指向)
Hermetic test pattern
特徴
- 各テストケースを真っさらな状態で返す
- 事前準備はフィクスチャーで整える
利点
- ランダムで実行できる
- 並列実行も可能になる
欠点
- 事前に設計と部品の開発が必要
- テストの実行時間が増加する
- ただし、トータルで見ると、バグを見つける時間が短くなるため、コストダウンに繋がる
Random order principle
特徴
- 常にテストケースをランダム実行する
欠点
更なる改善のために
Data-driven testing
特徴
- 全部のテストデータにデフォルト値を作成しておく
- テストデータに必要なものだけOverRideする
Stabilizing the Tests
Action Wrapper pattern
- 内部的に非同期に動いている部分を隠蔽してあたかも同期して動いているように見せる
Back Hole Proxy pattern
- 広告などによってテストが不安定になることがあるため、テストに必要がないものは表示させないようにする
Testing the Behavior
特徴
- テストシナリオは同じだが、異なるプラットフォームでテストできるようにする
Page Objects Pattern
Growing the Test Suite
デモ
デモで使用したコード
元々のテストコード
- 1回目は成功
- 2回目は失敗
- 失敗すると、ブラウザを終了しない
改善する際に気をつけること
- 1個1個修正したほうが良い
- まとめて修正すると大体コケる
- assertを敢えて間違えても正しく終了するか確認する
- assertionの目的を明らかにする (例えば、画面遷移ができたこととコメントが正しく投稿できたことを同じテストケースで書く必要は無い)
- GUIテストはテスト実行に時間がかかるのでお茶でも飲もう
改善その1
- 最初に乱数で発生させた文章を利用する(Hermetic test patternの実施)
改善その2
- @Beforeを利用して、Driverの宣言をする
- @Afterを利用して、ブラウザを終了させる(DRY testing patternの実施)
改善その3
- クリックするのを簡潔な関数にしてみる(隠蔽化)
- sendKeyも簡潔な関数へ(ただし、その際には1回テキストエリアをクリアする必要がある)
public void inputText (By locator, String text){
selenium.findElement(locator).clear();
selenium.findElement(locator).sendKeys(text);
}
改善その他
- どんどんメソッド分割(抽象化)していく
- createDefaultCommentDataという名前のメソッドを用いて、デフォルト値を設定するのもあり
- ある程度その部分が今回の特殊ケース特有の複数の変数の場合はprivateクラスにしてしまおう
- 引数が違うが同じ動作を行う場合はOverloadして別メソッドに
Q&A
Q. 元々のサンプルのテストコードでは、トップページを呼んでから商品ページに飛んでいたが、 今回のassertを考えると、その部分は目的ではないため、やる必要がないのでは?テストの実施時間も長くなるし。
A. 今回はこのようなサンプルになってはいるが、自分の経験でも直リンで飛ばしてテスト開始した。
Q. 「テストケースを綺麗にする=リファクタリングする」というイメージだが、テストケースをするためのテストコードを書くべきか
A. アプリケーションがグリーンになることを保証すれば良い ロケータがきちんと取れるかに関してはテストを書く場合がある
Q. 自動テストのテスト要件の管理方法は?
A. テストケース自体をエクセルで管理すると死ぬ(コードとの乖離が激しくなる) BDDで書かれたものなどで完結すると良い テスト管理ツールを用いることもある。(チケット管理ツールをテスト用にカスタマイズするなど)