001: /*
002: * Copyright 2006-2007, Unitils.org
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.unitils;
017:
018: import static junit.framework.Assert.assertEquals;
019: import static junit.framework.Assert.assertFalse;
020: import junit.framework.TestResult;
021: import junit.framework.TestSuite;
022: import junit.textui.TestRunner;
023: import org.junit.AfterClass;
024: import org.junit.Before;
025: import org.junit.BeforeClass;
026: import org.junit.Test;
027: import org.junit.internal.runners.InitializationError;
028: import org.junit.runner.Result;
029: import org.junit.runner.notification.RunNotifier;
030: import org.testng.TestListenerAdapter;
031: import org.testng.TestNG;
032: import org.unitils.core.TestListener;
033: import org.unitils.core.Unitils;
034: import static org.unitils.inject.util.InjectionUtils.injectIntoStatic;
035: import org.unitils.util.ReflectionUtils;
036:
037: import java.util.Iterator;
038:
039: /**
040: * Test for the main flow of the unitils test listeners for JUnit3 ({@link UnitilsJUnit3}),
041: * JUnit4 (@link UnitilsJUnit4TestClassRunner}) and TestNG ({@link UnitilsTestNG}).
042: * <p/>
043: * Except for some minor differences, the flows for all these test frameworks
044: * are expected to be the same (see {@link #assertInvocationOrder}.
045: * <p/>
046: * 3 tests are performed: TestClass1 and TestClass2 both with 2 test methods and EmptyTestClass
047: * that does not contain any methods. TestClass1 also contains an ignored test (not for JUnit3).
048: *
049: * @author Tim Ducheyne
050: * @author Filip Neven
051: * @see UnitilsJUnit3Test_TestClass1
052: * @see UnitilsJUnit3Test_TestClass2
053: * @see UnitilsJUnit3Test_EmptyTestClass
054: * @see UnitilsJUnit4Test_TestClass1
055: * @see UnitilsJUnit4Test_TestClass2
056: * @see UnitilsTestNGTest_TestClass1
057: * @see UnitilsTestNGTest_TestClass2
058: * @see UnitilsTestNGTest_EmptyTestClass
059: */
060: public class UnitilsInvocationTest {
061:
062: /* Listener that records all method invocations during the tests */
063: private static TracingTestListener tracingTestListener;
064:
065: /* Temporary holder so that the test listener that was replaced during the test can be place back */
066: private static TestListener oldTestListenerUnitilsJUnit3;
067:
068: /* Temporary holder so that the test listener that was replaced during the test can be place back */
069: private static TestListener oldTestListenerUnitilsJUnit4;
070:
071: /**
072: * Sets up the test by installing the tracing test listener that will record all method invocations during the test.
073: * The current test listeners are stored so that they can be restored during the class tear down.
074: */
075: @BeforeClass
076: public static void classSetup() {
077: oldTestListenerUnitilsJUnit3 = (TestListener) ReflectionUtils
078: .getFieldValue(null, ReflectionUtils.getFieldWithName(
079: UnitilsJUnit3.class, "testListener", true));
080: oldTestListenerUnitilsJUnit4 = (TestListener) ReflectionUtils
081: .getFieldValue(null, ReflectionUtils.getFieldWithName(
082: UnitilsJUnit4TestClassRunner.class,
083: "testListener", true));
084:
085: injectIntoStatic(null, UnitilsJUnit3.class, "testListener");
086: injectIntoStatic(null, UnitilsJUnit4TestClassRunner.class,
087: "testListener");
088:
089: tracingTestListener = new TracingTestListener();
090:
091: UnitilsJUnit3Test_TestClass1
092: .setTracingTestListener(tracingTestListener);
093: UnitilsJUnit3Test_TestClass2
094: .setTracingTestListener(tracingTestListener);
095: UnitilsJUnit3Test_EmptyTestClass
096: .setTracingTestListener(tracingTestListener);
097:
098: UnitilsJUnit4Test_TestClass1
099: .setTracingTestListener(tracingTestListener);
100: UnitilsJUnit4Test_TestClass2
101: .setTracingTestListener(tracingTestListener);
102:
103: UnitilsTestNGTest_TestClass1
104: .setTracingTestListener(tracingTestListener);
105: UnitilsTestNGTest_TestClass2
106: .setTracingTestListener(tracingTestListener);
107: UnitilsTestNGTest_EmptyTestClass
108: .setTracingTestListener(tracingTestListener);
109: UnitilsTestNGTest_GroupsTest
110: .setTracingTestListener(tracingTestListener);
111: }
112:
113: /**
114: * This will put back the old test listeners that were replaced by the tracing test listener.
115: */
116: @AfterClass
117: public static void classTearDown() {
118: injectIntoStatic(oldTestListenerUnitilsJUnit3,
119: UnitilsJUnit3.class, "testListener");
120: injectIntoStatic(oldTestListenerUnitilsJUnit4,
121: UnitilsJUnit4TestClassRunner.class, "testListener");
122: }
123:
124: /**
125: * Sets up the test by clearing the previous recorded method invocations. This will also re-initiliaze
126: * the base-classes so that, for example beforeAll() will be called another time.
127: */
128: @Before
129: public void setUp() throws Exception {
130: tracingTestListener.getCallList().clear();
131:
132: // clear state so that beforeAll is called
133: injectIntoStatic(false, UnitilsJUnit3.class, "beforeAllCalled");
134: injectIntoStatic(null, UnitilsJUnit3.class, "lastTestClass");
135: injectIntoStatic(false, UnitilsJUnit4TestClassRunner.class,
136: "beforeAllCalled");
137:
138: }
139:
140: /**
141: * Tests the correct invocation sequence of listener methods for a JUnit3 test.
142: */
143: @Test
144: public void testUnitilsJUnit3() {
145: TestSuite suite = new TestSuite();
146: suite.addTestSuite(UnitilsJUnit3Test_TestClass1.class);
147: suite.addTestSuite(UnitilsJUnit3Test_TestClass2.class);
148: suite.addTestSuite(UnitilsJUnit3Test_EmptyTestClass.class);
149:
150: TestRunner testRunner = new TestRunner();
151: TestResult testResult = testRunner.doRun(suite);
152:
153: assertInvocationOrder("JUnit3", tracingTestListener);
154: // EmptyTestClass has caused a failure and will not be run
155: assertEquals(0, testResult.errorCount());
156: assertEquals(1, testResult.failureCount());
157: }
158:
159: /**
160: * Tests the correct invocation sequence of listener methods for a JUnit4 test.
161: */
162: @Test
163: public void testUnitilsJUnit4() throws Exception {
164:
165: Result result = new Result();
166: RunNotifier runNotifier = new RunNotifier();
167: runNotifier.addListener(result.createListener());
168:
169: TestUnitilsJUnit4TestClassRunner testRunner1 = new TestUnitilsJUnit4TestClassRunner(
170: UnitilsJUnit4Test_TestClass1.class);
171: TestUnitilsJUnit4TestClassRunner testRunner2 = new TestUnitilsJUnit4TestClassRunner(
172: UnitilsJUnit4Test_TestClass2.class);
173: testRunner1.run(runNotifier);
174: testRunner2.run(runNotifier);
175:
176: assertInvocationOrder("JUnit4", tracingTestListener);
177: assertEquals(4, result.getRunCount());
178: assertEquals(1, result.getIgnoreCount());
179: }
180:
181: /**
182: * Tests the correct invocation sequence of listener methods for a TestNG test.
183: */
184: @Test
185: public void testUnitilsTestNG() {
186: TestListenerAdapter testListenerAdapter = new TestListenerAdapter();
187:
188: TestNG testng = new TestNG();
189: testng.setTestClasses(new Class[] {
190: UnitilsTestNGTest_TestClass1.class,
191: UnitilsTestNGTest_TestClass2.class,
192: UnitilsTestNGTest_EmptyTestClass.class });
193: testng.addListener(testListenerAdapter);
194: testng.run();
195:
196: assertInvocationOrder("TestNG", tracingTestListener);
197: assertEquals(0, testListenerAdapter.getFailedTests().size());
198: }
199:
200: /**
201: * Tests the correct invocation sequence of listener methods for a TestNG test that defines a test group.
202: */
203: @Test
204: public void testUnitilsTestNG_group() {
205: TestListenerAdapter testListenerAdapter = new TestListenerAdapter();
206:
207: TestNG testng = new TestNG();
208: testng
209: .setTestClasses(new Class[] { UnitilsTestNGTest_GroupsTest.class });
210: testng.setGroups("testGroup");
211: testng.addListener(testListenerAdapter);
212: testng.run();
213:
214: Iterator<?> iterator = tracingTestListener.getCallList()
215: .iterator();
216: assertEquals("[Unitils] beforeAll", iterator.next());
217: assertEquals("[Unitils] beforeTestClass - GroupsTest",
218: iterator.next());
219: assertEquals("[Test] testBeforeClass - GroupsTest",
220: iterator.next());
221: assertEquals("[Unitils] beforeTestSetUp - GroupsTest",
222: iterator.next());
223: assertEquals("[Test] testSetUp - GroupsTest",
224: iterator.next());
225: assertEquals("[Unitils] beforeTestMethod - GroupsTest",
226: iterator.next());
227: assertEquals("[Test] testMethod - GroupsTest",
228: iterator.next());
229: assertEquals("[Unitils] afterTestMethod - GroupsTest",
230: iterator.next());
231: assertEquals("[Test] testTearDown - GroupsTest",
232: iterator.next());
233: assertEquals("[Unitils] afterTestTearDown - GroupsTest",
234: iterator.next());
235: assertEquals("[Test] testAfterClass - GroupsTest",
236: iterator.next());
237: assertEquals("[Unitils] afterTestClass - GroupsTest",
238: iterator.next());
239: assertEquals("[Unitils] afterAll", iterator.next());
240: assertEquals(0, testListenerAdapter.getFailedTests().size());
241: }
242:
243: /**
244: * Tests the correct invocation sequence of listener methods for a TestNG test that defines an unknown test group.
245: */
246: @Test
247: public void testUnitilsTestNG_unknownGroup() {
248: TestListenerAdapter testListenerAdapter = new TestListenerAdapter();
249:
250: TestNG testng = new TestNG();
251: testng
252: .setTestClasses(new Class[] { UnitilsTestNGTest_GroupsTest.class });
253: testng.setGroups("xxxx");
254: testng.addListener(testListenerAdapter);
255: testng.run();
256:
257: Iterator<?> iterator = tracingTestListener.getCallList()
258: .iterator();
259: assertEquals("[Unitils] beforeAll", iterator.next());
260: assertEquals("[Unitils] afterAll", iterator.next());
261: assertEquals(0, testListenerAdapter.getFailedTests().size());
262: }
263:
264: /**
265: * Asserts that the given listener recorded the correct invocation sequence. Except for some minor difference, the
266: * sequence should be equal for all test frameworks.
267: * <p/>
268: * Following difference are allowed:<ul>
269: * <li>beforeTestClass and afterTestClass no not exist in JUnit 3 (the Unitils versions will be called however)</li>
270: * <li>empty tests are not run at all in JUnit3 and TestNG, in JUnit 4 the beforeTestClass and afterTestClass will be called</li>
271: * </ul>
272: * For JUnit3 and JUnit4 afterAll will be called during the runtime exit and can therefore not be asserted here.
273: * The same is true for the last afterTestClass method of JUnit3 tests. This is because you cannot determine which test
274: * is going to be the last test in the class
275: *
276: * @param type JUnit3, JUnit4 or TestNG
277: * @param tracingTestListener the listener, not null
278: */
279: private void assertInvocationOrder(String type,
280: TracingTestListener tracingTestListener) {
281: Iterator<?> iterator = tracingTestListener.getCallList()
282: .iterator();
283: assertEquals("[Unitils] beforeAll", iterator.next());
284:
285: assertEquals("[Unitils] beforeTestClass - TestClass1",
286: iterator.next());
287: if (!"JUnit3".equals(type)) {
288: assertEquals("[Test] testBeforeClass - TestClass1",
289: iterator.next());
290: }
291: assertEquals("[Unitils] beforeTestSetUp - TestClass1",
292: iterator.next());
293: assertEquals("[Test] testSetUp - TestClass1",
294: iterator.next());
295: assertEquals("[Unitils] beforeTestMethod - TestClass1",
296: iterator.next());
297: assertEquals("[Test] testMethod - TestClass1",
298: iterator.next());
299: assertEquals("[Unitils] afterTestMethod - TestClass1",
300: iterator.next());
301: assertEquals("[Test] testTearDown - TestClass1",
302: iterator.next());
303: assertEquals("[Unitils] afterTestTearDown - TestClass1",
304: iterator.next());
305: assertEquals("[Unitils] beforeTestSetUp - TestClass1",
306: iterator.next());
307: assertEquals("[Test] testSetUp - TestClass1",
308: iterator.next());
309: assertEquals("[Unitils] beforeTestMethod - TestClass1",
310: iterator.next());
311: assertEquals("[Test] testMethod - TestClass1",
312: iterator.next());
313: assertEquals("[Unitils] afterTestMethod - TestClass1",
314: iterator.next());
315: assertEquals("[Test] testTearDown - TestClass1",
316: iterator.next());
317: assertEquals("[Unitils] afterTestTearDown - TestClass1",
318: iterator.next());
319: if (!"JUnit3".equals(type)) {
320: assertEquals("[Test] testAfterClass - TestClass1",
321: iterator.next());
322: }
323: assertEquals("[Unitils] afterTestClass - TestClass1",
324: iterator.next());
325:
326: assertEquals("[Unitils] beforeTestClass - TestClass2",
327: iterator.next());
328: if (!"JUnit3".equals(type)) {
329: assertEquals("[Test] testBeforeClass - TestClass2",
330: iterator.next());
331: }
332: assertEquals("[Unitils] beforeTestSetUp - TestClass2",
333: iterator.next());
334: assertEquals("[Test] testSetUp - TestClass2",
335: iterator.next());
336: assertEquals("[Unitils] beforeTestMethod - TestClass2",
337: iterator.next());
338: assertEquals("[Test] testMethod - TestClass2",
339: iterator.next());
340: assertEquals("[Unitils] afterTestMethod - TestClass2",
341: iterator.next());
342: assertEquals("[Test] testTearDown - TestClass2",
343: iterator.next());
344: assertEquals("[Unitils] afterTestTearDown - TestClass2",
345: iterator.next());
346: assertEquals("[Unitils] beforeTestSetUp - TestClass2",
347: iterator.next());
348: assertEquals("[Test] testSetUp - TestClass2",
349: iterator.next());
350: assertEquals("[Unitils] beforeTestMethod - TestClass2",
351: iterator.next());
352: assertEquals("[Test] testMethod - TestClass2",
353: iterator.next());
354: assertEquals("[Unitils] afterTestMethod - TestClass2",
355: iterator.next());
356: assertEquals("[Test] testTearDown - TestClass2",
357: iterator.next());
358: assertEquals("[Unitils] afterTestTearDown - TestClass2",
359: iterator.next());
360: if (!"JUnit3".equals(type)) {
361: assertEquals("[Test] testAfterClass - TestClass2",
362: iterator.next());
363: // last afterTestClass (TestClass2) will be called when the runtime exits
364: assertEquals("[Unitils] afterTestClass - TestClass2",
365: iterator.next());
366: }
367:
368: // For JUnit 3 and JUnit 4 afterAll will be called when the runtime exits
369: if ("TestNG".equals(type)) {
370: assertEquals("[Unitils] afterAll", iterator.next());
371: }
372: assertFalse(iterator.hasNext());
373: }
374:
375: /**
376: * Overridden test class runner to be able to use the {@link TracingTestListener} as test listener.
377: */
378: private class TestUnitilsJUnit4TestClassRunner extends
379: UnitilsJUnit4TestClassRunner {
380:
381: public TestUnitilsJUnit4TestClassRunner(Class<?> testClass)
382: throws InitializationError {
383: super (testClass);
384: }
385:
386: @Override
387: protected Unitils getUnitils() {
388:
389: return new Unitils() {
390:
391: @Override
392: public TestListener createTestListener() {
393: return tracingTestListener;
394: }
395: };
396: }
397: }
398:
399: /**
400: * JUnit 3 test class without any tests. Inner class to avoid a failing test.
401: */
402: protected static class UnitilsJUnit3Test_EmptyTestClass extends
403: UnitilsJUnit3 {
404:
405: private static TracingTestListener tracingTestListener;
406:
407: public static void setTracingTestListener(
408: TracingTestListener testListener) {
409: tracingTestListener = testListener;
410: }
411:
412: @Override
413: protected Unitils getUnitils() {
414: if (tracingTestListener != null) {
415: return new Unitils() {
416:
417: @Override
418: public TestListener createTestListener() {
419: return tracingTestListener;
420: }
421: };
422: }
423: return super.getUnitils();
424: }
425: }
426: }
|