package junit.awtui; | |
import java.awt.*; | |
import java.awt.event.*; | |
import java.awt.image.ImageProducer; | |
import java.util.Vector; | |
import junit.framework.*; | |
import junit.runner.*; | |
/** | |
* An AWT based user interface to run tests. | |
* Enter the name of a class which either provides a static | |
* suite method or is a subclass of TestCase. | |
* <pre> | |
* Synopsis: java junit.awtui.TestRunner [-noloading] [TestCase] | |
* </pre> | |
* TestRunner takes as an optional argument the name of the testcase class to be run. | |
*/ | |
public class TestRunner extends BaseTestRunner { | |
protected Frame fFrame; | |
protected Vector fExceptions; | |
protected Vector fFailedTests; | |
protected Thread fRunner; | |
protected TestResult fTestResult; | |
protected TextArea fTraceArea; | |
protected TextField fSuiteField; | |
protected Button fRun; | |
protected ProgressBar fProgressIndicator; | |
protected List fFailureList; | |
protected Logo fLogo; | |
protected Label fNumberOfErrors; | |
protected Label fNumberOfFailures; | |
protected Label fNumberOfRuns; | |
protected Button fQuitButton; | |
protected Button fRerunButton; | |
protected TextField fStatusLine; | |
protected Checkbox fUseLoadingRunner; | |
protected static final Font PLAIN_FONT= new Font("dialog", Font.PLAIN, 12); | |
private static final int GAP= 4; | |
public TestRunner() { | |
} | |
private void about() { | |
AboutDialog about= new AboutDialog(fFrame); | |
about.setModal(true); | |
about.setLocation(300, 300); | |
about.setVisible(true); | |
} | |
public void testStarted(String testName) { | |
showInfo("Running: "+testName); | |
} | |
public void testEnded(String testName) { | |
setLabelValue(fNumberOfRuns, fTestResult.runCount()); | |
synchronized(this) { | |
fProgressIndicator.step(fTestResult.wasSuccessful()); | |
} | |
} | |
public void testFailed(int status, Test test, Throwable t) { | |
switch (status) { | |
case TestRunListener.STATUS_ERROR: | |
fNumberOfErrors.setText(Integer.toString(fTestResult.errorCount())); | |
appendFailure("Error", test, t); | |
break; | |
case TestRunListener.STATUS_FAILURE: | |
fNumberOfFailures.setText(Integer.toString(fTestResult.failureCount())); | |
appendFailure("Failure", test, t); | |
break; | |
} | |
} | |
protected void addGrid(Panel p, Component co, int x, int y, int w, int fill, double wx, int anchor) { | |
GridBagConstraints c= new GridBagConstraints(); | |
c.gridx= x; c.gridy= y; | |
c.gridwidth= w; | |
c.anchor= anchor; | |
c.weightx= wx; | |
c.fill= fill; | |
if (fill == GridBagConstraints.BOTH || fill == GridBagConstraints.VERTICAL) | |
c.weighty= 1.0; | |
c.insets= new Insets(y == 0 ? GAP : 0, x == 0 ? GAP : 0, GAP, GAP); | |
p.add(co, c); | |
} | |
private void appendFailure(String kind, Test test, Throwable t) { | |
kind+= ": " + test; | |
String msg= t.getMessage(); | |
if (msg != null) { | |
kind+= ":" + truncate(msg); | |
} | |
fFailureList.add(kind); | |
fExceptions.addElement(t); | |
fFailedTests.addElement(test); | |
if (fFailureList.getItemCount() == 1) { | |
fFailureList.select(0); | |
failureSelected(); | |
} | |
} | |
/** | |
* Creates the JUnit menu. Clients override this | |
* method to add additional menu items. | |
*/ | |
protected Menu createJUnitMenu() { | |
Menu menu= new Menu("JUnit"); | |
MenuItem mi= new MenuItem("About..."); | |
mi.addActionListener( | |
new ActionListener() { | |
public void actionPerformed(ActionEvent event) { | |
about(); | |
} | |
} | |
); | |
menu.add(mi); | |
menu.addSeparator(); | |
mi= new MenuItem("Exit"); | |
mi.addActionListener( | |
new ActionListener() { | |
public void actionPerformed(ActionEvent event) { | |
System.exit(0); | |
} | |
} | |
); | |
menu.add(mi); | |
return menu; | |
} | |
protected void createMenus(MenuBar mb) { | |
mb.add(createJUnitMenu()); | |
} | |
protected TestResult createTestResult() { | |
return new TestResult(); | |
} | |
protected Frame createUI(String suiteName) { | |
Frame frame= new Frame("JUnit"); | |
Image icon= loadFrameIcon(); | |
if (icon != null) | |
frame.setIconImage(icon); | |
frame.setLayout(new BorderLayout(0, 0)); | |
frame.setBackground(SystemColor.control); | |
final Frame finalFrame= frame; | |
frame.addWindowListener( | |
new WindowAdapter() { | |
public void windowClosing(WindowEvent e) { | |
finalFrame.dispose(); | |
System.exit(0); | |
} | |
} | |
); | |
MenuBar mb = new MenuBar(); | |
createMenus(mb); | |
frame.setMenuBar(mb); | |
//---- first section | |
Label suiteLabel= new Label("Test class name:"); | |
fSuiteField= new TextField(suiteName != null ? suiteName : ""); | |
fSuiteField.selectAll(); | |
fSuiteField.requestFocus(); | |
fSuiteField.setFont(PLAIN_FONT); | |
fSuiteField.setColumns(40); | |
fSuiteField.addActionListener( | |
new ActionListener() { | |
public void actionPerformed(ActionEvent e) { | |
runSuite(); | |
} | |
} | |
); | |
fSuiteField.addTextListener( | |
new TextListener() { | |
public void textValueChanged(TextEvent e) { | |
fRun.setEnabled(fSuiteField.getText().length() > 0); | |
fStatusLine.setText(""); | |
} | |
} | |
); | |
fRun= new Button("Run"); | |
fRun.setEnabled(false); | |
fRun.addActionListener( | |
new ActionListener() { | |
public void actionPerformed(ActionEvent e) { | |
runSuite(); | |
} | |
} | |
); | |
boolean useLoader= useReloadingTestSuiteLoader(); | |
fUseLoadingRunner= new Checkbox("Reload classes every run", useLoader); | |
if (inVAJava()) | |
fUseLoadingRunner.setVisible(false); | |
//---- second section | |
fProgressIndicator= new ProgressBar(); | |
//---- third section | |
fNumberOfErrors= new Label("0000", Label.RIGHT); | |
fNumberOfErrors.setText("0"); | |
fNumberOfErrors.setFont(PLAIN_FONT); | |
fNumberOfFailures= new Label("0000", Label.RIGHT); | |
fNumberOfFailures.setText("0"); | |
fNumberOfFailures.setFont(PLAIN_FONT); | |
fNumberOfRuns= new Label("0000", Label.RIGHT); | |
fNumberOfRuns.setText("0"); | |
fNumberOfRuns.setFont(PLAIN_FONT); | |
Panel numbersPanel= createCounterPanel(); | |
//---- fourth section | |
Label failureLabel= new Label("Errors and Failures:"); | |
fFailureList= new List(5); | |
fFailureList.addItemListener( | |
new ItemListener() { | |
public void itemStateChanged(ItemEvent e) { | |
failureSelected(); | |
} | |
} | |
); | |
fRerunButton= new Button("Run"); | |
fRerunButton.setEnabled(false); | |
fRerunButton.addActionListener( | |
new ActionListener() { | |
public void actionPerformed(ActionEvent e) { | |
rerun(); | |
} | |
} | |
); | |
Panel failedPanel= new Panel(new GridLayout(0, 1, 0, 2)); | |
failedPanel.add(fRerunButton); | |
fTraceArea= new TextArea(); | |
fTraceArea.setRows(5); | |
fTraceArea.setColumns(60); | |
//---- fifth section | |
fStatusLine= new TextField(); | |
fStatusLine.setFont(PLAIN_FONT); | |
fStatusLine.setEditable(false); | |
fStatusLine.setForeground(Color.red); | |
fQuitButton= new Button("Exit"); | |
fQuitButton.addActionListener( | |
new ActionListener() { | |
public void actionPerformed(ActionEvent e) { | |
System.exit(0); | |
} | |
} | |
); | |
// --------- | |
fLogo= new Logo(); | |
//---- overall layout | |
Panel panel= new Panel(new GridBagLayout()); | |
addGrid(panel, suiteLabel, 0, 0, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST); | |
addGrid(panel, fSuiteField, 0, 1, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST); | |
addGrid(panel, fRun, 2, 1, 1, GridBagConstraints.HORIZONTAL, 0.0, GridBagConstraints.CENTER); | |
addGrid(panel, fUseLoadingRunner, 0, 2, 2, GridBagConstraints.NONE, 1.0, GridBagConstraints.WEST); | |
addGrid(panel, fProgressIndicator, 0, 3, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST); | |
addGrid(panel, fLogo, 2, 3, 1, GridBagConstraints.NONE, 0.0, GridBagConstraints.NORTH); | |
addGrid(panel, numbersPanel, 0, 4, 2, GridBagConstraints.NONE, 0.0, GridBagConstraints.WEST); | |
addGrid(panel, failureLabel, 0, 5, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST); | |
addGrid(panel, fFailureList, 0, 6, 2, GridBagConstraints.BOTH, 1.0, GridBagConstraints.WEST); | |
addGrid(panel, failedPanel, 2, 6, 1, GridBagConstraints.HORIZONTAL, 0.0, GridBagConstraints.CENTER); | |
addGrid(panel, fTraceArea, 0, 7, 2, GridBagConstraints.BOTH, 1.0, GridBagConstraints.WEST); | |
addGrid(panel, fStatusLine, 0, 8, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.CENTER); | |
addGrid(panel, fQuitButton, 2, 8, 1, GridBagConstraints.HORIZONTAL, 0.0, GridBagConstraints.CENTER); | |
frame.add(panel, BorderLayout.CENTER); | |
frame.pack(); | |
return frame; | |
} | |
protected Panel createCounterPanel() { | |
Panel numbersPanel= new Panel(new GridBagLayout()); | |
addToCounterPanel( | |
numbersPanel, | |
new Label("Runs:"), | |
0, 0, 1, 1, 0.0, 0.0, | |
GridBagConstraints.CENTER, GridBagConstraints.NONE, | |
new Insets(0, 0, 0, 0) | |
); | |
addToCounterPanel( | |
numbersPanel, | |
fNumberOfRuns, | |
1, 0, 1, 1, 0.33, 0.0, | |
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, | |
new Insets(0, 8, 0, 40) | |
); | |
addToCounterPanel( | |
numbersPanel, | |
new Label("Errors:"), | |
2, 0, 1, 1, 0.0, 0.0, | |
GridBagConstraints.CENTER, GridBagConstraints.NONE, | |
new Insets(0, 8, 0, 0) | |
); | |
addToCounterPanel( | |
numbersPanel, | |
fNumberOfErrors, | |
3, 0, 1, 1, 0.33, 0.0, | |
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, | |
new Insets(0, 8, 0, 40) | |
); | |
addToCounterPanel( | |
numbersPanel, | |
new Label("Failures:"), | |
4, 0, 1, 1, 0.0, 0.0, | |
GridBagConstraints.CENTER, GridBagConstraints.NONE, | |
new Insets(0, 8, 0, 0) | |
); | |
addToCounterPanel( | |
numbersPanel, | |
fNumberOfFailures, | |
5, 0, 1, 1, 0.33, 0.0, | |
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, | |
new Insets(0, 8, 0, 0) | |
); | |
return numbersPanel; | |
} | |
private void addToCounterPanel(Panel counter, Component comp, | |
int gridx, int gridy, int gridwidth, int gridheight, | |
double weightx, double weighty, | |
int anchor, int fill, | |
Insets insets) { | |
GridBagConstraints constraints= new GridBagConstraints(); | |
constraints.gridx= gridx; | |
constraints.gridy= gridy; | |
constraints.gridwidth= gridwidth; | |
constraints.gridheight= gridheight; | |
constraints.weightx= weightx; | |
constraints.weighty= weighty; | |
constraints.anchor= anchor; | |
constraints.fill= fill; | |
constraints.insets= insets; | |
counter.add(comp, constraints); | |
} | |
public void failureSelected() { | |
fRerunButton.setEnabled(isErrorSelected()); | |
showErrorTrace(); | |
} | |
private boolean isErrorSelected() { | |
return fFailureList.getSelectedIndex() != -1; | |
} | |
private Image loadFrameIcon() { | |
Toolkit toolkit= Toolkit.getDefaultToolkit(); | |
try { | |
java.net.URL url= BaseTestRunner.class.getResource("smalllogo.gif"); | |
return toolkit.createImage((ImageProducer) url.getContent()); | |
} catch (Exception ex) { | |
} | |
return null; | |
} | |
public Thread getRunner() { | |
return fRunner; | |
} | |
public static void main(String[] args) { | |
new TestRunner().start(args); | |
} | |
public static void run(Class test) { | |
String args[]= { test.getName() }; | |
main(args); | |
} | |
public void rerun() { | |
int index= fFailureList.getSelectedIndex(); | |
if (index == -1) | |
return; | |
Test test= (Test)fFailedTests.elementAt(index); | |
rerunTest(test); | |
} | |
private void rerunTest(Test test) { | |
if (!(test instanceof TestCase)) { | |
showInfo("Could not reload "+ test.toString()); | |
return; | |
} | |
Test reloadedTest= null; | |
TestCase rerunTest= (TestCase)test; | |
try { | |
Class reloadedTestClass= getLoader().reload(test.getClass()); | |
reloadedTest= TestSuite.createTest(reloadedTestClass, rerunTest.getName()); | |
} catch(Exception e) { | |
showInfo("Could not reload "+ test.toString()); | |
return; | |
} | |
TestResult result= new TestResult(); | |
reloadedTest.run(result); | |
String message= reloadedTest.toString(); | |
if(result.wasSuccessful()) | |
showInfo(message+" was successful"); | |
else if (result.errorCount() == 1) | |
showStatus(message+" had an error"); | |
else | |
showStatus(message+" had a failure"); | |
} | |
protected void reset() { | |
setLabelValue(fNumberOfErrors, 0); | |
setLabelValue(fNumberOfFailures, 0); | |
setLabelValue(fNumberOfRuns, 0); | |
fProgressIndicator.reset(); | |
fRerunButton.setEnabled(false); | |
fFailureList.removeAll(); | |
fExceptions= new Vector(10); | |
fFailedTests= new Vector(10); | |
fTraceArea.setText(""); | |
} | |
protected void runFailed(String message) { | |
showStatus(message); | |
fRun.setLabel("Run"); | |
fRunner= null; | |
} | |
synchronized public void runSuite() { | |
if (fRunner != null && fTestResult != null) { | |
fTestResult.stop(); | |
} else { | |
setLoading(shouldReload()); | |
fRun.setLabel("Stop"); | |
showInfo("Initializing..."); | |
reset(); | |
showInfo("Load Test Case..."); | |
final Test testSuite= getTest(fSuiteField.getText()); | |
if (testSuite != null) { | |
fRunner= new Thread() { | |
public void run() { | |
fTestResult= createTestResult(); | |
fTestResult.addListener(TestRunner.this); | |
fProgressIndicator.start(testSuite.countTestCases()); | |
showInfo("Running..."); | |
long startTime= System.currentTimeMillis(); | |
testSuite.run(fTestResult); | |
if (fTestResult.shouldStop()) { | |
showStatus("Stopped"); | |
} else { | |
long endTime= System.currentTimeMillis(); | |
long runTime= endTime-startTime; | |
showInfo("Finished: " + elapsedTimeAsString(runTime) + " seconds"); | |
} | |
fTestResult= null; | |
fRun.setLabel("Run"); | |
fRunner= null; | |
System.gc(); | |
} | |
}; | |
fRunner.start(); | |
} | |
} | |
} | |
private boolean shouldReload() { | |
return !inVAJava() && fUseLoadingRunner.getState(); | |
} | |
private void setLabelValue(Label label, int value) { | |
label.setText(Integer.toString(value)); | |
label.invalidate(); | |
label.getParent().validate(); | |
} | |
public void setSuiteName(String suite) { | |
fSuiteField.setText(suite); | |
} | |
private void showErrorTrace() { | |
int index= fFailureList.getSelectedIndex(); | |
if (index == -1) | |
return; | |
Throwable t= (Throwable) fExceptions.elementAt(index); | |
fTraceArea.setText(getFilteredTrace(t)); | |
} | |
private void showInfo(String message) { | |
fStatusLine.setFont(PLAIN_FONT); | |
fStatusLine.setForeground(Color.black); | |
fStatusLine.setText(message); | |
} | |
protected void clearStatus() { | |
showStatus(""); | |
} | |
private void showStatus(String status) { | |
fStatusLine.setFont(PLAIN_FONT); | |
fStatusLine.setForeground(Color.red); | |
fStatusLine.setText(status); | |
} | |
/** | |
* Starts the TestRunner | |
*/ | |
public void start(String[] args) { | |
String suiteName= processArguments(args); | |
fFrame= createUI(suiteName); | |
fFrame.setLocation(200, 200); | |
fFrame.setVisible(true); | |
if (suiteName != null) { | |
setSuiteName(suiteName); | |
runSuite(); | |
} | |
} | |
} |