84

jUnit 4.4を使用してテストを実行し、一連の統合テストのセットアップとティアダウンを実行しようとしています。分解は確実に実行する必要があります。TestNGで他の問題が発生しているので、jUnitに移植することを検討しています。テストを実行する前、およびすべてのテストが完了した後、どのフックを実行できますか?

注:ビルドにはMaven2を使用しています。Mavenのpre-post-integration-testフェーズを使用してみましたが、テストが失敗すると、Mavenが停止して実行されませんpost-integration-test。これは役に立ちません。

4

11 に答える 11

117

はい、テスト スイート内のテストの前後に、セットアップ メソッドと破棄メソッドを確実に実行できます。コードでデモンストレーションしましょう:

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

したがって、セットアップ/破棄は、それぞれすべてのテストの前後にのみ実行されることがわかります。

キャッチ: これは、テスト スイートを実行している場合にのみ機能し、Test1 と Test2 を個別の JUnit テストとして実行していません。あなたはmavenを使用していると述べましたが、maven Surefireプラグインは、スイートの一部ではなく、個別にテストを実行するのが好きです。この場合、各テスト クラスを拡張するスーパークラスを作成することをお勧めします。スーパークラスには、注釈付きの @BeforeClass および @AfterClass メソッドが含まれます。上記の方法ほどきれいではありませんが、うまくいくと思います。

失敗したテストの問題については、maven.test.error.ignore を設定して、失敗したテストでビルドが続行されるようにすることができます。これは継続的なプラクティスとしてはお勧めできませんが、すべてのテストに合格するまで機能するはずです。詳細については、maven Surefire のドキュメントを参照してください。

于 2008-10-07T02:51:40.210 に答える
37

私の同僚は次のことを提案しました: カスタム RunListener を使用して testRunFinished() メソッドを実装できます: http://junit.sourceforge.net/javadoc/org/junit/runner/notification/RunListener.html#testRunFinished(org. junit.runner.Result)

RunListenerを登録するには、surefire プラグインを次のように構成するだけです

この構成は、フェイルセーフ プラグインでも選択する必要があります。このソリューションは、スイート、ルックアップ テスト クラスなどを指定する必要がないため、優れています。これにより、すべてのテストが完了するのを待って、Maven がその魔法を実行できるようになります。

于 2013-02-07T17:29:46.093 に答える
12

別の質問への回答で説明したように、 JUnit4.9以降で@ClassRuleアノテーションを使用できます。

于 2011-10-03T18:15:12.140 に答える
5

注釈を使用すると、次のようなことができます。

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()
    {

    }

}
于 2008-09-17T13:32:46.800 に答える
3

ここで、私たちは

  • JUnit 4.5 にアップグレードし、
  • 動作するサービスを必要とする各テスト クラスまたはメソッドにタグを付けるための注釈を書きました。
  • サービスのセットアップとティアダウンを実装するための静的メソッドを含む各アノテーションのハンドラーを作成し、
  • 通常の Runner を拡張して、テストの注釈を見つけ、適切なポイントで静的ハンドラー メソッドをテスト実行チェーンに追加しました。
于 2009-04-01T18:13:40.127 に答える
2

「注: ビルドには maven 2 を使用しています。maven の pre-& post-integration-test フェーズを使用してみましたが、テストが失敗した場合、maven は停止し、post-integration-test を実行しません。 、それは助けにはなりません。」

代わりにフェイルセーフプラグインを試すことができます。セットアップや中間段階のステータスに関係なく、確実にクリーンアップを行う機能があると思います

于 2010-12-07T14:54:16.527 に答える
2

すべてのテストが「技術的な」クラスを拡張し、同じパッケージにある場合、ちょっとしたトリックを行うことができます:

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() {}
}

このソリューションには多くの欠点があることに注意してください。

  • パッケージのすべてのテストを実行する必要があります
  • 「技術」クラスをサブクラス化する必要があります
  • サブクラス内で @BeforeClass および @AfterClass を使用することはできません
  • パッケージ内のテストを 1 つだけ実行すると、クリーニングは行われません
  • ...

詳細情報: listClassesIn() => Java で特定のクラスのすべてのサブクラスを見つけるにはどうすればよいですか?

于 2011-09-27T15:51:26.717 に答える
0

私が知る限り、JUnit でこれを行うメカニズムはありませんが、Suite をサブクラス化し、フックを提供するバージョンで run() メソッドをオーバーライドしてみてください。

于 2008-09-17T13:28:22.597 に答える
0

あなたが望む機能を得るために私が考える唯一の方法は、次のようなことをすることです

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() {}  
} 

私は日食でこのようなものを使用しているので、その環境の外でどれほど移植性があるかわかりません

于 2008-09-17T13:50:29.923 に答える
0

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>
于 2010-06-23T17:39:59.503 に答える
0

スイートを作成せず、すべてのテスト クラスを一覧表示する必要がある場合は、リフレクションを使用してテスト クラスの数を動的に検索し、基本クラス @AfterClass でカウント ダウンして、tearDown を 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 の回答から得られますhttps://stackoverflow.com/a/37488620/5930242

このクラスをどこにでも拡張したくない場合は、この最後の SO の回答が必要な場合があります。

于 2016-10-25T22:38:58.823 に答える