package org.pitest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jmock.MockObjectTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Categories;
import org.junit.experimental.categories.Categories.IncludeCategory;
import org.junit.experimental.categories.Category;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.Suite.SuiteClasses;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.pitest.functional.Option;
import org.pitest.help.PitHelpError;
import org.pitest.junit.JUnitCompatibleConfiguration;
import org.pitest.testapi.Description;
import org.pitest.testapi.TestGroupConfig;
import org.pitest.testapi.TestListener;
import org.pitest.testapi.TestResult;
import org.pitest.testapi.TestUnit;
import org.pitest.testapi.execute.Container;
import org.pitest.testapi.execute.FindTestUnits;
import org.pitest.testapi.execute.Pitest;
import org.pitest.testapi.execute.containers.UnContainer;
import com.example.JUnitParamsTest;
public class TestJUnitConfiguration {
private final JUnitCompatibleConfiguration testee = new JUnitCompatibleConfiguration(
new TestGroupConfig(),
Collections.<String>emptyList());
private Pitest pitest;
private Container container;
@Mock
private TestListener listener;
@Before
public void createTestee() {
MockitoAnnotations.initMocks(this);
this.container = new UnContainer();
this.pitest = new Pitest(Collections.singletonList(this.listener));
}
public static class SimpleJUnit4Test {
@Test
public void testOne() {
}
}
@Test
public void shouldFindJunit4Tests() {
run(SimpleJUnit4Test.class);
verify(this.listener).onTestSuccess(any(TestResult.class));
}
public static class JUnit3TestWithSingleStringConstructorAndJUnit4Annotations
extends TestCase {
private final String name;
public JUnit3TestWithSingleStringConstructorAndJUnit4Annotations(
final String name) {
super(name);
this.name = name;
}
@Test
public void testOne() {
assertEquals("testOne", this.name);
}
@Test
public void testTwo() {
assertEquals("testTwo", this.name);
}
}
@Test
public void shouldCallSingleStringArgumentsConstructorWithTestNameWithAnnotations() {
run(JUnit3TestWithSingleStringConstructorAndJUnit4Annotations.class);
verify(this.listener, times(2)).onTestSuccess(any(TestResult.class));
}
public static class JUnit3TestWithSingleStringConstructor extends TestCase {
private final String name;
public JUnit3TestWithSingleStringConstructor(final String name) {
super(name);
this.name = name;
}
public void testOne() {
assertEquals("testOne", this.name);
}
public void testTwo() {
assertEquals("testTwo", this.name);
}
}
@Test
public void shouldCallSingleStringArgumentsConstructorWithTestName() {
run(JUnit3TestWithSingleStringConstructor.class);
verify(this.listener, times(2)).onTestSuccess(any(TestResult.class));
}
static class HideFromJunit1 {
public static class JUnit4TestWithUnmetExpectations {
@Test(expected = FileNotFoundException.class)
public void testOne() {
}
}
}
@Test
public void shouldFailTestsThatDoNotThrowExpectedException() {
run(HideFromJunit1.JUnit4TestWithUnmetExpectations.class);
verify(this.listener).onTestFailure(any(TestResult.class));
}
public static class JUnit4TestWithExpectations {
@Test(expected = FileNotFoundException.class)
public void testOne() throws FileNotFoundException {
throw new FileNotFoundException();
}
}
@Test
public void shouldPassTestsThatThrowExpectedException() {
run(JUnit4TestWithExpectations.class);
verify(this.listener).onTestSuccess(any(TestResult.class));
}
public static class SimpleJUnit3Test extends TestCase {
public void testOne() {
}
}
@Test
public void testFindJUnit3Tests() {
run(SimpleJUnit3Test.class);
verify(this.listener).onTestSuccess(any(TestResult.class));
}
public static class MixedJunit3And4Test extends TestCase {
@Test
public void testOne() {
}
}
@Test
public void shouldRunOnlyOneTestWhenMatchesBothJunit3And4Criteria() {
run(MixedJunit3And4Test.class);
verify(this.listener).onTestSuccess(any(TestResult.class));
}
public static class BaseTestCaseWithTest extends TestCase {
public void testFoo() {
}
@Test
public void testBar() {
}
}
public static class InheritedTest extends BaseTestCaseWithTest {
}
public static class OverridesTestInParent extends BaseTestCaseWithTest {
@Override
public void testFoo() {
}
}
@Test
public void shouldRunTestsInheritedFromParent() {
run(InheritedTest.class);
verify(this.listener, times(2)).onTestSuccess(any(TestResult.class));
}
@Test
public void testOverriddenTestsCalledOnlyOnce() {
run(OverridesTestInParent.class);
verify(this.listener, times(2)).onTestSuccess(any(TestResult.class));
}
static abstract class HideFromJunit4 {
public static class MixedJUnit3And4SetupAndTearDown extends TestCase {
public static int count = 0;
@Override
@Before
public void setUp() {
count++;
}
@Override
@After
public void tearDown() {
count = count + 10;
}
@Test
public void testCallCount() {
assertEquals(1, count);
}
}
}
@Test
public void shouldCallBeforeAndAfterMethodsEligableForBothJUnit3And4OnlyOnce() {
run(HideFromJunit4.MixedJUnit3And4SetupAndTearDown.class);
verify(this.listener).onTestSuccess(any(TestResult.class));
assertEquals(11, HideFromJunit4.MixedJUnit3And4SetupAndTearDown.count);
}
public static class TestWithTimeout {
@Test(timeout = 5)
public void testBar() {
for (int i = 0; i != 10; i++) {
try {
Thread.sleep(1000);
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
@Test
public void shouldTimeTestsOut() {
run(TestWithTimeout.class);
verify(this.listener).onTestFailure(any(TestResult.class));
}
@RunWith(Parameterized.class)
public static class ParameterisedTest {
int i;
public ParameterisedTest(final int i) {
this.i = i;
}
@Parameters
public static Collection<Object[]> params() {
return Arrays.asList(new Object[][] { { 1 }, { 2 }, { 3 } });
}
@Test
public void test() {
System.out.println(this.i);
}
@Test
public void test2() {
System.out.println("> " + this.i);
}
}
@Test
public void shouldCreateTestForEachParameterOfParameterizedTest() {
run(ParameterisedTest.class);
verify(this.listener, times(6)).onTestSuccess(any(TestResult.class));
}
static abstract class HideFromJUnit8 {
@RunWith(Theories.class)
public static class TheoriesTest {
@DataPoint
public static int i = 1;
@Theory
public void testTheory(final int i) {
assertEquals(1, i);
}
@Theory
public void failingTheory(final int i) {
fail();
}
@Theory
public void errorTheory(final int i) {
throw new NullPointerException();
}
}
}
@Test
public void shouldRunTestsCreatedByCustomRunners() {
run(HideFromJUnit8.TheoriesTest.class);
verify(this.listener).onTestSuccess(any(TestResult.class));
verify(this.listener, times(2)).onTestFailure(any(TestResult.class));
}
static abstract class HideFromJUnit9 {
public static class JMockTest extends MockObjectTestCase {
org.jmock.Mock mock;
@Override
public void setUp() {
this.mock = mock(Runnable.class);
this.mock.expects(once()).method("run");
}
public void testFails() {
}
public void testPasses() {
final Runnable r = (Runnable) this.mock.proxy();
r.run();
}
}
}
@Test
public void shouldRunJMock1Tests() {
run(HideFromJUnit9.JMockTest.class);
verify(this.listener).onTestSuccess(any(TestResult.class));
verify(this.listener).onTestFailure(any(TestResult.class));
}
public static interface Marker {
}
@RunWith(Categories.class)
@IncludeCategory(Marker.class)
@SuiteClasses({ MarkerTest1.class, MarkerTest2.class })
public static class CustomSuite {
}
@Category(Marker.class)
public static class MarkerTest1 {
@Test
public void one() {
}
@Test
public void two() {
}
}
@Category(Marker.class)
public static class MarkerTest2 {
@Test
public void one() {
}
@Test
public void two() {
}
}
@Test
public void shouldSplitTestInSuitesIntoSeperateUnitsWhenUsingNonStandardSuiteRunners() {
final List<TestUnit> actual = find(CustomSuite.class);
System.out.println(actual);
assertEquals(4, actual.size());
}
@Ignore
public static class AnnotatedAsIgnored {
@Test
public void ignoreMe() {
}
@Test
public void ignoreMeToo() {
}
}
@Test
public void shouldSkipAllMethodsInClassAnnotatedWithIgnore() {
run(AnnotatedAsIgnored.class);
verify(this.listener, times(1)).onTestSkipped((any(TestResult.class)));
verify(this.listener, never()).onTestStart(any(Description.class));
}
public static class HasMethodAnnotatedAsIgnored {
@Test
@Ignore
public void ignoreMe() {
}
@Test
@Ignore
public void ignoreMeToo() {
}
@Test
public void dontIgnoreMe() {
}
}
@Test
public void shouldSkipAllMethodsAnnotatedWithIgnore() {
run(HasMethodAnnotatedAsIgnored.class);
verify(this.listener, times(2)).onTestSkipped((any(TestResult.class)));
verify(this.listener).onTestSuccess((any(TestResult.class)));
}
public static class HasMethodAnnotatedAsIgnoredAndBeforeClassAnnotation {
@BeforeClass
public static void foo() {
}
@Test
@Ignore
public void ignoreMe() {
}
@Test
public void dontIgnoreMe() {
}
}
@Test
public void shouldNotSkipEnabledTestsInAClassWithBeforeClassAnotationAndAnIgnoredTest() {
run(HasMethodAnnotatedAsIgnoredAndBeforeClassAnnotation.class);
verify(this.listener).onTestSuccess((any(TestResult.class)));
}
@Test
public void shouldNotReportAnErrorWhenCorrectJUnitVersionOnClasspath() {
assertEquals(Option.<PitHelpError> none(), this.testee.verifyEnvironment());
}
public static class HasAssumptionFailure {
@Test
public void testWithFailedAssumption() {
assumeTrue(false);
}
}
@Test
public void shouldTreatAssumptionFailuesAsSuccess() {
// see http://junit.sourceforge.net/doc/ReleaseNotes4.4.html#assumptions
run(HasAssumptionFailure.class);
verify(this.listener).onTestSuccess((any(TestResult.class)));
}
public static class JUnit3Test extends TestCase {
public void testSomething() {
}
public void testSomethingElse() {
}
}
public static class JUnit3SuiteMethod extends TestCase {
public JUnit3SuiteMethod(final String testName) {
super(testName);
}
public static junit.framework.Test suite() {
final TestSuite suite = new TestSuite();
suite.addTest(new JUnit3Test());
return suite;
}
}
@Test
public void shouldDetectTestInJUnitThreeSuiteMethods() {
final List<TestUnit> actual = find(JUnit3SuiteMethod.class);
assertEquals(2, actual.size());
}
public static class OwnSuiteMethod extends TestCase {
public static TestSuite suite() {
return new TestSuite(OwnSuiteMethod.class);
}
public void testOne() {
}
}
@Test
public void shouldFindTestsInClassWithASuiteMethod() {
final List<TestUnit> actual = find(OwnSuiteMethod.class);
assertEquals(1, actual.size());
}
public static class NoSuitableConstructor extends TestCase {
public NoSuitableConstructor(final int i, final int j, final long l) {
}
public void testSomething() {
}
}
@Test
public void shouldNotFindTestsInJUnit3TestsWithoutASuitableConstructor() {
final List<TestUnit> actual = find(NoSuitableConstructor.class);
assertEquals(0, actual.size());
}
@Test
// see http://code.google.com/p/junitparams/
public void shouldFindTestInJUnitParamsTest() {
run(JUnitParamsTest.class);
verify(this.listener, times(3)).onTestSuccess(any(TestResult.class));
}
public static class HasOneMethodAnnotatedAsIgnored {
@Test
public void dontIgnoreMe() {
}
@Test
@Ignore
public void ignoreMe() {
}
@Test
public void dontIgnoreMeEither() {
}
}
@Test
public void shouldRunOtherMethodsInAClassWithOneIgnoredTest() {
run(HasOneMethodAnnotatedAsIgnored.class);
verify(this.listener, times(2)).onTestSuccess((any(TestResult.class)));
}
private void run(final Class<?> clazz) {
this.pitest.run(this.container, this.testee, clazz);
}
private List<TestUnit> find(Class<?> clazz) {
FindTestUnits finder = new FindTestUnits(this.testee);
return finder.findTestUnitsForAllSuppliedClasses(Arrays
.<Class<?>> asList(clazz));
}
}