2012-01-27 10 views
6

私はJUnit 4.10をテストスイートの実行に使用していますが、How to Re-run failed JUnit tests immediately?ポストのMatthew Farwellの素晴らしいメモの後に "再試行失敗テスト"ルールを実装しました。テストケース内部のルールとしてこれを使用する場合、それは完璧に動作スイート内のすべてのテストケースにJUnit @Ruleを適用する方法

public class RetryTestRule implements TestRule { 

    private final int retryCount; 

    public RetryTestRule(int retryCount) { 
    this.retryCount = retryCount; 
    } 

    @Override 
    public Statement apply(Statement base, Description description) { 
    return statement(base, description); 
    } 

    private Statement statement(final Statement base, final Description description) { 
    return new Statement() { 
     @Override 
     public void evaluate() throws Throwable { 
     Throwable caughtThrowable = null; 

     // retry logic 
     for (int i = 0; i < retryCount; i++) { 
      try { 
      base.evaluate(); 
      return; 
      } catch (Throwable t) { 
      caughtThrowable = t; 
      System.err.println(description.getDisplayName() + ": run " + (i + 1) + "  failed"); 
      } 
     } 
     System.err.println(description.getDisplayName() + ": Giving up after " + retryCount 
      + " failures"); 
     throw caughtThrowable; 
     } 
    }; 
    } 
} 

が、のすべてのテストケースで@Rule表記を使用するために最適ではないようだ:私は、次のコードでクラス「RetryTestRule」を作成しました代わりにスイートの定義における単一表記のスイート、ビットをチェックした後、私は私のスイートクラスの新しい@ClassRule表記を試してみましたので:問題は、予想通り、これは動作しませんです

@RunWith(Suite.class) 
@SuiteClasses({ 
    UserRegistrationTest.class, 
    WebLoginTest.class 
}) 
public class UserSuite {  
    @ClassRule 
    public static RetryTestRule retry = new RetryTestRule(2); 
} 

:失敗したテストが再試行されていません。誰もがこれを試して、解決策を知っていますか?助けが大いにありがとう!

+0

重複している可能性があります:http://stackoverflow.com/questions/7639353/how-to-define-junit-method-rule-in-a-suite – pholser

+0

あなたのユニットテストはランダムに失敗しますか? – Tobb

答えて

6

@ClassRuleは、メソッドごとに1回ではなく、クラスごとに1回実行されます。メソッドごとに何かを実行させるには、@Ruleを使用するか、How to define JUnit method rule in a suite?の答えに従う必要があります。

あなたの既存のルールを再利用するには、次のようにRunRulesクラスを使用して、実行するためのルールのリストにルールを追加することができます。

public class MyRunner extends BlockJUnit4ClassRunner { 
    public MyRunner(Class<?> klass) throws InitializationError { 
     super(klass); 
    } 

    @Override 
    protected void runChild(final FrameworkMethod method, RunNotifier notifier) { 
     Description description= describeChild(method); 
     if (method.getAnnotation(Ignore.class) != null) { 
      notifier.fireTestIgnored(description); 
     } else { 
      RunRules runRules = new RunRules(methodBlock(method), Arrays.asList(new TestRule[]{new RetryTestRule(3)}), description); 
      runLeaf(runRules, description, notifier); 
     } 
    } 
} 

これは、上記の回答からの例を使用しています。おそらく2つの答えを組み合わせて、より細かい制御を行い、たとえばテストに注釈がある場合はRetryTestRuleを作成することができます。

+0

あなたの素早い答え、マシューに感謝します。提案したように両方の答えを組み合わせて、簡単にカスタムランナーとスイートを作成しました。それから、スイートルームのクラスに@RunWith(MySuite.class)を追加しました。 – jbaxenom

+0

何かまたはこのアプローチ(両方の回答*の組み合わせ)が不足しているため、テストは '@ClassRule ... ExternalResource .. 'の実行前に実行されます。 ..前のメソッド ' – Daniel

関連する問題