001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.impl.wsdl.panels.testsuite;
014:
015: import java.awt.BorderLayout;
016: import java.awt.Component;
017: import java.awt.Dimension;
018: import java.awt.event.ActionEvent;
019: import java.awt.event.ActionListener;
020: import java.util.ArrayList;
021: import java.util.List;
022:
023: import javax.swing.AbstractAction;
024: import javax.swing.Action;
025: import javax.swing.BorderFactory;
026: import javax.swing.Box;
027: import javax.swing.ButtonGroup;
028: import javax.swing.Icon;
029: import javax.swing.JComponent;
030: import javax.swing.JPanel;
031: import javax.swing.JProgressBar;
032: import javax.swing.JScrollPane;
033: import javax.swing.JTabbedPane;
034: import javax.swing.JTextArea;
035: import javax.swing.JToggleButton;
036: import javax.swing.text.Document;
037:
038: import com.eviware.soapui.SoapUI;
039: import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
040: import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
041: import com.eviware.soapui.impl.wsdl.support.HelpUrls;
042: import com.eviware.soapui.model.ModelItem;
043: import com.eviware.soapui.model.support.PropertiesMap;
044: import com.eviware.soapui.model.support.TestRunListenerAdapter;
045: import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
046: import com.eviware.soapui.model.testsuite.TestCase;
047: import com.eviware.soapui.model.testsuite.TestRunContext;
048: import com.eviware.soapui.model.testsuite.TestRunner;
049: import com.eviware.soapui.model.testsuite.TestSuite.TestSuiteRunType;
050: import com.eviware.soapui.support.DocumentListenerAdapter;
051: import com.eviware.soapui.support.UISupport;
052: import com.eviware.soapui.support.components.JUndoableTextArea;
053: import com.eviware.soapui.support.components.JXToolBar;
054: import com.eviware.soapui.ui.desktop.DesktopPanel;
055:
056: /**
057: * DesktopPanel for WsdlTestSuite
058: *
059: * @author Ole.Matzura
060: */
061:
062: @SuppressWarnings("serial")
063: public class WsdlTestSuiteDesktopPanel extends JPanel implements
064: DesktopPanel {
065: private final WsdlTestSuite testSuite;
066: private JProgressBar progressBar;
067: private JTestCaseList testCaseList;
068: private RunAction runAction = new RunAction();
069: private CancelAction cancelAction = new CancelAction();
070: private TestSuiteRunner testSuiteRunner = new TestSuiteRunner();
071: private JToggleButton sequentialButton;
072: private JToggleButton parallellButton;
073: private final InternalTestSuiteListener testSuiteListener = new InternalTestSuiteListener();
074: private JTextArea descriptionArea;
075:
076: public WsdlTestSuiteDesktopPanel(WsdlTestSuite testSuite) {
077: super (new BorderLayout());
078: this .testSuite = testSuite;
079:
080: buildUI();
081: testSuite.addTestSuiteListener(testSuiteListener);
082: }
083:
084: private void buildUI() {
085: add(buildToolbar(), BorderLayout.NORTH);
086: add(buildContent(), BorderLayout.CENTER);
087:
088: setPreferredSize(new Dimension(300, 400));
089: }
090:
091: protected JTestCaseList getTestCaseList() {
092: return testCaseList;
093: }
094:
095: @Override
096: public void addNotify() {
097: super .addNotify();
098: testSuite.addTestSuiteListener(testSuiteListener);
099: }
100:
101: @Override
102: public void removeNotify() {
103: super .removeNotify();
104: testSuite.removeTestSuiteListener(testSuiteListener);
105: }
106:
107: private JComponent buildToolbar() {
108: cancelAction.setEnabled(false);
109: runAction.setEnabled(testSuite.getTestCaseCount() > 0);
110:
111: JXToolBar toolbar = UISupport.createToolbar();
112:
113: addToolbarActions(toolbar);
114: toolbar.add(Box.createHorizontalGlue());
115: toolbar.add(UISupport
116: .createToolbarButton(new ShowOnlineHelpAction(
117: HelpUrls.TESTSUITEEDITOR_HELP_URL)));
118:
119: progressBar = new JProgressBar(0, testSuite.getTestCaseCount());
120: JPanel progressPanel = UISupport.createProgressBarPanel(
121: progressBar, 10, false);
122:
123: JPanel panel = new JPanel(new BorderLayout());
124:
125: panel.add(toolbar, BorderLayout.PAGE_START);
126: panel.add(progressPanel, BorderLayout.CENTER);
127:
128: return panel;
129: }
130:
131: protected void addToolbarActions(JXToolBar toolbar) {
132: toolbar.add(UISupport.createToolbarButton(runAction));
133: toolbar.addRelatedGap();
134: toolbar.add(UISupport.createToolbarButton(cancelAction));
135:
136: ButtonGroup buttonGroup = new ButtonGroup();
137:
138: sequentialButton = new JToggleButton(UISupport
139: .createImageIcon("/sequential.gif"), true);
140: sequentialButton
141: .setToolTipText("The selected TestCases are run in sequence");
142: sequentialButton.setPreferredSize(UISupport
143: .getPreferredButtonSize());
144: sequentialButton
145: .setSelected(testSuite.getRunType() == TestSuiteRunType.SEQUENTIAL);
146: sequentialButton.addActionListener(new ActionListener() {
147:
148: public void actionPerformed(ActionEvent e) {
149: testSuite.setRunType(TestSuiteRunType.SEQUENTIAL);
150: }
151: });
152:
153: buttonGroup.add(sequentialButton);
154:
155: parallellButton = new JToggleButton(UISupport
156: .createImageIcon("/parallell.gif"));
157: parallellButton
158: .setToolTipText("The selected TestCases are run in parallel");
159: parallellButton.setPreferredSize(UISupport
160: .getPreferredButtonSize());
161: parallellButton
162: .setSelected(testSuite.getRunType() == TestSuiteRunType.PARALLEL);
163: parallellButton.addActionListener(new ActionListener() {
164:
165: public void actionPerformed(ActionEvent e) {
166: testSuite.setRunType(TestSuiteRunType.PARALLEL);
167: }
168: });
169:
170: buttonGroup.add(parallellButton);
171:
172: toolbar.addUnrelatedGap();
173: toolbar.add(sequentialButton);
174: toolbar.addRelatedGap();
175: toolbar.add(parallellButton);
176:
177: }
178:
179: private JComponent buildContent() {
180: JTabbedPane tabs = new JTabbedPane(JTabbedPane.TOP);
181:
182: testCaseList = buildTestCaseList(testSuite);
183:
184: tabs.addTab("TestCases", new JScrollPane(testCaseList));
185: tabs.addTab("Description", buildDescriptionPanel());
186:
187: return UISupport.createTabPanel(tabs, true);
188: }
189:
190: private Component buildDescriptionPanel() {
191: JPanel panel = new JPanel(new BorderLayout());
192: descriptionArea = new JUndoableTextArea(testSuite
193: .getDescription());
194: descriptionArea.getDocument().addDocumentListener(
195: new DocumentListenerAdapter() {
196: public void update(Document document) {
197: testSuite.setDescription(descriptionArea
198: .getText());
199: }
200: });
201:
202: panel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
203: panel
204: .add(new JScrollPane(descriptionArea),
205: BorderLayout.CENTER);
206:
207: return panel;
208: }
209:
210: protected JTestCaseList buildTestCaseList(WsdlTestSuite testSuite) {
211: return new JTestCaseList(testSuite);
212: }
213:
214: public Icon getIcon() {
215: return getModelItem().getIcon();
216: }
217:
218: public WsdlTestSuite getModelItem() {
219: return testSuite;
220: }
221:
222: public boolean onClose(boolean canCancel) {
223: return true;
224: }
225:
226: public JComponent getComponent() {
227: return this ;
228: }
229:
230: public boolean dependsOn(ModelItem modelItem) {
231: return modelItem == testSuite
232: || modelItem == testSuite.getProject();
233: }
234:
235: public String getTitle() {
236: return getModelItem().getName();
237: }
238:
239: public String getDescription() {
240: return "TestSuite: [" + getModelItem().getName() + "]";
241: }
242:
243: protected void runTestSuite() {
244: new Thread(testSuiteRunner, testSuite.getName()
245: + " TestSuiteRunner").start();
246: }
247:
248: protected void beforeRun() {
249: runAction.setEnabled(false);
250: cancelAction.setEnabled(true);
251: testCaseList.setEnabled(false);
252: }
253:
254: protected void afterRun() {
255: runAction.setEnabled(true);
256: cancelAction.setEnabled(false);
257: testCaseList.setEnabled(true);
258:
259: progressBar.setString("Finished");
260: }
261:
262: private final class InternalTestSuiteListener extends
263: TestSuiteListenerAdapter {
264: public void testCaseAdded(TestCase testCase) {
265: runAction.setEnabled(testSuite.getTestCaseCount() > 0);
266: }
267:
268: public void testCaseRemoved(TestCase testCase) {
269: runAction.setEnabled(testSuite.getTestCaseCount() > 0);
270: }
271: }
272:
273: private class RunAction extends AbstractAction {
274: public RunAction() {
275: putValue(Action.SMALL_ICON, UISupport
276: .createImageIcon("/run_testcase.gif"));
277: putValue(Action.SHORT_DESCRIPTION,
278: "Runs the selected TestCases");
279: }
280:
281: public void actionPerformed(ActionEvent e) {
282: runTestSuite();
283: }
284: }
285:
286: private class CancelAction extends AbstractAction {
287: public CancelAction() {
288: putValue(Action.SMALL_ICON, UISupport
289: .createImageIcon("/stop_testcase.gif"));
290: putValue(Action.SHORT_DESCRIPTION,
291: "Cancels ongoing TestCase runs");
292: }
293:
294: public void actionPerformed(ActionEvent e) {
295: testSuiteRunner.cancel();
296: }
297: }
298:
299: /**
300: * Runs the selected testsuites..
301: *
302: * @author Ole.Matzura
303: */
304:
305: public class TestSuiteRunner implements Runnable {
306: private boolean canceled;
307: private List<TestRunner> runners = new ArrayList<TestRunner>();
308: private InternalTestRunListener internalTestRunListener = new InternalTestRunListener();
309:
310: public void cancel() {
311: canceled = true;
312:
313: for (TestRunner runner : runners) {
314: runner.cancel("Canceled from TestSuite");
315: }
316: }
317:
318: public void run() {
319: canceled = false;
320: beforeRun();
321:
322: int[] indices = testCaseList.getSelectedIndices();
323: if (indices.length == 0) {
324: indices = new int[testSuite.getTestCaseCount()];
325: for (int c = 0; c < indices.length; c++)
326: indices[c] = c;
327: }
328:
329: progressBar.setValue(0);
330: progressBar.setString("");
331: progressBar.setMaximum(indices.length);
332:
333: TestSuiteRunType runType = testSuite.getRunType();
334:
335: for (int c = 0; c < indices.length; c++) {
336: TestCase testCase = (TestCase) testSuite
337: .getTestCaseAt(indices[c]);
338: if (SoapUI.getTestMonitor()
339: .hasRunningLoadTest(testCase)) {
340: progressBar.setString("Skipping "
341: + testCase.getName());
342: progressBar.setValue(c + 1);
343: continue;
344: }
345:
346: if (runType == TestSuiteRunType.PARALLEL) {
347: testCase
348: .addTestRunListener(internalTestRunListener);
349: progressBar.setString("Starting "
350: + testCase.getName());
351: } else {
352: progressBar.setString("Running "
353: + testCase.getName());
354: }
355:
356: TestRunner runner = testCase.run(
357: PropertiesMap.EMPTY_MAP, true);
358: runners.add(runner);
359:
360: if (runType == TestSuiteRunType.SEQUENTIAL) {
361: runner.waitUntilFinished();
362: progressBar.setValue(c + 1);
363: runners.remove(runner);
364: }
365:
366: if (canceled)
367: break;
368: }
369:
370: if (runners.isEmpty())
371: afterRun();
372: }
373:
374: /**
375: * Waits for running tests to finish when running in parallel
376: */
377:
378: private class InternalTestRunListener extends
379: TestRunListenerAdapter {
380: public void afterRun(TestRunner testRunner,
381: TestRunContext runContext) {
382: runners.remove(testRunner);
383: testRunner.getTestCase().removeTestRunListener(this );
384:
385: progressBar.setValue(progressBar.getValue() + 1);
386:
387: if (runners.isEmpty())
388: WsdlTestSuiteDesktopPanel.this.afterRun();
389: }
390: }
391: }
392: }
|