Fight the Future

Java言語とJVM、そしてJavaエコシステム全般にまつわること

ステートフルなテスト-TestNGをさらに深く理解してみる(1)

@ITさんの連載も終わり、Next Generation Java Testing: TestNG and Advanced Conceptsをネタに記事では書かなかったことを紹介していく。
不定期連載の予定。

ステートフルなテストとは

TestNGは各テストメソッドの呼び出しで同じインスタンスを利用する。詳しくは@ITさんの連載第1回を読んでね。
同じインスタンスだから状態を持つわけで、ステートフルなテストと呼ばれる。
一般的にテスト間で状態を共有することは「やってはいけない」プラクティスである。
ではなぜTestNGはそれをやってしまているのか?

状態のカテゴライズ

まず。状態は2つのものがあり、きちんと区別する必要がある。

  • 不変な状態(Immutable State)
  • 変化する状態(Mutable State)

不変な状態はたとえばfinal宣言したフィールドとか。これはまったく問題ない。
重要なのは値の初期化が一度しか行われないということ。
状態が変わることはないので、こう言える。


不変な状態にアクセスするテストメソッドは互いに独立している。


一方、変化する状態はたとえば普通のインスタンス変数とか。

public class Sample {
  private int count;

  @Test
  public void test1() {
    count++;
    assertEquals(1, count);
  }

  @Test
  public void test2() {
    count++;
    assertEquals(2, count);
  }
}

countはテストメソッドの実行で値が変わる。だからcountは変化する状態。
だけどこのテストは誤り。test1()とtest2()がどんな順序で実行されるかわからないから。
この場合test1()->test2()の順序で実行されなければテストが成功しない。
つまりこう言える。


変化する状態をテスト間で共有してよいのは、どの順序でテストを実行するのか決められるときだけである。


そのためにTestNGのdependsOnXXX属性を利用する。
テスト間で「絶対に」状態を共有してはならない、という原則は誤ってるというのがTestNGの考え。
逆にこうした依存性を指定していないときに変化する状態を用いてはならないということ。

共有する状態の種類 安全か
不変な状態 安全
依存性を指定した変化する状態 安全
依存性を指定していない変化する状態 安全でない

テストの実行速度

あと、同じインスタンスを使うことで実行速度の面でもメリットがある。