2016-07-06 80 views
0

JUnit測試我已經被標註有重複最多N次,每次測試,直到第一次成功

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations=... 

測試的每一個的概率,採取單獨,失敗是相當低的。然而,由於大量的測試,所有測試成功的可能性,從而通過自動測試,也很低。測試成功後,一旦知道所測試的功能是正確實現的(當測試失敗時,它們總是失敗,因爲功能沒有正確實現,或者由於條件的某些組合而偶爾失敗測試環境,很少發生)。

所以我需要的是,對於一個固定的N,重複每次測試最多N次直到成功。只有在測試全部失敗N次的情況下,我纔會推斷出一些事情必須被打破。

一個能否提供一個清潔的方式來實現這一點(繼承了Spring的JUnit亞軍,也許?一些其他的方式?)

+1

爲什麼你有失敗的測試?這通常是設計不好的標誌,或者對不應該進行測試的事情進行過度熱切的測試。他們是否對您無法控制的組件進行集成測試? –

+0

@KoosGadellaa「你爲什麼沒有通過測試?」 - 這是一個很長的故事,不可能改變測試環境。重點是我只需要知道功能是否以足夠高的概率正確執行,這是一個需要快速解決的問題。 –

+0

也許你可以使用[Contiperf](http://databene.org/contiperf)運行N次,然後在每個測試用例中都有一個監聽器,它允許您輕鬆驗證測試用例是否有成功的結果?第一次成功運行後不會停止,但是 –

回答

0

這是一個基本的實現,這似乎工作(一個詮釋了其測試的測試類都重複方法直到成功爲止與@CustomJUnit4ClassRunner代替@SpringJUnit4ClassRunner):

import org.junit.internal.runners.model.ReflectiveCallable; 
import org.junit.internal.runners.statements.Fail; 
import org.junit.runners.model.FrameworkMethod; 
import org.junit.runners.model.InitializationError; 
import org.junit.runners.model.Statement; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

public class CustomJUnit4ClassRunner extends SpringJUnit4ClassRunner { 

    public CustomJUnit4ClassRunner(Class<?> clazz) 
      throws InitializationError { 
     super(clazz); 
    } 

    @Override 
    protected Statement methodBlock(FrameworkMethod frameworkMethod) { 
     Object testInstance; 
     try { 
      testInstance = new ReflectiveCallable() { 

       @Override 
       protected Object runReflectiveCall() throws Throwable { 
        return createTest(); 
       } 
      }.run(); 
     } 
     catch (Throwable ex) { 
      return new Fail(ex); 
     } 

     Statement statement = methodInvoker(frameworkMethod, testInstance); 
     statement = possiblyExpectingExceptions(frameworkMethod, testInstance, statement); 
     statement = withBefores(frameworkMethod, testInstance, statement); 
     statement = withAfters(frameworkMethod, testInstance, statement); 
     //statement = withRulesReflectively(frameworkMethod, testInstance, statement); 
     //statement = withPotentialRepeat(frameworkMethod, testInstance, statement); 
     statement = withPotentialTimeout(frameworkMethod, testInstance, statement); 
     statement = withRepeatUntilSuccess(frameworkMethod, testInstance, statement); 

     return statement; 
    } 

    private Statement withRepeatUntilSuccess(FrameworkMethod frameworkMethod, Object testInstance, Statement next) { 
     return new CustomTestRepeat(next, frameworkMethod.getMethod(), Constants.MAX_NUM); 
    } 

} 

連同以下類

import java.lang.reflect.Method; 

import org.junit.runners.model.Statement; 

public class CustomTestRepeat extends Statement { 

    private final Statement next; 

    private final Method testMethod; 

    private final int repeat; 

    public CustomTestRepeat(Statement next, Method testMethod, int repeat) { 
     this.next = next; 
     this.testMethod = testMethod; 
     this.repeat = Math.max(1, repeat); 
    } 

    @Override 
    public void evaluate() throws Throwable { 
     for (int i = 0; i < this.repeat - 1; i++) { 
      try { 
       this.next.evaluate(); 
      } 
      //Assertion errors are not instances of java.lang.Exception 
      catch (Throwable e) { 
       continue; 
      } 
      return; 
     } 
     this.next.evaluate(); 
    } 
}