Introduce @Repeat and RepeatRule for repeatable @Test methods

With thanks to original author Frank Appel (@fappel)

See:
 - https://gist.github.com/fappel/8bcb2aea4b39ff9cfb6e
 - http://www.codeaffine.com/2013/04/10/running-junit-tests-repeatedly-without-loops/
This commit is contained in:
Chris Beams 2014-11-06 13:02:49 +01:00
parent 8b6f0ac64e
commit 1a92b05bf4
No known key found for this signature in database
GPG Key ID: 3D214F8F5BC5ED73
3 changed files with 163 additions and 0 deletions

View File

@ -0,0 +1,38 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Method-level annotation to be used in connection with {@link RepeatRule} to cause a
* given {@link org.junit.Test} method to be repeated a specified number of times.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Repeat {
/**
* Specifies the number of times to repeat the annotated {@link org.junit.Test}.
*/
int value();
}

View File

@ -0,0 +1,57 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.util;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/**
* @see {@link Repeat}
*/
public class RepeatRule implements TestRule {
private static class RepeatStatement extends Statement {
private final int times;
private final Statement statement;
private RepeatStatement(int times, Statement statement) {
this.times = times;
this.statement = statement;
}
@Override
public void evaluate() throws Throwable {
for (int i = 0; i < times; 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(times, statement);
}
return result;
}
}

View File

@ -0,0 +1,68 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.util;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.*;
public class RepeatRuleTests {
private static final int EXPECTED_COUNT = 10;
private static int ACTUAL_BEFORE_COUNT;
private static int ACTUAL_TEST_COUNT;
private static int ACTUAL_AFTER_COUNT;
public @Rule RepeatRule repeatRule = new RepeatRule();
@BeforeClass
public static void beforeTests() {
ACTUAL_BEFORE_COUNT = 0;
ACTUAL_TEST_COUNT = 0;
ACTUAL_AFTER_COUNT = 0;
}
@Before
public void setUp() {
ACTUAL_BEFORE_COUNT++;
}
@Test
@Repeat(EXPECTED_COUNT)
public void shouldBeRepeated() {
ACTUAL_TEST_COUNT++;
}
@After
public void tearDown() {
ACTUAL_AFTER_COUNT++;
}
@AfterClass
public static void afterTests() {
assertThat(ACTUAL_BEFORE_COUNT, equalTo(EXPECTED_COUNT));
assertThat(ACTUAL_TEST_COUNT, equalTo(EXPECTED_COUNT));
assertThat(ACTUAL_AFTER_COUNT, equalTo(EXPECTED_COUNT));
}
}