Index: pom.xml =================================================================== --- pom.xml (revision 452990) +++ pom.xml (working copy) @@ -27,7 +27,7 @@ junit junit - 3.8.1 + 4.0 Index: src/main/java/org/apache/maven/surefire/junit4/JUnit4StackTraceWriter.java =================================================================== --- src/main/java/org/apache/maven/surefire/junit4/JUnit4StackTraceWriter.java (revision 0) +++ src/main/java/org/apache/maven/surefire/junit4/JUnit4StackTraceWriter.java (revision 0) @@ -0,0 +1,58 @@ +package org.apache.maven.surefire.junit4; + +import org.apache.maven.surefire.report.StackTraceWriter; +import org.junit.runner.notification.Failure; + +/** + * Writes out a specific {@link org.junit.runner.notification.Failure} for + * surefire as a stacktrace. + * + * @author Karl M. Davis + */ +public class JUnit4StackTraceWriter implements StackTraceWriter +{ + // Member Variables + private Failure junitFailure; + + /** + * Constructor. + * + * @param junitFailure + * the {@link Failure} that this will be operating on + */ + public JUnit4StackTraceWriter(Failure junitFailure) + { + this.junitFailure = junitFailure; + } + + /* + * (non-Javadoc) + * + * @see org.apache.maven.surefire.report.StackTraceWriter#writeTraceToString() + */ + public String writeTraceToString() + { + return junitFailure.getTrace(); + } + + /** + * At the moment, returns the same as {@link #writeTraceToString()}. + * + * @see org.apache.maven.surefire.report.StackTraceWriter#writeTrimmedTraceToString() + */ + public String writeTrimmedTraceToString() + { + return junitFailure.getTrace(); + } + + /** + * Returns the exception associated with this failure. + * + * @see org.apache.maven.surefire.report.StackTraceWriter#getThrowable() + */ + public Throwable getThrowable() + { + return junitFailure.getException(); + } + +} Index: src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSet.java =================================================================== --- src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSet.java (revision 0) +++ src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSet.java (revision 0) @@ -0,0 +1,59 @@ +package org.apache.maven.surefire.junit4; + +import org.apache.maven.surefire.report.ReporterManager; +import org.apache.maven.surefire.testset.AbstractTestSet; +import org.apache.maven.surefire.testset.TestSetFailedException; +import org.junit.runner.Request; +import org.junit.runner.Runner; +import org.junit.runner.notification.RunListener; +import org.junit.runner.notification.RunNotifier; + +public class JUnit4TestSet extends AbstractTestSet +{ + // Member Variables + private Runner junitTestRunner; + + /** + * Constructor. + * + * @param testClass the class to be run as a test + */ + protected JUnit4TestSet(Class testClass) + { + super(testClass); + + junitTestRunner = Request.aClass(testClass).getRunner(); + } + + /** + * Actually runs the test and adds the tests results to the reportManager. + * + * @see org.apache.maven.surefire.testset.SurefireTestSet#execute(org.apache.maven.surefire.report.ReporterManager, java.lang.ClassLoader) + */ + public void execute(ReporterManager reportManager, ClassLoader loader) + throws TestSetFailedException + { + RunNotifier fNotifier = new RunNotifier(); + RunListener listener = new JUnit4TestSetReporter(this, reportManager); + fNotifier.addListener(listener); + + try + { + junitTestRunner.run(fNotifier); + } + finally + { + fNotifier.removeListener(listener); + } + } + + /** + * Returns the number of tests to be run in this class. + * + * @see org.apache.maven.surefire.testset.SurefireTestSet#getTestCount() + */ + public int getTestCount() throws TestSetFailedException + { + return junitTestRunner.testCount(); + } +} Index: src/main/java/org/apache/maven/surefire/junit4/JUnit4DirectoryTestSuite.java =================================================================== --- src/main/java/org/apache/maven/surefire/junit4/JUnit4DirectoryTestSuite.java (revision 0) +++ src/main/java/org/apache/maven/surefire/junit4/JUnit4DirectoryTestSuite.java (revision 0) @@ -0,0 +1,41 @@ +package org.apache.maven.surefire.junit4; + +import java.io.File; +import java.util.ArrayList; + +import org.apache.maven.surefire.suite.AbstractDirectoryTestSuite; +import org.apache.maven.surefire.testset.SurefireTestSet; +import org.apache.maven.surefire.testset.TestSetFailedException; + +/** + * Test suite for JUnit4 based on a directory of Java test classes. This is + * capable of running both JUnit3 and JUnit4 test classes (I think). + * + * @author Karl M. Davis + */ +public class JUnit4DirectoryTestSuite extends AbstractDirectoryTestSuite +{ + /** + * Constructor. + */ + public JUnit4DirectoryTestSuite(File basedir, ArrayList includes, + ArrayList excludes) + { + super(basedir, includes, excludes); + } + + /** + * This method will be called for each class to be run as a test. It returns + * a surefire test set that will later be executed. + * + * @see org.apache.maven.surefire.suite.AbstractDirectoryTestSuite#createTestSet(java.lang.Class, + * java.lang.ClassLoader) + */ + @Override + protected SurefireTestSet createTestSet(Class testClass, + ClassLoader classLoader) throws TestSetFailedException + { + return new JUnit4TestSet(testClass); + } + +} Index: src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSetReporter.java =================================================================== --- src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSetReporter.java (revision 0) +++ src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSetReporter.java (revision 0) @@ -0,0 +1,135 @@ +package org.apache.maven.surefire.junit4; + +import java.util.ResourceBundle; + +import org.apache.maven.surefire.Surefire; +import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.ReporterManager; +import org.junit.runner.Description; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunListener; + +public class JUnit4TestSetReporter extends RunListener +{ + // Constants + private static ResourceBundle bundle = ResourceBundle.getBundle( Surefire.SUREFIRE_BUNDLE_NAME ); + + // Member Variables + private JUnit4TestSet testSet; + private ReporterManager reportMgr; + /** + * This flag is set after a failure has occurred so that a testSucceeded event is not fired. This is necessary because JUnit4 always fires a testRunFinished event-- even if there was a failure. + */ + private boolean failureFlag; + + /** + * Constructor. + * + * @param testSet + * the specific test set that this will report on as it is + * executed + * @param reportManager + * the report manager to log testing events to + */ + JUnit4TestSetReporter(JUnit4TestSet testSet, ReporterManager reportManager) + { + this.testSet = testSet; + this.reportMgr = reportManager; + } + + /** + * Called right before any tests from a specific class are run. + * + * @see org.junit.runner.notification.RunListener#testRunStarted(org.junit.runner.Description) + */ + @Override + public void testRunStarted(Description description) throws Exception + { + String rawString = bundle.getString( "testSetStarting" ); + ReportEntry report = new ReportEntry(testSet, testSet.getName(), rawString); + + this.reportMgr.testSetStarting(report); + } + + /** + * Called right after all tests from a specific class are run. + * + * @see org.junit.runner.notification.RunListener#testRunFinished(org.junit.runner.Result) + */ + @Override + public void testRunFinished(Result result) throws Exception + { + String rawString = bundle.getString( "testSetCompletedNormally" ); + ReportEntry report = new ReportEntry(testSet, testSet.getName(), rawString); + + this.reportMgr.testSetCompleted(report); + this.reportMgr.reset(); + } + + /** + * Called when a specific test has been skipped (for whatever reason). + * + * @see org.junit.runner.notification.RunListener#testIgnored(org.junit.runner.Description) + */ + @Override + public void testIgnored(Description description) throws Exception + { + String rawString = bundle.getString( "testSkipped" ); + ReportEntry report = new ReportEntry(testSet, description.getDisplayName(), rawString); + + this.reportMgr.testSkipped(report); + } + + /** + * Called when a specific test has started. + * + * @see org.junit.runner.notification.RunListener#testStarted(org.junit.runner.Description) + */ + @Override + public void testStarted(Description description) throws Exception + { + String rawString = bundle.getString( "testStarting" ); + ReportEntry report = new ReportEntry(testSet, description.getDisplayName(), rawString); + + this.reportMgr.testStarting(report); + + this.failureFlag = false; + } + + /** + * Called when a specific test has failed. + * + * @see org.junit.runner.notification.RunListener#testFailure(org.junit.runner.notification.Failure) + */ + @Override + public void testFailure(Failure failure) throws Exception + { + String rawString = bundle.getString( "executeException" ); + ReportEntry report = new ReportEntry(testSet, failure.getTestHeader(), rawString, new JUnit4StackTraceWriter(failure)); + + if(failure.getException() instanceof AssertionError) + this.reportMgr.testFailed(report); + else + this.reportMgr.testError(report); + + failureFlag = true; + } + + /** + * Called after a specific test has finished. + * + * @see org.junit.runner.notification.RunListener#testFinished(org.junit.runner.Description) + */ + @Override + public void testFinished(Description description) throws Exception + { + if(failureFlag == false) + { + String rawString = bundle.getString( "testSuccessful" ); + ReportEntry report = new ReportEntry(testSet, description.getDisplayName(), rawString); + + this.reportMgr.testSucceeded(report); + } + } +} Index: src/main/java/org/apache/maven/surefire/junit4/JUnit4DirectoryTestSuite.java =================================================================== --- src/main/java/org/apache/maven/surefire/junit4/JUnit4DirectoryTestSuite.java (revision 0) +++ src/main/java/org/apache/maven/surefire/junit4/JUnit4DirectoryTestSuite.java (revision 0) @@ -0,0 +1,41 @@ +package org.apache.maven.surefire.junit4; + +import java.io.File; +import java.util.ArrayList; + +import org.apache.maven.surefire.suite.AbstractDirectoryTestSuite; +import org.apache.maven.surefire.testset.SurefireTestSet; +import org.apache.maven.surefire.testset.TestSetFailedException; + +/** + * Test suite for JUnit4 based on a directory of Java test classes. This is + * capable of running both JUnit3 and JUnit4 test classes (I think). + * + * @author Karl M. Davis + */ +public class JUnit4DirectoryTestSuite extends AbstractDirectoryTestSuite +{ + /** + * Constructor. + */ + public JUnit4DirectoryTestSuite(File basedir, ArrayList includes, + ArrayList excludes) + { + super(basedir, includes, excludes); + } + + /** + * This method will be called for each class to be run as a test. It returns + * a surefire test set that will later be executed. + * + * @see org.apache.maven.surefire.suite.AbstractDirectoryTestSuite#createTestSet(java.lang.Class, + * java.lang.ClassLoader) + */ + @Override + protected SurefireTestSet createTestSet(Class testClass, + ClassLoader classLoader) throws TestSetFailedException + { + return new JUnit4TestSet(testClass); + } + +} Index: src/main/java/org/apache/maven/surefire/junit4/JUnit4StackTraceWriter.java =================================================================== --- src/main/java/org/apache/maven/surefire/junit4/JUnit4StackTraceWriter.java (revision 0) +++ src/main/java/org/apache/maven/surefire/junit4/JUnit4StackTraceWriter.java (revision 0) @@ -0,0 +1,58 @@ +package org.apache.maven.surefire.junit4; + +import org.apache.maven.surefire.report.StackTraceWriter; +import org.junit.runner.notification.Failure; + +/** + * Writes out a specific {@link org.junit.runner.notification.Failure} for + * surefire as a stacktrace. + * + * @author Karl M. Davis + */ +public class JUnit4StackTraceWriter implements StackTraceWriter +{ + // Member Variables + private Failure junitFailure; + + /** + * Constructor. + * + * @param junitFailure + * the {@link Failure} that this will be operating on + */ + public JUnit4StackTraceWriter(Failure junitFailure) + { + this.junitFailure = junitFailure; + } + + /* + * (non-Javadoc) + * + * @see org.apache.maven.surefire.report.StackTraceWriter#writeTraceToString() + */ + public String writeTraceToString() + { + return junitFailure.getTrace(); + } + + /** + * At the moment, returns the same as {@link #writeTraceToString()}. + * + * @see org.apache.maven.surefire.report.StackTraceWriter#writeTrimmedTraceToString() + */ + public String writeTrimmedTraceToString() + { + return junitFailure.getTrace(); + } + + /** + * Returns the exception associated with this failure. + * + * @see org.apache.maven.surefire.report.StackTraceWriter#getThrowable() + */ + public Throwable getThrowable() + { + return junitFailure.getException(); + } + +} Index: src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSet.java =================================================================== --- src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSet.java (revision 0) +++ src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSet.java (revision 0) @@ -0,0 +1,59 @@ +package org.apache.maven.surefire.junit4; + +import org.apache.maven.surefire.report.ReporterManager; +import org.apache.maven.surefire.testset.AbstractTestSet; +import org.apache.maven.surefire.testset.TestSetFailedException; +import org.junit.runner.Request; +import org.junit.runner.Runner; +import org.junit.runner.notification.RunListener; +import org.junit.runner.notification.RunNotifier; + +public class JUnit4TestSet extends AbstractTestSet +{ + // Member Variables + private Runner junitTestRunner; + + /** + * Constructor. + * + * @param testClass the class to be run as a test + */ + protected JUnit4TestSet(Class testClass) + { + super(testClass); + + junitTestRunner = Request.aClass(testClass).getRunner(); + } + + /** + * Actually runs the test and adds the tests results to the reportManager. + * + * @see org.apache.maven.surefire.testset.SurefireTestSet#execute(org.apache.maven.surefire.report.ReporterManager, java.lang.ClassLoader) + */ + public void execute(ReporterManager reportManager, ClassLoader loader) + throws TestSetFailedException + { + RunNotifier fNotifier = new RunNotifier(); + RunListener listener = new JUnit4TestSetReporter(this, reportManager); + fNotifier.addListener(listener); + + try + { + junitTestRunner.run(fNotifier); + } + finally + { + fNotifier.removeListener(listener); + } + } + + /** + * Returns the number of tests to be run in this class. + * + * @see org.apache.maven.surefire.testset.SurefireTestSet#getTestCount() + */ + public int getTestCount() throws TestSetFailedException + { + return junitTestRunner.testCount(); + } +} Index: src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSetReporter.java =================================================================== --- src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSetReporter.java (revision 0) +++ src/main/java/org/apache/maven/surefire/junit4/JUnit4TestSetReporter.java (revision 0) @@ -0,0 +1,135 @@ +package org.apache.maven.surefire.junit4; + +import java.util.ResourceBundle; + +import org.apache.maven.surefire.Surefire; +import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.ReporterManager; +import org.junit.runner.Description; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunListener; + +public class JUnit4TestSetReporter extends RunListener +{ + // Constants + private static ResourceBundle bundle = ResourceBundle.getBundle( Surefire.SUREFIRE_BUNDLE_NAME ); + + // Member Variables + private JUnit4TestSet testSet; + private ReporterManager reportMgr; + /** + * This flag is set after a failure has occurred so that a testSucceeded event is not fired. This is necessary because JUnit4 always fires a testRunFinished event-- even if there was a failure. + */ + private boolean failureFlag; + + /** + * Constructor. + * + * @param testSet + * the specific test set that this will report on as it is + * executed + * @param reportManager + * the report manager to log testing events to + */ + JUnit4TestSetReporter(JUnit4TestSet testSet, ReporterManager reportManager) + { + this.testSet = testSet; + this.reportMgr = reportManager; + } + + /** + * Called right before any tests from a specific class are run. + * + * @see org.junit.runner.notification.RunListener#testRunStarted(org.junit.runner.Description) + */ + @Override + public void testRunStarted(Description description) throws Exception + { + String rawString = bundle.getString( "testSetStarting" ); + ReportEntry report = new ReportEntry(testSet, testSet.getName(), rawString); + + this.reportMgr.testSetStarting(report); + } + + /** + * Called right after all tests from a specific class are run. + * + * @see org.junit.runner.notification.RunListener#testRunFinished(org.junit.runner.Result) + */ + @Override + public void testRunFinished(Result result) throws Exception + { + String rawString = bundle.getString( "testSetCompletedNormally" ); + ReportEntry report = new ReportEntry(testSet, testSet.getName(), rawString); + + this.reportMgr.testSetCompleted(report); + this.reportMgr.reset(); + } + + /** + * Called when a specific test has been skipped (for whatever reason). + * + * @see org.junit.runner.notification.RunListener#testIgnored(org.junit.runner.Description) + */ + @Override + public void testIgnored(Description description) throws Exception + { + String rawString = bundle.getString( "testSkipped" ); + ReportEntry report = new ReportEntry(testSet, description.getDisplayName(), rawString); + + this.reportMgr.testSkipped(report); + } + + /** + * Called when a specific test has started. + * + * @see org.junit.runner.notification.RunListener#testStarted(org.junit.runner.Description) + */ + @Override + public void testStarted(Description description) throws Exception + { + String rawString = bundle.getString( "testStarting" ); + ReportEntry report = new ReportEntry(testSet, description.getDisplayName(), rawString); + + this.reportMgr.testStarting(report); + + this.failureFlag = false; + } + + /** + * Called when a specific test has failed. + * + * @see org.junit.runner.notification.RunListener#testFailure(org.junit.runner.notification.Failure) + */ + @Override + public void testFailure(Failure failure) throws Exception + { + String rawString = bundle.getString( "executeException" ); + ReportEntry report = new ReportEntry(testSet, failure.getTestHeader(), rawString, new JUnit4StackTraceWriter(failure)); + + if(failure.getException() instanceof AssertionError) + this.reportMgr.testFailed(report); + else + this.reportMgr.testError(report); + + failureFlag = true; + } + + /** + * Called after a specific test has finished. + * + * @see org.junit.runner.notification.RunListener#testFinished(org.junit.runner.Description) + */ + @Override + public void testFinished(Description description) throws Exception + { + if(failureFlag == false) + { + String rawString = bundle.getString( "testSuccessful" ); + ReportEntry report = new ReportEntry(testSet, description.getDisplayName(), rawString); + + this.reportMgr.testSucceeded(report); + } + } +}