Junit4: 中断されたテスト ケースは、スレッドの再利用によりランダムな失敗を引き起こします。

作成日 2016年09月28日  ·  14コメント  ·  ソース: junit-team/junit4

テスト ケースが中断されると (Thread.interrupt())、テスト ランナー スレッドは中断された状態のままのように見えます。 これにより、後でスレッドが他のテスト ケースに再利用されるときに、ランダムな失敗が発生します。

期待される動作: スレッドが再利用されると、新しいテスト ケースを開始する前に、スレッドの割り込みフラグが消去されます。 これは、 Thread.interrupted()呼び出すことで実行できます。これは、中断された状態を返し、中断されたフラグをクリアします。

test1 が test2 の前に実行される場合、次のコードで問題が再現されるはずです。

import org.junit.Test;

public class ThreadTest {
  <strong i="9">@Test</strong>
  public void test1() {
    Thread.currentThread().interrupt();
  }

  <strong i="10">@Test</strong>
  public void test2() throws InterruptedException {
    Thread.sleep(1000);
  }
}

私が遭遇した問題は、 https://www.thoughtwire.com/junit-interupt/ で説明されている問題に似てい

bug

最も参考になるコメント

新しいテスト ケースを実行する直前に、複数のテスト ケースで再利用される各スレッドでThread.interrupted()を呼び出すという考えを支持します。 しかし、特に 1 つのスレッドが複数のテスト クラスに使用されている場合はそうです。 中断フラグは、あるテスト ケースから別のテスト ケースに漏れて、テスト ケースが不安定になる状態です。 特に、とにかく正しく取得するのが難しいことで有名な複数のスレッドを処理するテスト ケース。

全てのコメント14件

バグ報告ありがとうございます。

テストの実行中に中断されたビットが設定された場合、JUnit によってテストが失敗するのではないかと思います。 そうしないと、多くのテストに合格すると失敗し始め、修正はどこにでもinterrupted()呼び出しをまき散らすことになるからです。

ExpectesException assertThrows()またはexpectThrows()が中断されたビットをクリアする必要があるかどうかという問題もあります。 私は彼らがそうすべきだと推測しています。

@junit-team/junit-committers の考えは?

新しいテスト ケースを実行する直前に、複数のテスト ケースで再利用される各スレッドでThread.interrupted()を呼び出すという考えを支持します。 しかし、特に 1 つのスレッドが複数のテスト クラスに使用されている場合はそうです。 中断フラグは、あるテスト ケースから別のテスト ケースに漏れて、テスト ケースが不安定になる状態です。 特に、とにかく正しく取得するのが難しいことで有名な複数のスレッドを処理するテスト ケース。

@kcooneyこれで作業を開始できます。

@npathai素晴らしい!

ExpectedExceptionまたはassertThrows()が中断されたビットをクリアする必要があるかどうかについては、まだ未解決の問題があります。 @junit-team/junit-committers の考えは?

私見では、各テストの後に割り込みフラグをクリアする必要があります。 ExpectedExceptionassertThrows()ではクリアしないでください。テスト後にクリアされるからです。

@kcooney ExpectedExceptionassertThrows()がフラグをクリアする必要があると考える理由を説明していただけますか。

@stefanbirkner私が読んだ一般的なガイダンスは、 InterruptedExceptionをキャッチして再スローしない場合はいつでも、 interruptを呼び出す必要があります (https://www.ibm.com/developerworks/library を参照)。 /j-jtp05236/index.html で「割り込みを飲み込まないでください」を検索してください)。 ExpectedExceptionassertThrows()予期しない例外を「飲み込む」ので、人々が何をすべきかを知りたかったのです。

FWIW、GitHub で JUnit 5 のinterrupted()呼び出しをすばやく検索しましたが、呼び出しは見つかりませんでした。

@kcooney @stefanbirkner IDE が JUnit フレームワークとどのように統合されるのか疑問に思っていました。 次のような長期実行テストケースがある場合

<strong i="8">@Test</strong>
  public void test1() throws InterruptedException {
    Thread.sleep(100000);
  }

<strong i="9">@Test</strong>
  public void test2() throws InterruptedException {
    Thread.sleep(100000);
  }

そしてIDEを使ってテストケースを強制終了。 IDE は、JUnit テストなどを実行しているスレッドを中断しますか?
IntelliJで動作を確認したところ、IDEからテストケースを強制停止すると、別のプロセスを実行してプロセスを中断しているようです。 コンソールにProcess finished with exit code 130 (interrupted by signal 2: SIGINT)れます。
Eclipse JDT ソースを調べたところ、テスト ケースの実行に何らかのリモート接続が使用されていることがわかりました。

私が疑っているのは、中断を尊重せず、それを飲み込むことにより、ある意味でThread.interrupted()慣習に違反しているということです。 そこで、IDE 統合が実際にjunitThread.interrupt()を使用して JUnit テストのそれ以上の実行を停止した場合、その要求は受け入れられないと考えました。 したがって、この場合、 test1が実行されているときに IDE から停止ボタンをクリックすると、現在のメソッドが実行され、それ以上のテスト ケースは実行されません。 この動作は、割り込みステータス フラグをリセットすることで影響を受けますか。

質問がばかげている場合は申し訳ありません。IDE の統合方法についての経験がありません。 私に光を当てることができれば、それは素晴らしいことです。

@ npathai IDE はRunNotifier.pleaseStop()呼び出すと思います

それは懸念のように聞こえるので、このです:IDEが呼び出した場合、何が起こるかpleaseStop() 、次にThread.interrupt()テストを実行しているスレッド上で?

そのスレッドがブロッキング メソッド内になく、ブロッキング メソッドを呼び出さない場合、テストの実行は現在のテストの完了後に中止されます ( pleaseStop() )。

そのスレッドがブロッキング メソッド内にある場合、またはブロッキング メソッドを呼び出す場合は、 InterruptedExceptionがスローされます。 テストがその例外をキャッチしない場合、テストは失敗し、テストの実行は中止されます。

テストが例外を飲み込むと、事態は複雑になります。

Surefire ではpleaseStop() を使用します。 私たちは、現在の行動に依存しています。
JUnit のスケジューラは、新しい Runnable (テスト メソッド) のスケジュールを停止しますが、
保留中のメソッドが続行されます。

2018 年 11 月 9 日金曜日、午後 5 時 48 分、Kevin Cooney [email protected]
書きました:

したがって、懸念事項は次のとおりです。IDE が呼び出した場合はどうなりますか。
テストを実行しているスレッドでpleaseStop()、次にThread.interrupt()?

そのスレッドがブロッキング メソッドになく、ブロッキング メソッドを呼び出さない場合
メソッドを使用すると、現在のテスト完了後にテスト実行が中止されます (
停止してください()

そのスレッドがブロッキング メソッド内にあるか、ブロッキング メソッドを呼び出している場合、
割り込み例外をスローします。 テストがその例外をキャッチしない場合、それは
失敗すると、テストの実行は中止されます。

テストが例外を飲み込むと、事態は複雑になります。


このスレッドに登録しているため、これを受け取っています。
このメールに直接返信して、GitHub で表示してください
https://github.com/junit-team/junit4/issues/1365#issuecomment-437420750
またはスレッドをミュート
https://github.com/notifications/unsubscribe-auth/AA_yR9IgJF3rTXtFz9y9EIBig914twYYks5utbHrgaJpZM4KIg2k
.

--
乾杯
ティボル

これは JUnit 5 に合わせて厳選するべきではありませんか? 5.3.2 でも同じ問題が発生しています。

@joaodias14最新バージョンにアップグレードしてください

@marcphilipp ありがとうございます!

このページは役に立ちましたか?
0 / 5 - 0 評価