2016-07-06 1 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(); 
    } 
}