From 4da2be7e7a034efa8fe4aae55e3dee7d34bab650 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Wed, 29 Apr 2009 21:29:53 +0000 Subject: [PATCH] [SPR-5145] Improved test suite for SpringJUnit4ClassRunner: added specific unit tests for test timeouts, repeated tests, and expected exceptions. git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1077 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../ExpectedExceptionSpringRunnerTests.java | 87 ++++++++++ .../FailingBeforeAndAfterMethodsTests.java | 65 +++----- .../junit4/RepeatedSpringRunnerTests.java | 151 ++++++++++++++++++ .../junit4/SpringJUnit4SuiteTests.java | 80 ++++------ .../junit4/TimedSpringRunnerTests.java | 97 +++++++++++ .../context/junit4/TrackingRunListener.java | 68 ++++++++ 6 files changed, 454 insertions(+), 94 deletions(-) create mode 100644 org.springframework.test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java create mode 100644 org.springframework.test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java create mode 100644 org.springframework.test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java create mode 100644 org.springframework.test/src/test/java/org/springframework/test/context/junit4/TrackingRunListener.java diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java new file mode 100644 index 00000000000..1ce10ff9ca3 --- /dev/null +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java @@ -0,0 +1,87 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context.junit4; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.JUnit4; +import org.springframework.test.annotation.ExpectedException; +import org.springframework.test.context.TestExecutionListeners; + +/** + * Verifies proper handling of the following in conjunction with the + * {@link SpringJUnit4ClassRunner}: + * + * + * @author Sam Brannen + * @since 3.0 + */ +@RunWith(JUnit4.class) +public class ExpectedExceptionSpringRunnerTests { + + @Test + public void timedTests() throws Exception { + Class testClass = ExpectedExceptionSpringRunnerTestCase.class; + TrackingRunListener listener = new TrackingRunListener(); + RunNotifier notifier = new RunNotifier(); + notifier.addListener(listener); + + new SpringJUnit4ClassRunner(testClass).run(notifier); + assertEquals("Verifying number of failures for test class [" + testClass + "].", 1, + listener.getTestFailureCount()); + assertEquals("Verifying number of tests started for test class [" + testClass + "].", 3, + listener.getTestStartedCount()); + assertEquals("Verifying number of tests finished for test class [" + testClass + "].", 3, + listener.getTestFinishedCount()); + } + + + @RunWith(SpringJUnit4ClassRunner.class) + @TestExecutionListeners( {}) + public static final class ExpectedExceptionSpringRunnerTestCase { + + // Should Pass. + @Test(expected = IndexOutOfBoundsException.class) + public void verifyJUnitExpectedException() { + new ArrayList().get(1); + } + + // Should Pass. + @Test + @ExpectedException(IndexOutOfBoundsException.class) + public void verifySpringExpectedException() { + new ArrayList().get(1); + } + + // Should Fail due to duplicate configuration. + @Test(expected = IllegalStateException.class) + @ExpectedException(IllegalStateException.class) + public void verifyJUnitAndSpringExpectedException() { + new ArrayList().get(1); + } + + } + +} diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsTests.java index a1fcc57abe2..ec5ffd493fd 100644 --- a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsTests.java +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,18 +17,16 @@ package org.springframework.test.context.junit4; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import java.util.Arrays; import java.util.Collection; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; import org.junit.runner.notification.RunNotifier; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; - import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestContext; import org.springframework.test.context.TestExecutionListener; @@ -39,15 +37,15 @@ import org.springframework.test.context.transaction.BeforeTransaction; /** *

- * JUnit 4 based unit test for verifying that 'before' and 'after' - * methods of {@link TestExecutionListener TestExecutionListeners} as well as - * {@link BeforeTransaction @BeforeTransaction} and - * {@link AfterTransaction @AfterTransaction} methods can fail a test in a JUnit - * 4.4 environment, as requested in before' and ' + * after' methods of {@link TestExecutionListener + * TestExecutionListeners} as well as {@link BeforeTransaction + * @BeforeTransaction} and {@link AfterTransaction @AfterTransaction} + * methods can fail a test in a JUnit 4.4 environment, as requested in SPR-3960. *

- * + * * @author Sam Brannen * @since 2.5 */ @@ -63,39 +61,23 @@ public class FailingBeforeAndAfterMethodsTests { @Parameters public static Collection testData() { - return Arrays.asList(new Object[][] { - - { AlwaysFailingBeforeTestMethodTestCase.class }, - - { AlwaysFailingAfterTestMethodTestCase.class }, - - { FailingBeforeTransactionalTestCase.class }, - - { FailingAfterTransactionalTestCase.class } - + return Arrays.asList(new Object[][] {// + // + { AlwaysFailingBeforeTestMethodTestCase.class },// + { AlwaysFailingAfterTestMethodTestCase.class },// + { FailingBeforeTransactionalTestCase.class },// + { FailingAfterTransactionalTestCase.class } // }); } @Test public void runTestAndAssertCounters() throws Exception { - final FailureTrackingRunListener failureTrackingRunListener = new FailureTrackingRunListener(); + final TrackingRunListener listener = new TrackingRunListener(); final RunNotifier notifier = new RunNotifier(); - notifier.addListener(failureTrackingRunListener); + notifier.addListener(listener); new SpringJUnit4ClassRunner(this.clazz).run(notifier); - assertEquals("Verifying number of failures for test class [" + this.clazz + "].", 1, - failureTrackingRunListener.failureCount); - } - - - static class FailureTrackingRunListener extends RunListener { - - int failureCount = 0; - - - public void testFailure(Failure failure) throws Exception { - this.failureCount++; - } + assertEquals("Verifying number of failures for test class [" + this.clazz + "].", 1, listener.getTestFailureCount()); } @@ -103,20 +85,18 @@ public class FailingBeforeAndAfterMethodsTests { @Override public void beforeTestMethod(TestContext testContext) { - org.junit.Assert.fail("always failing beforeTestMethod()"); + fail("always failing beforeTestMethod()"); } } - static class AlwaysFailingAfterTestMethodTestExecutionListener extends AbstractTestExecutionListener { @Override public void afterTestMethod(TestContext testContext) { - org.junit.Assert.fail("always failing afterTestMethod()"); + fail("always failing afterTestMethod()"); } } - @TestExecutionListeners(value = { AlwaysFailingBeforeTestMethodTestExecutionListener.class }, inheritListeners = false) public static class AlwaysFailingBeforeTestMethodTestCase extends AbstractJUnit4SpringContextTests { @@ -125,7 +105,6 @@ public class FailingBeforeAndAfterMethodsTests { } } - @TestExecutionListeners(value = { AlwaysFailingAfterTestMethodTestExecutionListener.class }, inheritListeners = false) public static class AlwaysFailingAfterTestMethodTestCase extends AbstractJUnit4SpringContextTests { @@ -134,7 +113,6 @@ public class FailingBeforeAndAfterMethodsTests { } } - @ContextConfiguration(locations = { "FailingBeforeAndAfterMethodsTests-context.xml" }) public static class FailingBeforeTransactionalTestCase extends AbstractTransactionalJUnit4SpringContextTests { @@ -144,11 +122,10 @@ public class FailingBeforeAndAfterMethodsTests { @BeforeTransaction public void beforeTransaction() { - org.junit.Assert.fail("always failing beforeTransaction()"); + fail("always failing beforeTransaction()"); } } - @ContextConfiguration(locations = { "FailingBeforeAndAfterMethodsTests-context.xml" }) public static class FailingAfterTransactionalTestCase extends AbstractTransactionalJUnit4SpringContextTests { @@ -158,7 +135,7 @@ public class FailingBeforeAndAfterMethodsTests { @AfterTransaction public void afterTransaction() { - org.junit.Assert.fail("always failing afterTransaction()"); + fail("always failing afterTransaction()"); } } diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java new file mode 100644 index 00000000000..40c1d59c10c --- /dev/null +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java @@ -0,0 +1,151 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context.junit4; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.springframework.test.annotation.Repeat; +import org.springframework.test.annotation.Timed; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; + +/** + * Verifies proper handling of the following in conjunction with the + * {@link SpringJUnit4ClassRunner}: + *
    + *
  • Spring's {@link Repeat @Repeat}
  • + *
  • Spring's {@link Timed @Timed}
  • + *
+ * + * @author Sam Brannen + * @since 3.0 + */ +@RunWith(Parameterized.class) +public class RepeatedSpringRunnerTests { + + private static final AtomicInteger invocationCount = new AtomicInteger(); + + private final Class testClass; + + private final int expectedFailureCount; + + private final int expectedTestStartedCount; + + private final int expectedTestFinishedCount; + + private final int expectedInvocationCount; + + + public RepeatedSpringRunnerTests(Class testClass, int expectedFailureCount, + int expectedTestStartedCount, int expectedTestFinishedCount, int expectedInvocationCount) { + this.testClass = testClass; + this.expectedFailureCount = expectedFailureCount; + this.expectedTestStartedCount = expectedTestStartedCount; + this.expectedTestFinishedCount = expectedTestFinishedCount; + this.expectedInvocationCount = expectedInvocationCount; + } + + @Parameters + public static Collection repetitionData() { + return Arrays.asList(new Object[][] {// + // + { NonAnnotatedRepeatedTestCase.class, 0, 1, 1, 1 },// + { DefaultRepeatValueRepeatedTestCase.class, 0, 1, 1, 1 },// + { NegativeRepeatValueRepeatedTestCase.class, 0, 1, 1, 1 },// + { RepeatedFiveTimesRepeatedTestCase.class, 0, 1, 1, 5 } // + }); + } + + @Test + public void assertRepetitions() throws Exception { + TrackingRunListener listener = new TrackingRunListener(); + RunNotifier notifier = new RunNotifier(); + notifier.addListener(listener); + invocationCount.set(0); + + new SpringJUnit4ClassRunner(this.testClass).run(notifier); + assertEquals("Verifying number of failures for test class [" + this.testClass + "].", + this.expectedFailureCount, listener.getTestFailureCount()); + assertEquals("Verifying number of tests started for test class [" + this.testClass + "].", + this.expectedTestStartedCount, listener.getTestStartedCount()); + assertEquals("Verifying number of tests finished for test class [" + this.testClass + "].", + this.expectedTestFinishedCount, listener.getTestFinishedCount()); + assertEquals("Verifying number of invocations for test class [" + this.testClass + "].", + this.expectedInvocationCount, invocationCount.get()); + } + + + @RunWith(SpringJUnit4ClassRunner.class) + @TestExecutionListeners( {}) + @ContextConfiguration(locations = {}) + public abstract static class AbstractRepeatedTestCase { + + protected void incrementInvocationCount() throws IOException { + invocationCount.incrementAndGet(); + } + } + + public static final class NonAnnotatedRepeatedTestCase extends AbstractRepeatedTestCase { + + @Test + @Timed(millis = 10000) + public void testNonAnnotated() throws Exception { + incrementInvocationCount(); + } + } + + public static final class DefaultRepeatValueRepeatedTestCase extends AbstractRepeatedTestCase { + + @Test + @Repeat + @Timed(millis = 10000) + public void testDefaultRepeatValue() throws Exception { + incrementInvocationCount(); + } + } + + public static final class NegativeRepeatValueRepeatedTestCase extends AbstractRepeatedTestCase { + + @Test + @Repeat(-5) + @Timed(millis = 10000) + public void testNegativeRepeatValue() throws Exception { + incrementInvocationCount(); + } + } + + public static final class RepeatedFiveTimesRepeatedTestCase extends AbstractRepeatedTestCase { + + @Test + @Repeat(5) + @Timed(millis = 10000) + public void testRepeatedFiveTimes() throws Exception { + incrementInvocationCount(); + } + } + +} diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java index 8484f1a720c..7d2289a5a64 100644 --- a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,13 +19,12 @@ package org.springframework.test.context.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; - import org.springframework.test.context.SpringRunnerContextCacheTests; /** *

- * JUnit 4 based test suite for tests involving {@link SpringJUnit4ClassRunner}, - * {@link SpringMethodRoadie}, and Spring's annotation-based test support. + * JUnit 4 based test suite for tests involving {@link SpringJUnit4ClassRunner} + * and the Spring TestContext Framework. *

*

* This test suite serves a dual purpose of verifying that tests run with @@ -37,57 +36,38 @@ import org.springframework.test.context.SpringRunnerContextCacheTests; * from an automated build process, test runner, etc. that is configured to run * tests based on a "*Tests.class" pattern match. *

- * + * * @author Sam Brannen * @since 2.5 */ @RunWith(Suite.class) // Note: the following 'multi-line' layout is for enhanced code readability. -@SuiteClasses( { - -StandardJUnit4FeaturesTests.class, - -StandardJUnit4FeaturesSpringRunnerTests.class, - -EnabledAndIgnoredSpringRunnerTests.class, - -HardCodedProfileValueSourceSpringRunnerTests.class, - -SpringJUnit4ClassRunnerAppCtxTests.class, - -ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.class, - -AbsolutePathSpringJUnit4ClassRunnerAppCtxTests.class, - -RelativePathSpringJUnit4ClassRunnerAppCtxTests.class, - -MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests.class, - -InheritedConfigSpringJUnit4ClassRunnerAppCtxTests.class, - -PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests.class, - -SpringRunnerContextCacheTests.class, - -ParameterizedDependencyInjectionTests.class, - -ClassLevelTransactionalSpringRunnerTests.class, - -MethodLevelTransactionalSpringRunnerTests.class, - -DefaultRollbackTrueTransactionalSpringRunnerTests.class, - -DefaultRollbackFalseTransactionalSpringRunnerTests.class, - -RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests.class, - -RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests.class, - -BeforeAndAfterTransactionAnnotationTests.class, - -TimedTransactionalSpringRunnerTests.class - +@SuiteClasses( {// +StandardJUnit4FeaturesTests.class,// + StandardJUnit4FeaturesSpringRunnerTests.class,// + ExpectedExceptionSpringRunnerTests.class,// + TimedSpringRunnerTests.class,// + RepeatedSpringRunnerTests.class,// + EnabledAndIgnoredSpringRunnerTests.class,// + HardCodedProfileValueSourceSpringRunnerTests.class,// + SpringJUnit4ClassRunnerAppCtxTests.class,// + ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.class,// + AbsolutePathSpringJUnit4ClassRunnerAppCtxTests.class,// + RelativePathSpringJUnit4ClassRunnerAppCtxTests.class,// + MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests.class,// + InheritedConfigSpringJUnit4ClassRunnerAppCtxTests.class,// + PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests.class,// + SpringRunnerContextCacheTests.class,// + ParameterizedDependencyInjectionTests.class,// + ClassLevelTransactionalSpringRunnerTests.class,// + MethodLevelTransactionalSpringRunnerTests.class,// + DefaultRollbackTrueTransactionalSpringRunnerTests.class,// + DefaultRollbackFalseTransactionalSpringRunnerTests.class,// + RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests.class,// + RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests.class,// + BeforeAndAfterTransactionAnnotationTests.class,// + TimedTransactionalSpringRunnerTests.class // }) public class SpringJUnit4SuiteTests { - /* this test case is comprised completely of tests loaded as a suite. */ + /* this test case consists entirely of tests loaded as a suite. */ } diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java new file mode 100644 index 00000000000..a3033eba07e --- /dev/null +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java @@ -0,0 +1,97 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context.junit4; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.JUnit4; +import org.springframework.test.annotation.Timed; +import org.springframework.test.context.TestExecutionListeners; + +/** + * Verifies proper handling of the following in conjunction with the + * {@link SpringJUnit4ClassRunner}: + *
    + *
  • JUnit's {@link Test#timeout() @Test(timeout=...)}
  • + *
  • Spring's {@link Timed @Timed}
  • + *
+ * + * @author Sam Brannen + * @since 3.0 + */ +@RunWith(JUnit4.class) +public class TimedSpringRunnerTests { + + @Test + public void timedTests() throws Exception { + Class testClass = TimedSpringRunnerTestCase.class; + TrackingRunListener listener = new TrackingRunListener(); + RunNotifier notifier = new RunNotifier(); + notifier.addListener(listener); + + new SpringJUnit4ClassRunner(testClass).run(notifier); + assertEquals("Verifying number of failures for test class [" + testClass + "].", 3, + listener.getTestFailureCount()); + assertEquals("Verifying number of tests started for test class [" + testClass + "].", 5, + listener.getTestStartedCount()); + assertEquals("Verifying number of tests finished for test class [" + testClass + "].", 5, + listener.getTestFinishedCount()); + } + + + @RunWith(SpringJUnit4ClassRunner.class) + @TestExecutionListeners( {}) + public static final class TimedSpringRunnerTestCase { + + // Should Pass. + @Test(timeout = 2000) + public void testJUnitTimeoutWithNoOp() { + /* no-op */ + } + + // Should Pass. + @Test + @Timed(millis = 2000) + public void testSpringTimeoutWithNoOp() { + /* no-op */ + } + + // Should Fail due to timeout. + @Test(timeout = 200) + public void testJUnitTimeoutWithOneSecondWait() throws Exception { + Thread.sleep(1000); + } + + // Should Fail due to timeout. + @Test + @Timed(millis = 200) + public void testSpringTimeoutWithOneSecondWait() throws Exception { + Thread.sleep(1000); + } + + // Should Fail due to duplicate configuration. + @Test(timeout = 200) + @Timed(millis = 200) + public void testSpringAndJUnitTimeout() { + /* no-op */ + } + } + +} diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TrackingRunListener.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TrackingRunListener.java new file mode 100644 index 00000000000..6a8edd857ca --- /dev/null +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TrackingRunListener.java @@ -0,0 +1,68 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context.junit4; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.runner.Description; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunListener; + +/** + * Simple {@link RunListener} which tracks how many times certain JUnit callback + * methods were called: only intended for the integration test suite. + * + * @author Sam Brannen + * @since 3.0 + */ +public class TrackingRunListener extends RunListener { + + private final AtomicInteger testFailureCount = new AtomicInteger(); + + private final AtomicInteger testStartedCount = new AtomicInteger(); + + private final AtomicInteger testFinishedCount = new AtomicInteger(); + + + public int getTestFailureCount() { + return this.testFailureCount.get(); + } + + public int getTestStartedCount() { + return this.testStartedCount.get(); + } + + public int getTestFinishedCount() { + return this.testFinishedCount.get(); + } + + @Override + public void testFailure(Failure failure) throws Exception { + this.testFailureCount.incrementAndGet(); + } + + @Override + public void testStarted(Description description) throws Exception { + this.testStartedCount.incrementAndGet(); + } + + @Override + public void testFinished(Description description) throws Exception { + this.testFinishedCount.incrementAndGet(); + } + +}