View Javadoc

1   /********************************************************************************
2    * DDTUnit, a Datadriven Approach to Unit- and Moduletesting
3    * Copyright (c) 2004, Joerg and Kai Gellien
4    * All rights reserved.
5    *
6    * The Software is provided under the terms of the Common Public License 1.0
7    * as provided with the distribution of DDTUnit in the file cpl-v10.html.
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   *     + Redistributions of source code must retain the above copyright
13   *       notice, this list of conditions and the following disclaimer.
14   *
15   *     + Redistributions in binary form must reproduce the above
16   *       copyright notice, this list of conditions and the following
17   *       disclaimer in the documentation and/or other materials provided
18   *       with the distribution.
19   *
20   *     + Neither the name of the authors or DDTUnit, nor the
21   *       names of its contributors may be used to endorse or promote
22   *       products derived from this software without specific prior
23   *       written permission.
24   *
25   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
29   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36   ********************************************************************************/
37  package junitx.ddtunit;
38  
39  import java.util.ArrayList;
40  import java.util.Iterator;
41  import java.util.List;
42  import java.util.ListIterator;
43  import java.util.Vector;
44  
45  import junit.framework.AssertionFailedError;
46  import junit.framework.Protectable;
47  import junit.framework.Test;
48  import junit.framework.TestCase;
49  import junit.framework.TestFailure;
50  import junit.framework.TestListener;
51  import junit.framework.TestResult;
52  import junitx.ddtunit.util.DDTConfiguration;
53  import junitx.ddtunit.util.PrivilegedAccessor;
54  
55  /**
56   * Extends class {@link TestResult}of JUnit <br/>This class will contain extra
57   * results from test execution based on xml data testcases.
58   * 
59   * @author jg
60   */
61  public class DDTTestResult extends TestResult {
62  	/**
63  	 * Vector containing all caught failures during test execution
64  	 */
65  	protected List<TestFailure> fMethodTestFailures;
66  
67  	/**
68  	 * Vector containing all errors caught during test execution
69  	 */
70  	protected List<TestFailure> fMethodTestErrors;
71  
72  	/**
73  	 * Number of executed tests inside of a testmethod
74  	 */
75  	protected int fRunMethodTests;
76  
77  	/**
78  	 * 
79  	 */
80  	public DDTTestResult() {
81  		super();
82  		fMethodTestFailures = new ArrayList<TestFailure>();
83  		fMethodTestErrors = new ArrayList<TestFailure>();
84  		fRunMethodTests = 0;
85  
86  		if (DDTConfiguration.getInstance().isActiveRunMonitor()
87  				&& !this.cloneListeners().contains(DDTRunMonitor.getInstance())) {
88  			this.addListener(DDTRunMonitor.getInstance());
89  		}
90  	}
91  
92  	/**
93  	 * Instanciate DDTTestResult by using JUnit TestResult as base info.
94  	 * 
95  	 * @param result
96  	 *            of JUnit TestResult
97  	 * @throws DDTException
98  	 */
99  	public DDTTestResult(TestResult result) throws DDTException {
100 		try {
101 			PrivilegedAccessor.setFieldValue(this, "fErrors",
102 					PrivilegedAccessor.getFieldValue(result, "fErrors"));
103 			PrivilegedAccessor.setFieldValue(this, "fFailures",
104 					PrivilegedAccessor.getFieldValue(result, "fFailures"));
105 			PrivilegedAccessor.setFieldValue(this, "fListeners",
106 					PrivilegedAccessor.getFieldValue(result, "fListeners"));
107 			this.fRunTests = ((Integer) PrivilegedAccessor.getFieldValue(
108 					result, "fRunTests")).intValue();
109 			fMethodTestFailures = new Vector<TestFailure>();
110 			fMethodTestErrors = new Vector<TestFailure>();
111 			fRunMethodTests = 0;
112 		} catch (Exception e) {
113 			e.printStackTrace();
114 			throw new DDTException(
115 					"Error on transforming TestResult to DDTResult", e);
116 		}
117 
118 		if (DDTConfiguration.getInstance().isActiveRunMonitor()
119 				&& !this.cloneListeners().contains(DDTRunMonitor.getInstance())) {
120 			this.addListener(DDTRunMonitor.getInstance());
121 		}
122 	}
123 
124 	/**
125 	 * DOCUMENT ME!
126 	 * 
127 	 * @param result
128 	 *            DOCUMENT ME!
129 	 * 
130 	 * @return DOCUMENT ME!
131 	 */
132 	public TestResult copyContent(TestResult result) {
133 		try {
134 			PrivilegedAccessor.setFieldValue(result, "fErrors",
135 					PrivilegedAccessor.getFieldValue(this, "fErrors"));
136 			PrivilegedAccessor.setFieldValue(result, "fFailures",
137 					PrivilegedAccessor.getFieldValue(this, "fFailures"));
138 			PrivilegedAccessor.setFieldValue(result, "fListeners",
139 					PrivilegedAccessor.getFieldValue(this, "fListeners"));
140 			PrivilegedAccessor.setFieldValue(result, "fRunTests", new Integer(
141 					this.fRunTests));
142 		} catch (Exception e) {
143 			e.printStackTrace();
144 			throw new DDTException(
145 					"Error on transforming TestResult to DDTResult", e);
146 		}
147 
148 		return result;
149 	}
150 
151 	/**
152 	 * DOCUMENT ME!
153 	 * 
154 	 * @return DOCUMENT ME!
155 	 * 
156 	 * @throws DDTException
157 	 *             DOCUMENT ME!
158 	 */
159 	TestResult createTestResult() throws DDTException {
160 		TestResult result = new TestResult();
161 
162 		try {
163 			PrivilegedAccessor.setFieldValue(result, "fError", this.fErrors);
164 			PrivilegedAccessor.setFieldValue(result, "fFailures",
165 					this.fFailures);
166 			PrivilegedAccessor.setFieldValue(result, "fListeners",
167 					this.fListeners);
168 			PrivilegedAccessor.setFieldValue(result, "fRunTests", new Integer(
169 					this.fRunTests));
170 		} catch (Exception e) {
171 			e.printStackTrace();
172 			throw new DDTException(
173 					"Error during conversion from DDTResult to TestResult");
174 		}
175 
176 		return result;
177 	}
178 
179 	/**
180 	 * Runs a TestCase.
181 	 * 
182 	 * @param test
183 	 *            to run
184 	 */
185 	protected void run(final TestCase test) {
186 		startTest(test);
187 
188 		Protectable p = new Protectable() {
189 			public void protect() throws Throwable {
190 				test.runBare();
191 			}
192 		};
193 
194 		runProtected(test, p);
195 
196 		endTest(test);
197 	}
198 
199 	/**
200 	 * Runs a TestCase.
201 	 * 
202 	 * @param test
203 	 *            to run
204 	 * @param protectedRunner
205 	 *            executes testmethod and and throws Throwable if any error
206 	 *            occures
207 	 */
208 	public void runProtected(final Test test, Protectable protectedRunner) {
209 		try {
210 			protectedRunner.protect();
211 		} catch (AssertionFailedError e) {
212 			addFailure(test, e);
213 		} catch (ThreadDeath e) { // don't catch ThreadDeath by accident
214 			throw e;
215 		} catch (Throwable e) {
216 			addError(test, e);
217 		}
218 	}
219 
220 	/**
221 	 * Add error of a method test execution for later statistic
222 	 * 
223 	 * @param test
224 	 *            to run
225 	 * @param testName
226 	 *            of dataset actually processed in testmethod
227 	 * @param throwable
228 	 *            caught during execution of test
229 	 * 
230 	 * @see junitx.ddtunit.DDTTestListener#addMethodTestError(junit.framework.Test,
231 	 *      java.lang.String, java.lang.Throwable)
232 	 */
233 	public void addMethodTestError(Test test, String testName,
234 			Throwable throwable) {
235 		fMethodTestErrors.add(new DDTTestFailure(test, testName, throwable));
236 
237 		for (Iterator e = cloneListeners().listIterator(); e.hasNext();) {
238 			TestListener listener = (TestListener) e.next();
239 
240 			if (DDTTestListener.class.isInstance(listener)) {
241 				((DDTTestListener) listener).addMethodTestError(test, testName,
242 						throwable);
243 			}
244 		}
245 	}
246 
247 	/**
248 	 * Add assertion failure of a method test execution for later statistic
249 	 * 
250 	 * @param test
251 	 *            to run
252 	 * @param testName
253 	 *            of dataset actually processed in testmethod
254 	 * @param assertError
255 	 *            caught during execution of test
256 	 * 
257 	 * @see junitx.ddtunit.DDTTestListener#addMethodTestFailure(junit.framework.Test,
258 	 *      java.lang.String, junit.framework.AssertionFailedError)
259 	 */
260 	public void addMethodTestFailure(Test test, String testName,
261 			AssertionFailedError assertError) {
262 		fMethodTestFailures
263 				.add(new DDTTestFailure(test, testName, assertError));
264 
265 		for (Iterator e = cloneListeners().listIterator(); e.hasNext();) {
266 			TestListener listener = (TestListener) e.next();
267 
268 			if (DDTTestListener.class.isInstance(listener)) {
269 				((DDTTestListener) listener).addMethodTestFailure(test,
270 						testName, assertError);
271 			}
272 		}
273 	}
274 
275 	/**
276 	 * Notify about end of method test
277 	 * 
278 	 * @param test
279 	 *            to run
280 	 * @param methodName
281 	 *            of actually processed method
282 	 * 
283 	 * @see junitx.ddtunit.DDTTestListener#endMethodTest(junitx.ddtunit.DDTTestCase,
284 	 *      java.lang.String)
285 	 */
286 	public void endMethodTest(IDDTTestCase test, String methodName) {
287 		for (Iterator e = cloneListeners().listIterator(); e.hasNext();) {
288 			TestListener listener = (TestListener) e.next();
289 
290 			if (DDTTestListener.class.isInstance(listener)) {
291 				((DDTTestListener) listener).endMethodTest(test, methodName);
292 			}
293 		}
294 	}
295 
296 	/**
297 	 * Notify about start of method test
298 	 * 
299 	 * @param test
300 	 *            to run
301 	 * @param methodName
302 	 *            of actually processed method
303 	 * 
304 	 * @see junitx.ddtunit.DDTTestListener#startMethodTest(junitx.ddtunit.DDTTestCase,
305 	 *      java.lang.String)
306 	 */
307 	public void startMethodTest(IDDTTestCase test, String methodName) {
308 		final int count = 1;
309 
310 		synchronized (this) {
311 			fRunMethodTests += count;
312 		}
313 
314 		for (Iterator e = cloneListeners().listIterator(); e.hasNext();) {
315 			TestListener listener = (TestListener) e.next();
316 
317 			if (DDTTestListener.class.isInstance(listener)) {
318 				((DDTTestListener) listener).startMethodTest(test, methodName);
319 			}
320 		}
321 	}
322 
323 	/**
324 	 * Returns a copy of the TestListeners
325 	 * 
326 	 * @return Vector of TestListeners
327 	 */
328 	private synchronized List<TestListener> cloneListeners() {
329 		List<TestListener> newListeners = new ArrayList<TestListener>();
330 		try {
331 			newListeners.addAll((List<TestListener>) PrivilegedAccessor
332 					.getFieldValue(this, "fListeners"));
333 		} catch (IllegalAccessException ex) {
334 			throw new DDTSetUpException("Error preparing listeners", ex);
335 		} catch (NoSuchFieldException ex) {
336 			throw new DDTSetUpException("Error preparing listeners", ex);
337 		}
338 		return newListeners;
339 	}
340 
341 	/**
342 	 * @return number of xml based tests run
343 	 */
344 	public int runMethodTestCount() {
345 		return fRunMethodTests;
346 	}
347 
348 	/**
349 	 * @return number of method test failures were caught during execution
350 	 */
351 	public int methodTestFailureCount() {
352 		return fMethodTestFailures.size();
353 	}
354 
355 	/**
356 	 * @return number of method test errors were caught during execution
357 	 */
358 	public int methodTestErrorCount() {
359 		return fMethodTestErrors.size();
360 	}
361 
362 	public ListIterator<TestFailure> methodTestFailures() {
363 		ListIterator<TestFailure> iter = this.fMethodTestFailures
364 				.listIterator();
365 		return iter;
366 	}
367 
368 }