JUnit 4.4を使用してテストを実行し、一連の統合テストのセットアップと分解を実行しようとしています。分解は確実に実行する必要があります。 TestNGで他の問題が発生しているので、jUnitに移植することを検討しています。テストを実行する前、およびすべてのテストが完了した後、どのフックを実行できますか?
注:ビルドにはmaven 2を使用しています。私はmavenのpre-
&post-integration-test
段階ですが、テストが失敗すると、mavenは停止し、実行されませんpost-integration-test
、これは役に立ちません。
はい。テストスイートでのテストの前後に、確実にセットアップおよびティアダウンメソッドを実行できます。コードでデモンストレーションさせてください:
package com.test;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({Test1.class, Test2.class})
public class TestSuite {
@BeforeClass
public static void setUp() {
System.out.println("setting up");
}
@AfterClass
public static void tearDown() {
System.out.println("tearing down");
}
}
したがって、Test1クラスは次のようになります。
package com.test;
import org.junit.Test;
public class Test1 {
@Test
public void test1() {
System.out.println("test1");
}
}
...そして、Test2が似ていると想像できます。 TestSuiteを実行した場合、以下が得られます。
setting up
test1
test2
tearing down
そのため、セットアップ/ティアダウンは、すべてのテストの前後でのみ実行されることがわかります。
キャッチ:これは、テストスイートを実行していて、個々のJUnitテストとしてTest1とTest2を実行していない場合にのみ機能します。 mavenを使用していると述べましたが、maven surefireプラグインは、スイートの一部ではなく、個別にテストを実行することを好みます。この場合、各テストクラスが拡張するスーパークラスを作成することをお勧めします。スーパークラスには、注釈付きの@BeforeClassおよび@AfterClassメソッドが含まれます。上記の方法ほどきれいではありませんが、うまくいくと思います。
失敗したテストの問題については、maven.test.error.ignoreを設定して、失敗したテストでビルドを続行できます。これは継続的なプラクティスとしては推奨されませんが、すべてのテストに合格するまで機能するはずです。詳細については、 maven surefire documentation を参照してください。
私の同僚は次のことを提案しました:カスタムRunListenerを使用してtestRunFinished()メソッドを実装できます: http://junit.sourceforge.net/javadoc/org/junit/runner/notification/RunListener.html# testRunFinished(org.junit.runner.Result)
RunListenerを登録するには、次のようにsurefireプラグインを設定するだけです。 http://maven.Apache.org/surefire/maven-surefire-plugin/examples/junit.html section「カスタムリスナーとレポーターの使用」
この構成は、フェイルセーフプラグインでも選択する必要があります。このソリューションは、スイート、ルックアップテストクラス、またはこれらのものを指定する必要がないため、素晴らしいです。これにより、Mavenはすべてのテストが終了するまで待機します。
JUnit 4.9+の@ClassRuleアノテーション を 別の質問の回答で説明した として使用できます。
注釈を使用すると、次のようなことができます。
import org.junit.*;
import static org.junit.Assert.*;
import Java.util.*;
class SomethingUnitTest {
@BeforeClass
public static void runBeforeClass()
{
}
@AfterClass
public static void runAfterClass()
{
}
@Before
public void setUp()
{
}
@After
public void tearDown()
{
}
@Test
public void testSomethingOrOther()
{
}
}
ここで、私たち
すべてのテストが「技術的な」クラスを拡張し、同じパッケージ内にある場合、ちょっとしたトリックを行うことができます。
public class AbstractTest {
private static int nbTests = listClassesIn(<package>).size();
private static int curTest = 0;
@BeforeClass
public static void incCurTest() { curTest++; }
@AfterClass
public static void closeTestSuite() {
if (curTest == nbTests) { /*cleaning*/ }
}
}
public class Test1 extends AbstractTest {
@Test
public void check() {}
}
public class Test2 extends AbstractTest {
@Test
public void check() {}
}
このソリューションには多くの欠点があることに注意してください:
詳細については、listClassesIn()=> Javaで指定されたクラスのすべてのサブクラスを見つける方法
「注:ビルドにmaven 2を使用しています。mavenの統合テスト前後のフェーズを使用しようとしましたが、テストが失敗した場合、mavenは停止し、統合後テストを実行しません。 、これは助けにはなりません。」
代わりにfailsafe-pluginを試すことができます。セットアップまたは中間段階のステータスに関係なくクリーンアップが行われるようにする機能があると思います
スイートを作成せず、すべてのテストクラスを一覧表示する必要がない場合は、リフレクションを使用してテストクラスの数を動的に検索し、基本クラス@AfterClassでカウントダウンしてティアダウンを1回だけ実行できます。
public class BaseTestClass
{
private static int testClassToRun = 0;
// Counting the classes to run so that we can do the tear down only once
static {
try {
Field field = ClassLoader.class.getDeclaredField("classes");
field.setAccessible(true);
@SuppressWarnings({ "unchecked", "rawtypes" })
Vector<Class> classes = (Vector<Class>) field.get(BlockJUnit4ClassRunner.class.getClassLoader());
for (Class<?> clazz : classes) {
if (clazz.getName().endsWith("Test")) {
testClassToRun++;
}
}
} catch (Exception ignore) {
}
}
// Setup that needs to be done only once
static {
// one time set up
}
@AfterClass
public static void baseTearDown() throws Exception
{
if (--testClassToRun == 0) {
// one time clean up
}
}
}
静的ブロックの代わりに@BeforeClassを使用する場合は、ブール値フラグを使用して、リフレクションカウントを実行し、最初の呼び出しでセットアップを1回だけテストすることもできます。これが誰かを助けることを願っています。スイートのすべてのクラスを列挙するよりも良い方法を見つけるのに午後かかりました。
あとは、このクラスをすべてのテストクラスに拡張するだけです。すべてのテストに共通するものを提供するための基本クラスがすでにあるため、これが私たちにとって最適なソリューションでした。
これからインスピレーションを得ますSO answer https://stackoverflow.com/a/37488620/5930242
このクラスをどこまでも拡張したくない場合は、この最後のSO answerがあなたが望むことをするかもしれません。
Maven-surefire-pluginはスイートクラスを最初に実行せず、スイートクラスとテストクラスを同じように扱うため、以下のようにプラグインを構成してスイートクラスのみを有効にし、すべてのテストを無効にすることができます。 Suiteはすべてのテストを実行します。
<plugin>
<groupId>org.Apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<includes>
<include>**/*Suite.Java</include>
</includes>
<excludes>
<exclude>**/*Test.Java</exclude>
<exclude>**/*Tests.Java</exclude>
</excludes>
</configuration>
</plugin>
あなたが望む機能を得るために私が考える唯一の方法は、次のようなことをすることです
import junit.framework.Test;
import junit.framework.TestResult;
import junit.framework.TestSuite;
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("TestEverything");
//$JUnit-BEGIN$
suite.addTestSuite(TestOne.class);
suite.addTestSuite(TestTwo.class);
suite.addTestSuite(TestThree.class);
//$JUnit-END$
}
public static void main(String[] args)
{
AllTests test = new AllTests();
Test testCase = test.suite();
TestResult result = new TestResult();
setUp();
testCase.run(result);
tearDown();
}
public void setUp() {}
public void tearDown() {}
}
私はEclipseでこのようなものを使用しているので、その環境の外でどれくらい移植性があるのか分かりません
私が知る限り、JUnitでこれを行うメカニズムはありませんが、Suiteをサブクラス化し、フックを提供するバージョンでrun()メソッドをオーバーライドすることもできます。