/* * Copyright (C) NetStruxr, Inc. All rights reserved. * * This software is published under the terms of the NetStruxr * Public Software License version 0.5, a copy of which has been * included with this distribution in the LICENSE.NPL file. */ package er.testrunner; import java.util.Enumeration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import junit.framework.AssertionFailedError; import junit.framework.Test; import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WOResponse; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSBundle; import com.webobjects.foundation.NSComparator; import com.webobjects.foundation.NSMutableArray; import com.webobjects.foundation.NSMutableSet; import er.extensions.foundation.ERXPatcher; /** * component for interactively running tests. */ public class ERXWOTestInterface extends WOComponent implements ERXTestListener { /** * Do I need to update serialVersionUID? * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a> */ private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory.getLogger(ERXWOTestInterface.class); // bind to a WOTextField public String theTest; // bind to a WOString public String errorMessage; // bind to a WOCheckbox public Boolean showExceptions; public ERXTestRunner aTestRunner; public ERXTestResult testResult; public long runTime; public NSArray allTests; public ERXWOTestInterface(WOContext context) { super(context); showExceptions = Boolean.FALSE; theTest = ""; runTime = 0; errorMessage = ""; testResult = null; } protected NSArray bundles() { NSMutableArray bundles = new NSMutableArray(NSBundle.frameworkBundles()); bundles.addObject(NSBundle.mainBundle()); return bundles; } public NSArray allTests() { if(allTests == null) { String thisBundleName = NSBundle.bundleForClass(getClass()).name(); NSMutableSet theClassNames = new NSMutableSet(); Enumeration bundleEnum = bundles().objectEnumerator(); while (bundleEnum.hasMoreElements()) { NSBundle bundle = (NSBundle)bundleEnum.nextElement(); if (!bundle.name().equals(thisBundleName)) { Enumeration classNameEnum = bundle.bundleClassNames().objectEnumerator(); while (classNameEnum.hasMoreElements()) { String className = (String)classNameEnum.nextElement(); if (className != null && ( className.endsWith( "Test" ) || className.endsWith( "TestCase" ) || className.indexOf("tests.") == 0 || className.indexOf(".tests.") > 0) && !className.startsWith( "junit." ) && className.indexOf( "$" ) < 0) { try { Class c = ERXPatcher.classForName(className); //if(c != null && c.isAssignableFrom(TestCase.class)) theClassNames.addObject(munge(className)); } catch(Exception ex) { // ignored log.warn("Skipping test {}.", className, ex); } } } } } allTests = theClassNames.allObjects(); try { allTests = allTests.sortedArrayUsingComparator(NSComparator.AscendingStringComparator); } catch (Exception ex) { log.warn("Could not sort tests.", ex); // so we won't get sorted, oh well :) } } return allTests; } private String munge(String className) { String mungedName = className; int offset = className.lastIndexOf('.'); if(offset >= 0) { mungedName = className.substring(offset+1) + " - " + className.substring(0, offset); } return mungedName; } private String demunge(String className) { String demungedName = className; int offset = className.indexOf(" - "); if(offset >= 0) { demungedName = className.substring(offset+3) + "." + className.substring(0, offset); } return demungedName; } private void resetInterface() { runTime = 0; errorMessage = ""; aTestRunner = new ERXTestRunner(this); testResult = new ERXTestResult(); allTests = null; } // ACTION METHOD public WOComponent performTest() { resetInterface(); try { testResult = start(); } catch(Exception e) { errorMessage = e.getMessage(); } return context().page(); } // Starts a test run. Analyzes the command line arguments (test) and runs the given test suite. public ERXTestResult start() throws Exception { if (theTest.equals("")) { throw new Exception("You need to provide the name of a class to use as the TestCase for this run."); } try { Test suite = aTestRunner.getTest(demunge(theTest)); return doRun(suite); } catch(Exception e) { throw new Exception("Could not create and run test suite: "+e); } } public ERXTestResult doRun(Test suite) { testResult.addListener(this); long startTime = System.currentTimeMillis(); suite.run(testResult); long endTime = System.currentTimeMillis(); runTime = endTime-startTime; return testResult; } ////////////////////////////////////// // TestListener implementation ////////////////////////////////////// public synchronized void addError(Test test, Throwable t) { log.error ("[E] {} : {}", test, t.getMessage(), t); } public synchronized void addFailure(Test test, AssertionFailedError t) { log.error ("[F] {} : {}", test, t.getMessage()); } public synchronized void startTest(Test test) { log.info ("[START] {}" + test); } public void endTest(Test test) { log.info ("[END] {}" + test); } ////////////////////////////////////// // ERTestListener implementation ////////////////////////////////////// public void runFailed(String message) { log.debug ("--------------------------- runFailed() ---------------------------"); errorMessage = message; } public void clearStatus() { log.debug ("-------------------------- clearStatus() --------------------------"); errorMessage = ""; } @Override public void appendToResponse(WOResponse r, WOContext c) { if (session().objectForKey("ERXWOTestInterface.enabled") != null) { super.appendToResponse(r, c); } else { r.appendContentString("please use the ERXDirectAction testAction to login first!"); } } }