Add Junit3 and Junit4 adapters allowing to launch AntUnit script from JUnit runner (I still have some weakness to fix in the junit4 runner)
git-svn-id: https://svn.apache.org/repos/asf/ant/antlibs/antunit/trunk@743906 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0b6bc826c1
commit
5220af86b5
|
|
@ -25,5 +25,8 @@ under the License.
|
|||
<!-- don't fork junit; regexp classes not available -->
|
||||
<property name="junit.fork" value="false" />
|
||||
|
||||
<property name="javac.test-source" value="1.5"/>
|
||||
<property name="javac.test-target" value="1.5"/>
|
||||
|
||||
<import file="common/build.xml"/>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@
|
|||
</properties>
|
||||
|
||||
<release version="1.2" date="not-released">
|
||||
<action type="add">
|
||||
Add Junit3 and Junit4 adapters allowing to launch AntUnit script from JUnit runner
|
||||
</action>
|
||||
<action type="update">
|
||||
expectfailure report the original build exception chained when failing
|
||||
</action>
|
||||
|
|
|
|||
|
|
@ -62,4 +62,8 @@
|
|||
<first>Steve</first>
|
||||
<last>Loughran</last>
|
||||
</name>
|
||||
<name>
|
||||
<first>Gilles</first>
|
||||
<last>Scokart</last>
|
||||
</name>
|
||||
</contributors>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you 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.
|
||||
-->
|
||||
|
||||
<project name="junit" default="all" xmlns:au="antlib:org.apache.ant.antunit"
|
||||
basedir="../../../../">
|
||||
|
||||
<target name="all">
|
||||
<fail message="These are not standalone tests." />
|
||||
</target>
|
||||
|
||||
<property name="outputdir" location="target/test_output"/>
|
||||
<property name="outputfile" location="${outputdir}/junit_out.xml"/>
|
||||
|
||||
<target name="suiteSetUp">
|
||||
<mkdir dir="${outputdir}"/>
|
||||
<delete file="${outputfile}"/>
|
||||
<echo file="${outputfile}" append="true" message="suiteSetUp-" />
|
||||
</target>
|
||||
|
||||
<target name="suiteTearDown">
|
||||
<echo file="${outputfile}" append="true" message="suiteTearDown" />
|
||||
</target>
|
||||
|
||||
<target name="setUp">
|
||||
<echo file="${outputfile}" append="true" message="setUp-" />
|
||||
</target>
|
||||
|
||||
<target name="tearDown">
|
||||
<echo file="${outputfile}" append="true" message="tearDown-" />
|
||||
</target>
|
||||
|
||||
|
||||
<target name="test1">
|
||||
<echo file="${outputfile}" append="true" message="test1-" />
|
||||
</target>
|
||||
|
||||
<target name="test2">
|
||||
<echo file="${outputfile}" append="true" message="test2-" />
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
||||
|
|
@ -4,7 +4,7 @@ import org.apache.tools.ant.Project;
|
|||
|
||||
/**
|
||||
* Provides project instances for AntUnit execution.<br/>
|
||||
* The aproach to creates a project depends on the context. When invoked from an
|
||||
* The approach to creates a project depends on the context. When invoked from an
|
||||
* ant project, some elements might be intialized from the parent project. When
|
||||
* executed in a junit runner, a brand new project must be initialized.<br/>
|
||||
* The AntScriptRunner will usually creates multiple project in order to provide test isolation.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.ant.antunit.junit3;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestResult;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.apache.ant.antunit.AntUnitScriptRunner;
|
||||
import org.apache.ant.antunit.ProjectFactory;
|
||||
import org.apache.tools.ant.DefaultLogger;
|
||||
import org.apache.tools.ant.MagicNames;
|
||||
import org.apache.tools.ant.Project;
|
||||
import org.apache.tools.ant.ProjectHelper;
|
||||
|
||||
/**
|
||||
* A JUnit 3 TestSuite that group a suite of AntUnit targets coming from an ant
|
||||
* script.
|
||||
*/
|
||||
public class AntUnitSuite extends TestSuite {
|
||||
|
||||
private final AntUnitScriptRunner antScriptRunner;
|
||||
private final MultiProjectDemuxOutputStream stderr;
|
||||
private final MultiProjectDemuxOutputStream stdout;
|
||||
|
||||
/**
|
||||
* Create a JUnit TestSuite that when executed will run the given ant
|
||||
* script.<br/>
|
||||
* Note that it is the responsibility of the caller to give the correct
|
||||
* File reference. Namely, if the File is a relative file, it will
|
||||
* be resolve relatively to the execution directory (which might be
|
||||
* different different from the project root directory).
|
||||
*
|
||||
* @param scriptFile
|
||||
* AntUnit script file
|
||||
* @param rootClass
|
||||
* The test class that creates this suite. This is used to give
|
||||
* a name to the suite so that an IDE can reexecute this suite.
|
||||
*/
|
||||
public AntUnitSuite(final File scriptFile, Class rootClass) {
|
||||
this(scriptFile);
|
||||
setName(rootClass.getName());// Allows eclipse to reexecute the test
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used by AntUnitTestCase when a single test case is created.
|
||||
* The difference with the public constructor is this version doesn't set
|
||||
* the name.
|
||||
*/
|
||||
AntUnitSuite(final File scriptFile) {
|
||||
MyProjectFactory prjFactory = new MyProjectFactory(scriptFile);
|
||||
antScriptRunner = new AntUnitScriptRunner(prjFactory);
|
||||
stdout = new MultiProjectDemuxOutputStream(antScriptRunner, false);
|
||||
stderr = new MultiProjectDemuxOutputStream(antScriptRunner, true);
|
||||
setName(antScriptRunner.getName() + "[" + scriptFile + "]");
|
||||
List testTargets = antScriptRunner.getTestTartgets();
|
||||
for (Iterator it = testTargets.iterator(); it.hasNext();) {
|
||||
String target = (String) it.next();
|
||||
AntUnitTestCase tc = new AntUnitTestCase(this, scriptFile, target);
|
||||
addTest(tc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Override Run the full AntUnit suite
|
||||
*/
|
||||
public void run(TestResult testResult) {
|
||||
List testTartgets = antScriptRunner.getTestTartgets();
|
||||
runInContainer(testTartgets, testResult, tests());
|
||||
}
|
||||
|
||||
/**
|
||||
* @Override Run a single test target of the AntUnit suite. suiteSetUp,
|
||||
* setUp, tearDown and suiteTearDown are executed around it.
|
||||
*/
|
||||
public void runTest(Test test, TestResult result) {
|
||||
String targetName = ((AntUnitTestCase) test).getTarget();
|
||||
List singleTargetList = Collections.singletonList(targetName);
|
||||
Enumeration singleTestList = Collections.enumeration(Collections
|
||||
.singletonList(test));
|
||||
runInContainer(singleTargetList, result, singleTestList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the test suite in a 'container' similar to the ant 'container'.
|
||||
* When ant executes a project it redirect the input and the output. In this
|
||||
* context we will only redirect output (unit test are not supposed to be
|
||||
* interactive)
|
||||
*
|
||||
* @param targetList
|
||||
* The list of test target to execute
|
||||
* @param result
|
||||
* The JUnit3 TestResult receiving result notification
|
||||
* @param tests
|
||||
* The JUnit3 Test classes instances to use in the notification.
|
||||
*/
|
||||
private void runInContainer(List targetList, TestResult result,
|
||||
Enumeration/*<Test>*/tests) {
|
||||
JUnitNotificationAdapter notifier = new JUnitNotificationAdapter(
|
||||
result, tests);
|
||||
PrintStream savedErr = System.err;
|
||||
PrintStream savedOut = System.out;
|
||||
try {
|
||||
System.setOut(new PrintStream(stdout));
|
||||
System.setErr(new PrintStream(stderr));
|
||||
antScriptRunner.runSuite(targetList, notifier);
|
||||
} finally {
|
||||
System.setOut(savedOut);
|
||||
System.setErr(savedErr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The antscript project factory that creates projects in a junit context.
|
||||
*/
|
||||
private static class MyProjectFactory implements ProjectFactory {
|
||||
|
||||
private final File scriptFile;
|
||||
private final PrintStream realStdErr = System.err;
|
||||
private final PrintStream realStdOut = System.out;
|
||||
|
||||
public MyProjectFactory(File scriptFile) {
|
||||
this.scriptFile = scriptFile;
|
||||
}
|
||||
|
||||
public Project createProject() {
|
||||
ProjectHelper prjHelper = ProjectHelper.getProjectHelper();
|
||||
Project prj = new Project();
|
||||
DefaultLogger logger = new DefaultLogger();
|
||||
logger.setMessageOutputLevel(Project.MSG_INFO);
|
||||
logger.setErrorPrintStream(realStdErr);
|
||||
logger.setOutputPrintStream(realStdOut);
|
||||
prj.addBuildListener(logger);
|
||||
String absolutePath = scriptFile.getAbsolutePath();
|
||||
prj.setUserProperty(MagicNames.ANT_FILE, absolutePath);
|
||||
prj.addReference(ProjectHelper.PROJECTHELPER_REFERENCE, prjHelper);
|
||||
prj.init();
|
||||
prjHelper.parse(prj, scriptFile);
|
||||
return prj;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.ant.antunit.junit3;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestResult;
|
||||
|
||||
/**
|
||||
* JUnit TestCase that will executes a single AntUnit target. This class is not
|
||||
* supposed to be used directly. <br/>
|
||||
* It is public only because junit must access it as a public.
|
||||
*/
|
||||
public class AntUnitTestCase extends TestCase {
|
||||
// We have to extends TestCase, and not implements Test because otherwise
|
||||
// JUnit4 will derive the Description composing the suite description from
|
||||
// this className only (AntUnitTestCase), and not from the name.
|
||||
// However, during execution it use the right Description (base on the
|
||||
// toString)
|
||||
|
||||
/**
|
||||
* AntUnitSuite that contains this AntUnitTestCase. Execution is done via
|
||||
* this suite
|
||||
*/
|
||||
private final AntUnitSuite suite;
|
||||
|
||||
/**
|
||||
* The test target
|
||||
*/
|
||||
private final String target;
|
||||
|
||||
/**
|
||||
* Prepare an AntUnitTestCase that will be executed alone. This constructor
|
||||
* is typically used by a junit 3 runner that will reexecute a specific
|
||||
* test.</br>
|
||||
* The execution of this test will be embed in a suiteSetUp and
|
||||
* suiteTearDown.
|
||||
* @param name The name of the AntUnitTestCase, normally obtained from a
|
||||
* previous execution.
|
||||
*/
|
||||
public AntUnitTestCase(String name) {
|
||||
super(name);
|
||||
TestCaseName nameParser = new TestCaseName(name);
|
||||
target = nameParser.getTarget();
|
||||
suite = new AntUnitSuite(nameParser.getScript());
|
||||
// TODO : check that target is in the list
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an AntUnitTestCase that will be executed in a suite. It is the
|
||||
* suite that prepare the antScriptRunner and the JUnitExcutionPlatform. It
|
||||
* is the responsibility of the suite to execute the suiteSetUp and the
|
||||
* suiteTearDown.
|
||||
*
|
||||
* @param target
|
||||
* @param antScriptRunner
|
||||
* @param executionEnv
|
||||
*/
|
||||
public AntUnitTestCase(AntUnitSuite suite, File scriptFile, String target) {
|
||||
// The name can be reused by eclipse when running a single test
|
||||
super(new TestCaseName(scriptFile, target).getName());
|
||||
this.target = target;
|
||||
this.suite = suite;
|
||||
}
|
||||
|
||||
/** Get the AntUnit test target name */
|
||||
public String getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
/** @overwrite */
|
||||
public void run(TestResult result) {
|
||||
suite.runTest(this, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the serialization and the parsing of the name of a TestCase. The
|
||||
* name of the TestCase contains the filename of the script and the target,
|
||||
* so that the name uniquely identify the TestCase, and a TestCase can be
|
||||
* executed from its name.
|
||||
*/
|
||||
static class TestCaseName {
|
||||
private final String name;
|
||||
private final File script;
|
||||
private final String target;
|
||||
|
||||
public TestCaseName(String name) {
|
||||
this.name = name;
|
||||
this.target = name.substring(0, name.indexOf(' '));
|
||||
String filename = name.substring(name.indexOf(' ') + 2, name
|
||||
.length() - 1);
|
||||
this.script = new File(filename);
|
||||
}
|
||||
|
||||
public TestCaseName(File script, String target) {
|
||||
this.script = script;
|
||||
this.target = target;
|
||||
this.name = target + " [" + script + "]";
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public File getScript() {
|
||||
return script;
|
||||
}
|
||||
|
||||
public String getTarget() {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.ant.antunit.junit3;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestResult;
|
||||
|
||||
import org.apache.ant.antunit.AntUnitExecutionNotifier;
|
||||
import org.apache.ant.antunit.AssertionFailedException;
|
||||
|
||||
/**
|
||||
* Adapt AntUnitExecutionNotifier events into JUnit3 TestResult events
|
||||
*/
|
||||
class JUnitNotificationAdapter implements AntUnitExecutionNotifier {
|
||||
|
||||
private final TestResult junitTestResult;
|
||||
private Map testByTarget = new HashMap();
|
||||
|
||||
public JUnitNotificationAdapter(TestResult testResult, Enumeration tests) {
|
||||
this.junitTestResult = testResult;
|
||||
while(tests.hasMoreElements()) {
|
||||
AntUnitTestCase test = (AntUnitTestCase) tests.nextElement();
|
||||
testByTarget.put(test.getTarget(), test);
|
||||
}
|
||||
}
|
||||
|
||||
public void fireStartTest(String targetName) {
|
||||
//TODO : if it is null, eclipse stop the unit test (add a unit test)
|
||||
junitTestResult.startTest((Test) testByTarget.get(targetName));
|
||||
}
|
||||
|
||||
public void fireEndTest(String targetName) {
|
||||
junitTestResult.endTest((Test) testByTarget.get(targetName));
|
||||
}
|
||||
|
||||
public void fireError(String targetName, Throwable t) {
|
||||
junitTestResult.addError((Test) testByTarget.get(targetName), t);
|
||||
}
|
||||
|
||||
public void fireFail(String targetName, AssertionFailedException ae) {
|
||||
//I don't see how to transform the AntUnit assertion exception into
|
||||
//junit assertion exception (we would loose the stack trace).
|
||||
//So failures will be reported as errors
|
||||
junitTestResult.addError((Test) testByTarget.get(targetName), ae);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.ant.antunit.junit3;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.ant.antunit.AntUnitScriptRunner;
|
||||
import org.apache.tools.ant.DemuxOutputStream;
|
||||
import org.apache.tools.ant.Project;
|
||||
|
||||
|
||||
/**
|
||||
* Forward stdout or stderr operation to the current antunit project.
|
||||
*/
|
||||
class MultiProjectDemuxOutputStream extends OutputStream {
|
||||
|
||||
private final AntUnitScriptRunner scriptRunner;
|
||||
|
||||
private Project lastProject;
|
||||
private DemuxOutputStream lastDemuxOutputStream = null;
|
||||
|
||||
private final boolean isErrorStream;
|
||||
|
||||
public MultiProjectDemuxOutputStream(AntUnitScriptRunner scriptRunner, boolean isErrorStream) {
|
||||
this.scriptRunner = scriptRunner;
|
||||
this.isErrorStream = isErrorStream;
|
||||
}
|
||||
|
||||
|
||||
private DemuxOutputStream getDemuxOutputStream() {
|
||||
if (lastProject != scriptRunner.getCurrentProject()) {
|
||||
lastProject = scriptRunner.getCurrentProject();
|
||||
lastDemuxOutputStream = new DemuxOutputStream(lastProject,isErrorStream);
|
||||
}
|
||||
return lastDemuxOutputStream;
|
||||
}
|
||||
|
||||
public void write(int b) throws IOException {
|
||||
getDemuxOutputStream().write(b);
|
||||
}
|
||||
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
getDemuxOutputStream().write(b, off, len);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
getDemuxOutputStream().close();
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
getDemuxOutputStream().flush();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.ant.antunit.junit4;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.apache.ant.antunit.junit3.AntUnitSuite;
|
||||
import org.apache.ant.antunit.junit3.AntUnitTestCase;
|
||||
import org.junit.internal.runners.CompositeRunner;
|
||||
import org.junit.internal.runners.InitializationError;
|
||||
|
||||
/**
|
||||
* JUnit4 Runner to put in a RunWith annotation of the AntUnitSuite when using a
|
||||
* JUnit4 runner. Using this runner is not mandatory because junit4 is able to
|
||||
* run junit3 test. However, the test will be faster (TODO make that true :-) )
|
||||
* with this Runner. Also, more features are available when this runner is used
|
||||
* (filtering & sorting)
|
||||
* TODO Support filtering and sorting
|
||||
*/
|
||||
public class AntUnitSuiteRunner extends CompositeRunner {
|
||||
|
||||
private AntUnitSuiteRunner(AntUnitSuite suite, Class junitTestClass) {
|
||||
super(suite.getName());
|
||||
Enumeration tests = suite.tests();
|
||||
while (tests.hasMoreElements()) {
|
||||
AntUnitTestCase tc = (AntUnitTestCase) tests.nextElement();
|
||||
add(new AntUnitTestCaseRunner(tc, junitTestClass));
|
||||
}
|
||||
}
|
||||
|
||||
public AntUnitSuiteRunner(Class testCaseClass) throws InitializationError {
|
||||
this(getJUnit3AntSuite(testCaseClass), testCaseClass);
|
||||
}
|
||||
|
||||
private static AntUnitSuite getJUnit3AntSuite(Class testCaseClass)
|
||||
throws InitializationError {
|
||||
try {
|
||||
Method suiteMethod = testCaseClass.getMethod("suite", new Class[0]);
|
||||
if (!Modifier.isStatic(suiteMethod.getModifiers())) {
|
||||
throw new InitializationError("suite method must be static");
|
||||
}
|
||||
return (AntUnitSuite) suiteMethod.invoke(null, new Object[0]);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new InitializationError(new Throwable[] { e });
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InitializationError(new Throwable[] { e });
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new InitializationError(new Throwable[] { e });
|
||||
} catch (ClassCastException e) {
|
||||
throw new InitializationError(new Throwable[] { e });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.ant.antunit.junit4;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestListener;
|
||||
import junit.framework.TestResult;
|
||||
|
||||
import org.apache.ant.antunit.junit3.AntUnitTestCase;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.Runner;
|
||||
import org.junit.runner.notification.Failure;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
|
||||
|
||||
class AntUnitTestCaseRunner extends Runner {
|
||||
|
||||
private final AntUnitTestCase fTest;
|
||||
private final Class junitTestClass;
|
||||
|
||||
public AntUnitTestCaseRunner(AntUnitTestCase testCase, Class junitTestClass) {
|
||||
this.fTest = testCase;
|
||||
this.junitTestClass = junitTestClass;
|
||||
}
|
||||
|
||||
public void run(final RunNotifier notifier) {
|
||||
final Description description = getDescription();
|
||||
TestListener testListener = new TestListener() {
|
||||
// TODO implement directly the mapping from AntUnitExecutionNotifier
|
||||
// to junit4 RunNotifier
|
||||
public void endTest(Test test) {
|
||||
notifier.fireTestFinished(description);
|
||||
}
|
||||
|
||||
public void startTest(Test test) {
|
||||
notifier.fireTestStarted(description);
|
||||
}
|
||||
|
||||
public void addError(Test test, Throwable t) {
|
||||
Failure failure = new Failure(description, t);
|
||||
notifier.fireTestFailure(failure);
|
||||
}
|
||||
|
||||
public void addFailure(Test test, AssertionFailedError t) {
|
||||
addError(test, t);
|
||||
}
|
||||
};
|
||||
TestResult result = new TestResult();
|
||||
result.addListener(testListener);
|
||||
fTest.run(result);
|
||||
}
|
||||
|
||||
public Description getDescription() {
|
||||
return Description.createTestDescription(junitTestClass, fTest
|
||||
.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.ant.antunit.junit3;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestResult;
|
||||
|
||||
import org.apache.tools.ant.util.FileUtils;
|
||||
|
||||
public class AntUnitSuiteTest extends TestCase {
|
||||
|
||||
AntUnitSuite suite = new AntUnitSuite(new File(
|
||||
"src/etc/testcases/antunit/junit.xml"));
|
||||
File outFile = new File("target/test_output/junit_out.xml");
|
||||
|
||||
public void testRunSuiteSetUp() throws FileNotFoundException, IOException {
|
||||
|
||||
TestResult testResult = new TestResult();
|
||||
suite.run(testResult);
|
||||
assertTrue(testResult.wasSuccessful());
|
||||
|
||||
String output = FileUtils.readFully(new FileReader(outFile));
|
||||
String EXPECT1 = "suiteSetUp-setUp-test1-tearDown-setUp-test2-tearDown-suiteTearDown";
|
||||
String EXPECT2 = "suiteSetUp-setUp-test2-tearDown-setUp-test1-tearDown-suiteTearDown";
|
||||
assertTrue("unexted output : " + output, EXPECT1.equals(output)
|
||||
|| EXPECT2.equals(output));
|
||||
}
|
||||
|
||||
public void testSuiteName() {
|
||||
assertTrue("Expected non empty suite name", suite.getName().trim()
|
||||
.length() > 0);
|
||||
}
|
||||
|
||||
public void testChildNames() {
|
||||
assertTrue("Expected more test, received " + suite.testCount(),
|
||||
suite.testCount() >= 1);
|
||||
|
||||
Enumeration/*<Test>*/tests = suite.tests();
|
||||
StringBuffer testTargets = new StringBuffer();
|
||||
while (tests.hasMoreElements()) {
|
||||
String nextName = tests.nextElement().toString();
|
||||
testTargets.append(" ").append(nextName).append(" ,");
|
||||
}
|
||||
|
||||
assertTrue("test1 not found in child : " + testTargets, testTargets
|
||||
.toString().contains(" test1 "));
|
||||
}
|
||||
|
||||
public void testSingleTestRunSuiteSetUp() throws Exception {
|
||||
AntUnitTestCase test1 = (AntUnitTestCase) suite.testAt(0);
|
||||
if (test1.getTarget().equals("test2")) {
|
||||
test1 = (AntUnitTestCase) suite.testAt(1);
|
||||
}
|
||||
TestResult testResult = new TestResult();
|
||||
suite.runTest(test1, testResult);
|
||||
assertTrue(testResult.wasSuccessful());
|
||||
|
||||
String output = FileUtils.readFully(new FileReader(outFile));
|
||||
assertTrue("unexted output : " + output,
|
||||
"suiteSetUp-setUp-test1-tearDown-suiteTearDown".equals(output));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package org.apache.ant.antunit.junit3;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.ant.antunit.junit3.AntUnitTestCase;
|
||||
import org.apache.tools.ant.util.FileUtils;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestResult;
|
||||
|
||||
public class AntUnitTestCaseTest extends TestCase {
|
||||
|
||||
File f = new File("src/etc/testcases/antunit/junit.xml");
|
||||
String test1Name = new AntUnitTestCase.TestCaseName(f, "test1").getName();
|
||||
|
||||
File outFile = new File("target/test_output/junit_out.xml");
|
||||
|
||||
public void testNameParsing() {
|
||||
AntUnitTestCase.TestCaseName nameObj = new AntUnitTestCase.TestCaseName(
|
||||
test1Name);
|
||||
assertEquals(f, nameObj.getScript());
|
||||
assertEquals("test1", nameObj.getTarget());
|
||||
}
|
||||
|
||||
public void testRunSuiteSetUp() throws FileNotFoundException, IOException {
|
||||
// When eclipse has to run a specific testCase (user click Run on it),
|
||||
// an AntUnitTestCase(name) is created, and the run should execute the
|
||||
// suiteSetup/SuiteTearDown
|
||||
AntUnitTestCase antUnitTestCase = new AntUnitTestCase(test1Name);
|
||||
|
||||
TestResult testResult = new TestResult();
|
||||
antUnitTestCase.run(testResult);
|
||||
assertTrue(testResult.wasSuccessful());
|
||||
|
||||
String output = FileUtils.readFully(new FileReader(outFile));
|
||||
assertEquals("suiteSetUp-setUp-test1-tearDown-suiteTearDown", output);
|
||||
}
|
||||
|
||||
private Test startedTest = null;
|
||||
private Test endedTest = null;
|
||||
|
||||
public void testTestIdentityInNotification() {
|
||||
// When eclipse has to run a specific testCase (user click Run on it),
|
||||
// an AntUnitTestCase(name) is created, and this instance must be used
|
||||
// in the notification (otherwise the test appears twice, once normal
|
||||
// but never executed, and once with "Unrooted Tests" parent.
|
||||
TestResult testResultMock = new TestResult() {
|
||||
public void startTest(Test test) {
|
||||
// Note that putting an assertion here to fail fatser doesn't
|
||||
// work because
|
||||
// exceptions are catched by the runner
|
||||
startedTest = test;
|
||||
}
|
||||
|
||||
public void endTest(Test test) {
|
||||
endedTest = test;
|
||||
}
|
||||
};
|
||||
|
||||
AntUnitTestCase antUnitTestCase = new AntUnitTestCase(test1Name);
|
||||
antUnitTestCase.run(testResultMock);
|
||||
|
||||
Assert.assertSame(antUnitTestCase, startedTest);
|
||||
Assert.assertSame(antUnitTestCase, endedTest);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package org.apache.ant.antunit.junit3;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.apache.ant.antunit.junit4.AntUnitSuiteRunner;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* A unit test using the junit3 and junit4 adapter.
|
||||
*/
|
||||
@RunWith(AntUnitSuiteRunner.class)
|
||||
public class EatYourOwnDogFoodTest extends TestCase {
|
||||
|
||||
public static TestSuite suite() {
|
||||
File script = new File("src/etc/testcases/antunit/java-io.xml");
|
||||
return new AntUnitSuite(script, EatYourOwnDogFoodTest.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package org.apache.ant.antunit.junit4;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.ant.antunit.junit3.AntUnitSuite;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.internal.runners.InitializationError;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
|
||||
public class AntUnitSuiteTest extends TestCase {
|
||||
|
||||
private boolean mockExecutionOK = false;
|
||||
private String mockExcutionError = "";
|
||||
|
||||
/**
|
||||
* When a test is executed, the description used in the notification must be
|
||||
* equals to the description declared, otherwise the runner is confused (for
|
||||
* example in eclipse you have all the tests listed twice, but reported only
|
||||
* once as executed.
|
||||
*
|
||||
* @throws InitializationError
|
||||
*/
|
||||
public void testDescriptionsReportedInNotifier() throws InitializationError {
|
||||
final AntUnitSuiteRunner runner = new AntUnitSuiteRunner(
|
||||
JUnit4AntUnitRunnable.class);
|
||||
final ArrayList tDescs = runner.getDescription().getChildren();
|
||||
|
||||
final int TEST_STARTED = 1, TEST_FINISHED = 2;
|
||||
RunNotifier notifierMock = new RunNotifier() {
|
||||
Description curTest = null;
|
||||
|
||||
public void fireTestStarted(Description description) {
|
||||
if (curTest != null) {
|
||||
mockExcutionError += "Unexpected fireTestStarted("
|
||||
+ description.getDisplayName() + "\n";
|
||||
}
|
||||
if (!tDescs.contains(description)) {
|
||||
mockExcutionError += "Unexpected fireTestStarted("
|
||||
+ description.getDisplayName() + ")\n";
|
||||
}
|
||||
curTest = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireTestFinished(Description description) {
|
||||
if (curTest == null) {
|
||||
mockExcutionError += "Unexpected fireTestFinished("
|
||||
+ description.getDisplayName() + "\n";
|
||||
}
|
||||
if (!curTest.equals(description)) {
|
||||
mockExcutionError += "Unexpected fireTestFinished("
|
||||
+ description.getDisplayName() + "); expect "
|
||||
+ curTest.getDisplayName() + "\n";
|
||||
}
|
||||
curTest = null;
|
||||
mockExecutionOK = true;
|
||||
}
|
||||
};
|
||||
|
||||
runner.run(notifierMock);
|
||||
assertTrue(mockExcutionError, mockExcutionError.isEmpty());
|
||||
assertTrue(mockExecutionOK);
|
||||
}
|
||||
|
||||
public void testMissingSuiteMethodInitializationError() {
|
||||
try {
|
||||
AntUnitSuiteRunner runner = new AntUnitSuiteRunner(
|
||||
JUnit4AntUnitRunnableWithoutSuiteMethod.class);
|
||||
fail("InitializationError expected");
|
||||
} catch (InitializationError e) {
|
||||
String msg = e.getCauses().get(0).getMessage();
|
||||
assertTrue("Unexpected error : " + msg, msg.contains("suite"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testNonStaticSuiteMethodInitializationError() {
|
||||
try {
|
||||
AntUnitSuiteRunner runner = new AntUnitSuiteRunner(
|
||||
JUnit4AntUnitRunnableWithNonStaticSuite.class);
|
||||
fail("InitializationError expected");
|
||||
} catch (InitializationError e) {
|
||||
String msg = e.getCauses().get(0).getMessage();
|
||||
assertTrue("Unexpected error : " + msg, msg.contains("suite"));
|
||||
assertTrue("Unexpected error : " + msg, msg.contains("static"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class JUnit4AntUnitRunnable {
|
||||
public static AntUnitSuite suite() {
|
||||
File f = new File("src/etc/testcases/antunit/junit.xml");
|
||||
return new AntUnitSuite(f, JUnit4AntUnitRunnable.class);
|
||||
}
|
||||
}
|
||||
|
||||
public static class JUnit4AntUnitRunnableWithNonStaticSuite {
|
||||
public AntUnitSuite suite() {
|
||||
File f = new File("src/etc/testcases/antunit/junit.xml");
|
||||
return new AntUnitSuite(f,
|
||||
JUnit4AntUnitRunnableWithNonStaticSuite.class);
|
||||
}
|
||||
}
|
||||
|
||||
public static class JUnit4AntUnitRunnableWithoutSuiteMethod {
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue