自動テストしてますか?
自動テストをやろう、と思った時に何の準備もせずに始めると、後から大きな手戻り(というか「もう、自動テスト止めようぜ」という空気)になりがちです。
ここで言う「自動テスト」は、Selenium的なものを使った、統合したシステムテストの自動テストを対象にしています。
いつでも同じ結果を返すように
原則はこれです。これが崩れると意味が無い。これが守れないようになってくると「これ意味あんのか?」となってしまい、自動テストへの熱意も薄れていきます。
立ちはだかるシステム日付(日時)
テスト前に前提条件のTableデータを登録する仕組みがあっても、そのシステムが「システム日付」を使っている場合、途端にスクリプトの難易度が上がる気がします。
単体テストなら
- 引数で日付を貰って処理を行う
- SQLで直接システム日付を参照せず、バインド変数化
- システム日付取得処理自体をMock化(好きじゃない)
することで回避することができます。作りの問題で容易に回避できます。
ただ、Selenium的なものだと...
TOP画面にはログインユーザが担当になっている「システム日付〜2日」分の未完了タスクをDBより検索し、表示する
ような機能をテストする場合、シナリオを取った時と実行する時のシステム日付が違えば結果も当然異なります。
あれ?昨日はうまくいったのに、今日はダメだな...となります。シナリオ取ってくれた人のモチベーションも急下降です。
DBのデータをシナリオを流す日付に合わせて都度変える
うーん。面倒ですよねぇ。
システム日付を固定化する
# date -s "04/01 00:00 2016"
マジですか。
システム日付はUtilから取得
プログラムでシステム日付を直接取得するのではなく、共通処理からといいうのはどうでしょう?
✕
val now = LocalDate.now()
val nowDateTime = LocalDateTime.now()
◯
val now = CurrentDateUtil.now()
val nowDateTime = CurrentDateUtil.nowDateTime()
共通処理CurrentDateUtilよりシステム日付を取得することをルール化します。
共通処理の中身はこんな感じ
object CurrentDateUtil {
private val fixDate = System.getProperty("fixDate", "") match {
case date if !date.isEmpty => Option(DateTimeFormat.forPattern("yyyy-MM-dd").parseLocalDate(date))
case _ => None
}
def now = {
if(fixDate.isEmpty) LocalDate.now() else fixDate.get
}
}
JVMの引数に指定されていれば固定日付を返します。
ex.) -DfixDate=2016-04-01
前提条件のシステム日付を決めて
- 前提条件のデータ登録
- Seleniumシナリオ記録
し、
- Seleniumシナリオ再生時
にはJVMのパラメータを設定しておくことで、システム日付が固定の状態でテストを実行できます。これで、いつ動かしても結果は同じになります。
まとめ
システムができてから自動化の取り組みをしたのでは遅いかもしれません。
ツールの使い方だけ習熟してもどうにもならないことありますし、せっかくの自動化への熱い思いを持続させるために、システム開発の初期段階から自動化しやすいように作れる箇所があるはずです。
いつか「テスト自動化やろう!」と思った時の参考になれば幸いです。