2009-09-29 4 views
71

Как и в названии, я ищу простой способ запускать тесты JUnit 4.x несколько раз подряд, используя Eclipse.Легкий способ запуска одного и того же теста юнита снова и снова?

Пример будет проходить один и тот же тест 10 раз подряд и сообщать результат.

У нас уже есть сложный способ сделать это, но я ищу простой способ сделать это, чтобы я мог быть уверен в том, что проверенный мной фиктивный тест, который я пытался исправить, остается фиксированным.

Идеальное решение - это плагин/настройка/функция Eclipse, о которых я не знаю.

+3

Мне очень интересно, почему вы хотели бы сделать это. – Buhb

+0

Я запускаю большой тест с черным ящиком, сделал небольшое изменение и хочу посмотреть, как это повлияло на стабильность этого ранее плохого теста. –

+0

Это действительно, за исключением того, что вы хотите, чтобы он работал до отказа, в то время как я просто хочу запускать его несколько раз, что может повлиять на ответы, которые я получаю. –

ответ

91

Проще всего (как минимум в t нового кода), чтобы сделать это, запустить тест в качестве параметризованного теста (аннотировать с @RunWith(Parameterized.class) и добавить метод для предоставления 10 пустых параметров). Таким образом, среда будет проходить тест 10 раз.

Этот тест должен быть единственным тестом в классе или лучше всего использовать все методы тестирования, которые должны выполняться 10 раз в классе.

Вот пример:

@RunWith(Parameterized.class) 
public class RunTenTimes { 

    @Parameterized.Parameters 
    public static Object[][] data() { 
     return new Object[10][0]; 
    } 

    public RunTenTimes() { 
    } 

    @Test 
    public void runsTenTimes() { 
     System.out.println("run"); 
    } 
} 

С выше, можно даже сделать это с помощью конструктора параметров меньше, но я не уверен, что если каркасные авторы Подразумевается, что, или, если будет ломаться в будущем.

Если вы внедряете свой собственный бегун, то вы можете провести тест 10 раз подряд. Если вы используете сторонний бегун, то с 4.7 вы можете использовать новую аннотацию @Rule и реализовать интерфейс MethodRule, чтобы он принял оператор и выполнил его 10 раз в цикле for. Нынешним недостатком такого подхода является то, что @Before и @After запускаются только один раз. Вероятно, это изменится в следующей версии JUnit (@Before будет работать после @Rule), но независимо от того, будете ли вы действовать на одном экземпляре объекта (что не соответствует бегуну Parameterized). Это предполагает, что любой бегун, которым вы управляете классом, правильно распознает аннотации @Rule. Это только в случае, если он делегирует бегунов JUnit.

Если вы работаете с пользовательским бегуном, который не распознает аннотацию @Rule, то вы действительно застряли в том, что вам нужно написать свой собственный бегун, который соответствующим образом делегирует этому Runner и запускает его 10 раз.

Обратите внимание, что есть другие способы потенциально решить эту проблему (например, бегун Теория), но для всех них требуется бегун. К сожалению, JUnit в настоящее время не поддерживает слои бегунов. Это бегун, который соединяет других бегунов.

+1

Святое дерьмо, я думаю, что вы, возможно, исправили хватку, которую я имел о JUnit в течение долгого времени - спасибо! :) – aperkins

+1

К сожалению, я уже бегу @RunWith с другим бегуном, но в противном случае это было бы идеальным решением. –

+0

Да, это решение, которое я хотел бы иметь, хотя и которое будет лучше для большинства людей, поэтому я собираюсь идти дальше и принимать ответ. –

45

Я обнаружил, что повторение аннотация Spring является полезной для такого рода вещь:

@Repeat(value = 10) 

Последние (Spring Framework 4.3.11.RELEASE API) документ:

+20

Изменение тестовых фреймворков - это не то, что я бы назвал простым способом сделать это. –

+0

Вам не нужно менять свой тестовый интерфейс - он отлично работает с JUnit. Главный недостаток заключается в том, что JUnit все еще рассматривает его как единый тест. Таким образом, в первый раз, когда он сломается, выполнение остановится. Однако, если вы еще не используете Spring, то это, вероятно, не так, как вы хотите ... – tveon

+0

Кажется, не работает для меня (весна 4.3.6 через Spring Boot 1.5.1) –

9

Что-нибудь случилось с:

@Test 
void itWorks() { 
    // stuff 
} 

@Test 
void itWorksRepeatably() { 
    for (int i = 0; i < 10; i++) { 
     itWorks(); 
    } 
} 

В отличие от случая, когда вы проверяете каждого из массива значений, вы не особенно волнует, которые работают не удалось.

Не нужно делать в настройках или аннотации, что вы можете делать в коде.

+1

Я бы хотел запустить несколько тестов как обычные модульные тесты и получить трассировку и статус для каждого из них. –

+13

В этом случае «@Before» и «@After» s не будут запущены – Bogdan

+1

Это вместе с ручным вызовом аннотированного метода '@ Before' до' itWorks() 'решило мою проблему. –

7

Там в перемежающихся аннотациях в tempus-fugit библиотеке, которая работает с JUnit 4,7-х @Rule повторить тест, несколько раз или с @RunWith.

Например,

@RunWith(IntermittentTestRunner.class) 
public class IntermittentTestRunnerTest { 

    private static int testCounter = 0; 

    @Test 
    @Intermittent(repition = 99) 
    public void annotatedTest() { 
     testCounter++; 
    } 
} 

После выполнения теста (с IntermittentTestRunner в @RunWith), testCounter будет равна 99.

+0

Да, это та же проблема, уже с использованием другого бегуна, и поэтому я не могу использовать эту идею. –

+0

Да, у меня такая же проблема с RunWith ... Как бы то ни было, я изменил tempus-fugit, чтобы обойти его немного, вы можете использовать @Rule, а не бегун, когда хотите многократно запускать. Вы отмечаете это с помощью @Repeating вместо прерывистого. Версия правила не будет запускать @ Before/@ Afters. Для получения дополнительной информации см. Http://tempus-fugit.googlecode.com/svn/site/documentation/concurrency.html#JUnit_Integration (прокрутите вниз до загрузки/тестирования). – Toby

7

Это работает намного проще для меня.

public class RepeatTests extends TestCase { 

    public static Test suite() { 
     TestSuite suite = new TestSuite(RepeatTests.class.getName()); 

     for (int i = 0; i < 10; i++) {    
     suite.addTestSuite(YourTest.class);    
     } 

     return suite; 
    } 
} 
+0

Высокие, как не использует другую структуру и фактически работает с JUnit 3 (критической для Android) –

+1

Реализация с JUnit4 может быть сделана с помощью Бегуна: 'общественного класса RepeatRunner расширяет BlockJUnit4ClassRunner { \t общественного RepeatRunner (Класс Klass) бросает InitializationError { \t \t super (класс); \t} \t \t @Override общественного недействительными запуска (конечная RunNotifier уведомитель) { \t \t для (INT I = 0; г <10; я ++) { \t \t \t super.run (уведомитель); \t \t} \t} } ' Хотя по крайней мере, в Eclipse, JUnit плагин вы получите результаты, как: "10/1 тесты прошли" –

21

Вдохновленный на this solution:

Используйте @Repeat аннотацию, как это:

public class MyTestClass { 

    @Rule 
    public RepeatRule repeatRule = new RepeatRule(); 

    @Test 
    @Repeat(10) 
    public void testMyCode() { 
     //your test code goes here 
    } 
} 

Вам нужно только эти два класса:

Repeat.java:

import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 
import static java.lang.annotation.ElementType.METHOD; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Retention(RetentionPolicy.RUNTIME) 
@Target({ METHOD, ANNOTATION_TYPE }) 
public @interface Repeat { 
    int value() default 1; 
} 

RepeatRule.java:

import org.junit.rules.TestRule; 
import org.junit.runner.Description; 
import org.junit.runners.model.Statement; 

public class RepeatRule implements TestRule { 

    private static class RepeatStatement extends Statement { 
     private final Statement statement; 
     private final int repeat;  

     public RepeatStatement(Statement statement, int repeat) { 
      this.statement = statement; 
      this.repeat = repeat; 
     } 

     @Override 
     public void evaluate() throws Throwable { 
      for (int i = 0; i < repeat; i++) { 
       statement.evaluate(); 
      } 
     } 

    } 

    @Override 
    public Statement apply(Statement statement, Description description) { 
     Statement result = statement; 
     Repeat repeat = description.getAnnotation(Repeat.class); 
     if (repeat != null) { 
      int times = repeat.value(); 
      result = new RepeatStatement(statement, times); 
     } 
     return result; 
    } 
} 

2016-10-25 Редактировать: Для того чтобы использовать это решение при использовании @RunWith(PowerMockRunner.class), обновления для Powermock 1.6.5 (который включает в себя this patch).

+0

Да. Как вы выполняете тесты? –

+0

Я сам не использую eclipse. Может быть, вы не используете тестовый бегун junut 4? (см. [doc «Настройка тестовой конфигурации»] (http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2FgettingStarted%2Fqs-junit.htm)) –

+2

Недостаточный приведенный выше код. Правило должно быть _instantiated_ дополнительно в качестве члена тестового класса. Посмотрите оригинальное сообщение: http://www.codeaffine.com/2013/04/10/running-junit-tests-repeatedly-without-loops/ – Bananeweizen

0

Я строю модуль, который позволяет выполнять такие тесты. Но он фокусируется не только на повторении. Но в гарантии, что какой-то фрагмент кода является потокобезопасным.

https://github.com/anderson-marques/concurrent-testing

Maven зависимостей:

<dependency> 
    <groupId>org.lite</groupId> 
    <artifactId>concurrent-testing</artifactId> 
    <version>1.0.0</version> 
</dependency> 

Пример использования:

package org.lite.concurrent.testing; 

import org.junit.Assert; 
import org.junit.Rule; 
import org.junit.Test; 
import ConcurrentTest; 
import ConcurrentTestsRule; 

/** 
* Concurrent tests examples 
*/ 
public class ExampleTest { 

    /** 
    * Create a new TestRule that will be applied to all tests 
    */ 
    @Rule 
    public ConcurrentTestsRule ct = ConcurrentTestsRule.silentTests(); 

    /** 
    * Tests using 10 threads and make 20 requests. This means until 10 simultaneous requests. 
    */ 
    @Test 
    @ConcurrentTest(requests = 20, threads = 10) 
    public void testConcurrentExecutionSuccess(){ 
     Assert.assertTrue(true); 
    } 

    /** 
    * Tests using 10 threads and make 20 requests. This means until 10 simultaneous requests. 
    */ 
    @Test 
    @ConcurrentTest(requests = 200, threads = 10, timeoutMillis = 100) 
    public void testConcurrentExecutionSuccessWaitOnly100Millissecond(){ 
    } 

    @Test(expected = RuntimeException.class) 
    @ConcurrentTest(requests = 3) 
    public void testConcurrentExecutionFail(){ 
     throw new RuntimeException("Fail"); 
    } 
} 

Это проект с открытым исходным кодом. Не стесняйтесь улучшаться.

7

С JUnit 5 Я был в состоянии решить эту проблему с помощью @RepeatedTest аннотацию:

@RepeatedTest(10) 
public void testMyCode() { 
    //your test code goes here 
} 

Обратите внимание, что @Test аннотации не следует использовать вместе с @RepeatedTest.

+0

Звучит очень многообещающе, просто отметить, что еще нет версии для релиза. –

+1

JUnit 5 ударил GA пару недель назад. – mkobit

0

Вы можете запустить тест JUnit из основного метода и повторить столько раз, что вам нужно:

package tests; 

import static org.junit.Assert.*; 

import org.junit.Test; 
import org.junit.runner.Result; 

public class RepeatedTest { 

    @Test 
    public void test() { 
     fail("Not yet implemented"); 
    } 

    public static void main(String args[]) { 

     boolean runForever = true; 

     while (runForever) { 
      Result result = org.junit.runner.JUnitCore.runClasses(RepeatedTest.class); 

      if (result.getFailureCount() > 0) { 
       runForever = false; 
       //Do something with the result object 

      } 
     } 

    } 

} 
10

С IntelliJ, вы можете сделать это из тестовой конфигурации. Как только вы откроете это окно, вы можете запустить тест сколько угодно раз.

enter image description here

при выполнении теста, IntelliJ выполнит все тесты были выбраны для того, сколько раз вы указали.

Пример запуска 624 тестов в 10 раз: enter image description here

+0

Это прекрасно, теперь, если вы можете указать на способ затмения сделать это, это ответит на вопрос OP о точке – khal

Смежные вопросы