JUnit 4のテストを条件付きで無視する


365

OK、@Ignoreアノテーションはテストケースを実行しないようにマークするのに適しています。

ただし、ランタイム情報に基づくテストを無視したい場合があります。例としては、特定の数のコアを備えたマシンで実行する必要がある同時実行テストがあるとします。このテストがユニプロセッサマシンで実行された場合、テストに合格することは(実行されていないため)正しくないだろうと思います。テストに失敗してビルドを中断するのは間違いです。

したがって、これは正しい結果のように見えるので、実行時にテストを無視できるようにしたいのです(テストフレームワークではビルドはパスできますが、テストが実行されなかったことを記録するため)。注釈によってこの柔軟性が得られないことはかなり確実であり、問​​題のクラスのテストスイートを手動で作成する必要があると思われます。ただし、ドキュメントではこれについて何も言及されておらず、APIを調べても、これがプログラムでどのように行われるかが明確ではありません(つまりTest@Ignoreアノテーションによって作成されたインスタンスと同等のインスタンスなどをプログラムでどのように作成しますか?)

誰かが過去に同じようなことをしたことがある、または私がこれについて他にどうしたらいいかについて明るい考えを持っているなら、私はそれについて聞いて幸せです。

回答:


476

JUnitの方法は、実行時にこれを行うことですorg.junit.Assume

 @Before
 public void beforeMethod() {
     org.junit.Assume.assumeTrue(someCondition());
     // rest of setup.
 }

@Beforeメソッドまたはテスト自体で実行できますが、メソッドでは実行できません@After。テスト自体で@Before実行すると、メソッドが実行されます。@BeforeClassクラスの初期化を防ぐために、内部で行うこともできます。

仮定が失敗すると、テストは無視されます。

編集:junit-ext@RunIfからの注釈と比較するには、サンプルコードは次のようになります。

@Test
public void calculateTotalSalary() {
    assumeThat(Database.connect(), is(notNull()));
    //test code below.
}

Database.connect()この方法でメソッドからの接続をキャプチャして使用する方がはるかに簡単であることは言うまでもありません。


1
@notnoop、それは私の観察ではまったくありません。それらは無視されます。IDEAテストランナーはそれらをそのように報告し、JUnitソースコードを見ると、テストが無視されたと報告されていることがわかります。
Yishai、

1
「将来的には、これは変更される可能性があり、仮定が失敗すると、テストが無視される可能性があります。」実際には4.5の時点で変更されたと思います。現在のjavadocは次のように述べています。「デフォルトのJUnitランナーは、失敗した仮定のテストを無視して扱います。カスタムランナーの動作は異なる場合があります。」github.com/KentBeck/junit/blob/…–
Yishai

4
Junit 4.8.1を搭載したEclipse 3.6は、テストに合格すると誤った仮定を報告します。Ant 1.8.1と同じです。
fijiaaron

8
渡されたものはバグであるため、Eclipseは失敗した仮定を報告する:bugs.eclipse.org/bugs/show_bug.cgi?id
Martin

1
@JeffStorey、それからあなたはいくつかのものを探しています。1つは@BeforeClassアノテーションです。ここで仮定が失敗する可能性があり、クラス全体がスキップされます。もう1つは@ClassRule(きめ細かい制御ですが、クラス全体で1回)です。
Yishai

51

Junit-extプロジェクトをチェックアウトする必要があります。これらにはRunIf、次のような条件テストを実行する注釈があります。

@Test
@RunIf(DatabaseIsConnected.class)
public void calculateTotalSalary() {
    //your code there
}

class DatabaseIsConnected implements Checker {
   public boolean satisify() {
        return Database.connect() != null;
   }
}

[チュートリアルから取得したコードサンプル]


3
この回答に感謝します-機能の興味深い代替構文ですが、Assume別の依存関係を導入しないように直接説明します。
Andrzej Doyle

3
私は個人的にこのソリューションを好みます。同じ条件に基づいて実行する必要がある多くのテストがある場合、これはすべてのテストでAssumeを使用する必要があるよりもはるかに理想的です。また、これがメソッドレベルではなくクラスレベルで使用できる場合は、さらに理想的です。
Richard

私はそれを好みます、これは実行時に条件付きでテストを実行するのに役立ちます。これは、いくつかの単体テストを実行する場所に適しています。要件は、特定のチェッカーで単体テストを実行することです。junit-extがmavenリポジトリーで使用できないことに本当に驚いています。mavenプロジェクトでこれをどのように利用するか。
シャンブ2014年

4
のような注釈は@RunIf、テストを実行する必要があるときの条件を実際のテストコードから分離するものです。私が気に入らないのは、特定のテストランナーが必要なことです。したがって、私は条件付きでテストを無視するJUnitルールを作成しました。
リュディガーヘルマン

2
junit-ext jar(ここでcode.google.com/p/junit-ext/downloads/…にあります)をローカルリポジトリにインストールし、この@RunIfアノテーションを実装した後... それは完全に無視されており、その理由はjunit-extがjunit 4.5に依存しているように思われるためかもしれません。スプリングテストのため4.9以上が必要です。だから...気にしないで。
2015

7

JUnit 4では、別のオプションとして、テストがカスタム基準を満たす必要があることを示す注釈を作成してから、デフォルトランナーを独自のもので拡張し、リフレクションを使用して、カスタム基準に基づいて決定することができます。次のようになります。

public class CustomRunner extends BlockJUnit4ClassRunner {
    public CTRunner(Class<?> klass) throws initializationError {
        super(klass);
    }

    @Override
    protected boolean isIgnored(FrameworkMethod child) {
        if(shouldIgnore()) {
            return true;
        }
        return super.isIgnored(child);
    }

    private boolean shouldIgnore(class) {
        /* some custom criteria */
    }
}

これは見た目もすっきりしていますが、JUnit4の場合、現在のバージョンではBlockJUnit4ClassRunner動作しませisIgnoredん。
Dave、

-2

簡単なメモ:Assume.assumeTrue(condition)残りのステップは無視しますが、テストに合格します。テストに失敗するにはorg.junit.Assert.fail()、条件ステートメント内で使用します。同様にAssume.assumeTrue()機能しますが、テストに失敗します。


5
上記の回答で述べたように、仮定が失敗してテストはパスせ、別のステータスが返されます。一部のランナーはパスのように誤ってこれ報告する可能性がありますが、それはテストランナーの弱点/バグです(そしてデフォルトのJUnitランナーはテストを無視したと表示します)。そして、あなたの最後の文章については、テストに失敗したことは特に私がしたいことではありません。
Andrzej Doyle

ああ。私の場合、テストは失敗したという仮定に合格しましたが、テストが失敗したことを報告してほしいと思っていました(テストウォッチャーからの例外を確認していました)。失敗を強いることは私を助けました。
TIn TIn 16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.