テストランナーにJUnitを使ってE2Eテストを実装する際、画面やAPIごとにテストクラスを分割しました。このときに複数のテストクラスに共通のテストメソッドを定義する方法を検討しました。
(1) 継承関係を使う
共通のテストメソッドをテストクラスの親クラスに定義することで、各テストクラスの実行時に親クラスのテストメソッドも実行される。
各テストクラスに特有の振る舞いをインターフェース(もしくは親クラスの抽象メソッド)として定義しておき、共通テストメソッドではこのインタフェースを使ってテストを実装する。
public abstract class CommonTestA {
// テストクラスに特有の振る舞いを定義ための抽象メソッド
abstract SomeObject doSomething();
@Test
public void commonTestX() {
// doSomething()を使って共通のテストケースを実装する
}
}
// このテストクラスを実行する際にCommonTest.commonTestX()も実行される
public class TestClass extends CommonTestA {
// テストクラスに固有のテストケースを実装する
}
この方法では、Javaの継承の制約により1つのテストクラスは1つの共通テストクラスしか継承できないため、共通テストクラスを複数作りたいときに問題となる。
(2) デフォルトメソッドを使う
Java 8で導入されたインターフェースのデフォルトメソッドを使うことで (1) の問題を回避できる。(インターフェースは1つのクラスに複数実装できるため。)ただし、JUnit 4以前ではデフォルトメソッドは実装クラス実行されないため、JUnit 5を使う必要がある。
public interface CommonTestA {
SomeObject doSomething();
@Test
default void commonTestA() {
// 共通テストメソッドをデフォルトメソッドとして定義する
}
}
// 1つのテストクラスに複数の共通テストインターフェースを実装できる
public class TestClassX implements CommonTestA, ComonTestB {
// ...
}