JaSST'15 Tokyo 『テストコードクリニック』参加記録

JaSSTソフトウェアテストシンポジウム-JaSST'15 Tokyo より

はじめに

JaSST'15のセッションの一つ『テストコードクリニック』に参加してきました。

このセッションでは、スライドに載っていない部分であるデモで多くの時間を割いていたので、そのデモでの修正方法なども紹介します。(記事の後半)

発表スライド

JaSST'15 テストコードクリニック

自己紹介

太田健一郎

プロセス改善などもやっている

Selenium Design Patterns and Best Practices

  • 2015年8月に翻訳書が出版される予定
  • 普通の本はSelenium APIの紹介が多いが、この本にはGUIテストなどの話が載っている。

自動テストソフトウェアのアーキテクチャ

詳しくはシステムテスト自動化標準ガイド(ギア本)に載ってる

 

システムテスト自動化 標準ガイド CodeZine BOOKS

システムテスト自動化 標準ガイド CodeZine BOOKS

 

 

あるある残念なコード

今回のサンプルは、商品のAdd Cartやコメントができるサイト

ただし、短時間に同じ内容コメントは投稿できない(弾く)仕組みになっている

サンプルコードはGithub上にある 


dimacus/SeleniumBestPracticesBook · GitHub

 

今回は、以下の2つのテストケースが対象

  1. コメントを書き込む
  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

 

デモ

デモで使用したコード

https://github.com/dimacus/SeleniumBestPracticesBook/blob/master/Java/src/test/java/chapter2/ProductReviewTests.java

元々のテストコード

  • 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で書かれたものなどで完結すると良い テスト管理ツールを用いることもある。(チケット管理ツールをテスト用にカスタマイズするなど)

まとめ