2013-05-24 34 views
8

私は自動化されたセレンテストの既存システムを改善しようとしています。 私の目標は、接続の問題で失敗したテストを繰り返すことです。 私はこのスレッドHow to Re-run failed JUnit tests immediately?を見つけてそれを追跡しようとしました。Junitを使用して失敗したテストを再実行してください

私の場合、スイートはクラスで構成されているので、@Beforeと@Afterの各部分を繰り返し実行するために@Ruleを@ClassRuleに置き換えようとしました。 私の無知には申し訳ありませんが、どこにこの規則を置くのですか?私のスイートクラスでは?またはテストを表すクラスでは?

答えて

0

あなたは@Afterまたは@Afterclass属性でテスト名自身を飾る:注意する

@After 
@Test 
@Category(SmokeTests.class) 
public void testProductPageOnly() throws TimeoutException { 
    //Some tests here. 
} 

@Afterclass 
public static void SomeTest { 
    //Some test here. 
} 

何か、@Afterclass常にを実行します。例外をスローする@Beforeclassを使用していても例外ではありません。

+1

これは初めてテストに失敗しただけではなく、テストを2回実行することはありませんか? –

+0

@ JohnB - 書かれているとおり、はい。しかし、彼のテストは本質的に一時的な接続性の問題のために失敗したように見えるので、これはOPの利点です。 – Brian

+1

しかし、最初に通過して2回目に失敗した場合、失敗を報告し、失敗を2倍にする可能性があります。 –

0

これは、問題解決することができますする可能性があります)テストクラスはjunit.framework.TestCase

2から継承されなければならない

1)終わりにresult意志が最後に含まれている。この

YourTestClass testClass = new YourTestClass(); 
TestResult result = testClass.run(); 
Enumeration<TestFailure> failures = result.failures(); 
if (result.failureCount() != 0) 
{ 
    TestFailure fail = failes.nextElement(); 
    junit.framework.Test test = fail.failedTest(); 
    test.run(result); 
} 

のようなものを使用してテストを実行しますテスト実行の結果、どのテストが失敗したのかを分析した後、再度実行することができます。

+2

JUnit 4.xにアップグレードできない、またはJava 5より前の互換性が必要な場合を除き、 '' '' 'junit.framework。*' ''クラスを拡張/使用しないでください。 – Foxsly

4

ここに私の解決策は、質問に記載されているものに基づいています。

それは与え@RuleFailedRule@ClassRuleRetryRule

public class RetryTest 
{ 
    public static class FailedRule implements TestRule 
    {  
     @Override 
     public Statement apply(final Statement base, final Description description) 
     { 
      return new Statement() 
      { 
        @Override 
        public void evaluate() throws Throwable 
        { 
         try 
         { 
          base.evaluate(); 
         } 
         catch (Throwable t) 
         { 
          System.out.println(description.getDisplayName() + " failed"); 
          retry.setNotGood(); 
          if (retry.isLastTry()) 
          { 
           System.out.println("No more retry !"); 
           throw t; 
          } 
          else 
          { 
           System.out.println("Retrying."); 
          } 
         } 
        } 
      }; 
     } 
    } 

    public static class RetryRule implements TestRule 
    { 
     private int retryCount, currentTry; 

     private boolean allGood = false; 

     public RetryRule(int retryCount) 
     { 
      this.retryCount = retryCount; 
      this.currentTry = 1; 
     } 

     public boolean isLastTry() 
     { 
      return currentTry == retryCount; 
     } 

     public void setNotGood() 
     { 
      allGood = false; 
     } 

     public Statement apply(final Statement base, final Description description) 
     { 
      return new Statement() 
      { 
       @Override 
       public void evaluate() throws Throwable 
       { 
        // implement retry logic here 
        for (; currentTry <= retryCount && !allGood; currentTry++) 
        { 
         allGood = true; 
         System.out.println("Try #" + currentTry); 
         base.evaluate(); 
        } 
       } 
      }; 
     } 
    } 

    @ClassRule 
    public static RetryRule retry = new RetryRule(3); 

    @Rule 
    public FailedRule onFailed = new FailedRule(); 

    @BeforeClass 
    public static void before() 
    { 
     System.out.println("Before..."); 
    } 

    @AfterClass 
    public static void after() 
    { 
     System.out.println("...After\n"); 
    } 

    @Test 
    public void test1() 
    { 
     System.out.println("> test1 running"); 
    } 

    @Test 
    public void test2() 
    { 
     System.out.println("> test2 running"); 
     Object o = null; 
     o.equals("foo"); 
    } 
} 

のcombinaisonです:

Try #1 
Before... 
> test1 running 
> test2 running 
test2(RetryTest) failed 
Retrying. 
...After 

Try #2 
Before... 
> test1 running 
> test2 running 
test2(RetryTest) failed 
Retrying. 
...After 

Try #3 
Before... 
> test1 running 
> test2 running 
test2(RetryTest) failed 
No more retry ! 
...After 

私はtest2o.equals("foo");をコメントしていた場合は、すべてが正常に動作試してみてください:

Try #1 
Before... 
> test1 running 
> test2 running 
...After 
+0

これは良いスタートです。ただし、おそらく2つのルールを組み合わせて、テストが成功するか最大限の再試行が行われるまで、ループ内で再評価を続けるRetryRuleを持つことができます。 – dkatzel

+0

しかしopは、試行のために、各リトライの前後に@ beforeと@ afterが実行されることを望んでいます。 – ToYonos

3

私は私が正しく理解していればHow to Re-run failed JUnit tests immediately?

のオリジナルの回答は、あなたが持っている問題はRetryRuleにコードの前に実行されている@Beforeによるもので、@Afterがその後実行されています。

だからあなたの現在の行動のようなものです:

@Before 
@Retry 
test code 
@Retry 
@After 

しかし、あなたは、原則としてご@Before@Afterを実装することができます - まさにそのルールExternalResourceがあります。あなたは、原則として@Before@Afterを実装します:

@Rule public ExternalResource beforeAfter = new ExternalResource() { 
    public void before() { 
     // code that was in @Before 
    } 

    public void after() { 
     // code that was in @After 
    } 
} 

次にあなたが@Before@Afterを必要としません。これらのルールは、RuleChainを使用してチェーンすることができます。これはあなたのルールに実行順序を強制的に:

@Rule public RuleChain chain= RuleChain 
         .outerRule(new LoggingRule("outer rule") 
         .around(new LoggingRule("middle rule") 
         .around(new LoggingRule("inner rule"); 

ので、あなたの最終的な解決策のようなものもないだろう:あなたはRuleChainを使用している場合、あなたはもはや上@Rule注釈が必要であることを

private ExternalResource beforeAfter = ... 
private RetryRule retry = ... 

@Rule public RuleChain chain = RuleChain 
           .outerRule(retry) 
           .around(beforeAfter); 

注意ExternalResourceRetryRuleですが、RuleChainで行っています。

+0

しかし、この解決策では、前後のすべてのテストのための1回ではなく、すべてのテストの前と後に呼び出されますか?それは問題になる可能性があります。 – ToYonos

+0

@ Before/@ Afterはテストごとに実行されます - これは私が知っている限りOPが望んでいるものです –

+0

実際問題としてはあまり明確ではありません。 – ToYonos

関連する問題