Легкий способ повторения одного и того же теста на юнитах снова и снова?
Как и в названии, я ищу несколько простых способов запуска тестов JUnit 4.x несколько раз подряд, используя Eclipse.
Пример будет выполнять один и тот же тест 10 раз подряд и сообщать результат.
У нас уже есть сложный способ сделать это, но я ищу простой способ сделать это, чтобы я мог быть уверен в том, что проверенный флай-тест, который я пытался исправить, остается фиксированным.
Идеальное решение было бы плагином/установкой/установкой Eclipse, о которой я не знаю.
Ответы
Ответ 1
Самый простой (как и в случае с @RunWith(Parameterized.class)
количеством нового кода) способ сделать это - запустить тест в качестве параметризованного теста (аннотировать с помощью @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");
}
}
С вышесказанным можно даже сделать это с помощью конструктора без параметров, но я не уверен, что авторы фреймворка намеревались это или если это произойдет в будущем.
Если вы реализуете свой собственный бегун, то вы можете запустить runner 10 раз. Если вы используете сторонний участник, то с 4.7 вы можете использовать новую аннотацию @Rule
и реализовать интерфейс MethodRule
чтобы он @Rule
и выполнил его 10 раз в цикле for. Нынешним недостатком такого подхода является то, что @Before
и @After
запускаются только один раз. Вероятно, это изменится в следующей версии JUnit (@Before
будет запускаться после @Rule
), но независимо от того, будете ли вы действовать в одном экземпляре объекта (что не соответствует Parameterized
бегуну). Это предполагает, что любой бегун, которым вы управляете классом, правильно распознает аннотации @Rule
. Это только в случае, если он делегирует бегунов JUnit.
Если вы работаете с пользовательским бегуном, который не распознает аннотацию @Rule
, вы действительно застряли в том, что вам нужно написать свой собственный бегун, который соответствующим образом делегирует этому Runner и запускает его 10 раз.
Обратите внимание, что есть другие способы потенциально решить эту проблему (например, бегун Теории), но все они требуют бегуна. К сожалению, JUnit в настоящее время не поддерживает слои бегунов. Это бегун, который соединяет других бегунов.
Ответ 2
Я обнаружил, что примечание Spring repeat полезно для такого рода вещей:
@Repeat(value = 10)
Последний (Spring Framework 4.3.11.RELEASE API) doc:
Ответ 3
С помощью IntelliJ вы можете сделать это из тестовой конфигурации. После того как вы откроете это окно, вы можете запустить тест сколько угодно раз,
![введите описание изображения здесь]()
когда вы запустите тест, intellij выполнит все тесты, которые вы выбрали, для количества раз, когда вы указали.
Пример: 624 теста 10 раз:
![введите описание изображения здесь]()
Ответ 4
Вдохновленный это решение:
Использовать аннотацию @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 (который включает этот патч).
Ответ 5
С JUnit 5 я смог решить эту проблему, используя аннотацию @RepeatedTest:
@RepeatedTest(10)
public void testMyCode() {
//your test code goes here
}
Обратите внимание, что @Test
аннотация не должна использоваться вместе с @RepeatedTest
.
Ответ 6
Что-то не так:
@Test
void itWorks() {
// stuff
}
@Test
void itWorksRepeatably() {
for (int i = 0; i < 10; i++) {
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.
Ответ 8
Это работает намного легче для меня.
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;
}
}
Ответ 9
Я создаю модуль, который позволяет делать такие тесты. Но он фокусируется не только на повторении. Но в гарантии, что какой-то фрагмент кода является потокобезопасным.
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");
}
}
Это проект с открытым исходным кодом. Не стесняйтесь улучшаться.
Ответ 10
Вы можете запустить свой 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
}
}
}
}