View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.panels.testsuite;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.Dimension;
18  import java.awt.event.ActionEvent;
19  import java.awt.event.ActionListener;
20  import java.util.ArrayList;
21  import java.util.List;
22  
23  import javax.swing.AbstractAction;
24  import javax.swing.Action;
25  import javax.swing.BorderFactory;
26  import javax.swing.Box;
27  import javax.swing.ButtonGroup;
28  import javax.swing.Icon;
29  import javax.swing.JComponent;
30  import javax.swing.JPanel;
31  import javax.swing.JProgressBar;
32  import javax.swing.JScrollPane;
33  import javax.swing.JTabbedPane;
34  import javax.swing.JTextArea;
35  import javax.swing.JToggleButton;
36  import javax.swing.text.Document;
37  
38  import com.eviware.soapui.SoapUI;
39  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
40  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
41  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
42  import com.eviware.soapui.model.ModelItem;
43  import com.eviware.soapui.model.support.PropertiesMap;
44  import com.eviware.soapui.model.support.TestRunListenerAdapter;
45  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
46  import com.eviware.soapui.model.testsuite.TestCase;
47  import com.eviware.soapui.model.testsuite.TestRunContext;
48  import com.eviware.soapui.model.testsuite.TestRunner;
49  import com.eviware.soapui.model.testsuite.TestSuite.TestSuiteRunType;
50  import com.eviware.soapui.support.DocumentListenerAdapter;
51  import com.eviware.soapui.support.UISupport;
52  import com.eviware.soapui.support.components.JUndoableTextArea;
53  import com.eviware.soapui.support.components.JXToolBar;
54  import com.eviware.soapui.ui.desktop.DesktopPanel;
55  
56  /***
57   * DesktopPanel for WsdlTestSuite
58   * 
59   * @author Ole.Matzura
60   */
61  
62  @SuppressWarnings("serial")
63  public class WsdlTestSuiteDesktopPanel extends JPanel implements DesktopPanel
64  {
65  	private final WsdlTestSuite testSuite;
66  	private JProgressBar progressBar;
67  	private JTestCaseList testCaseList;
68  	private RunAction runAction = new RunAction();
69  	private CancelAction cancelAction = new CancelAction();
70  	private TestSuiteRunner testSuiteRunner = new TestSuiteRunner();
71  	private JToggleButton sequentialButton;
72  	private JToggleButton parallellButton;
73  	private final InternalTestSuiteListener testSuiteListener = new InternalTestSuiteListener();
74  	private JTextArea descriptionArea;
75  
76  	public WsdlTestSuiteDesktopPanel(WsdlTestSuite testSuite)
77  	{
78  		super( new BorderLayout() );
79  		this.testSuite = testSuite;
80  		
81  		buildUI();
82  		testSuite.addTestSuiteListener( testSuiteListener );
83  	}
84  
85  	private void buildUI()
86  	{
87  		add( buildToolbar(), BorderLayout.NORTH );
88  		add( buildContent(), BorderLayout.CENTER );
89  		
90  		setPreferredSize( new Dimension( 300, 400 ));
91  	}
92  	
93  	protected JTestCaseList getTestCaseList()
94  	{
95  		return testCaseList;
96  	}
97  
98  	@Override
99  	public void addNotify()
100 	{
101 		super.addNotify();
102 		testSuite.addTestSuiteListener( testSuiteListener );
103 	}
104 
105 	@Override
106 	public void removeNotify()
107 	{
108 		super.removeNotify();
109 		testSuite.removeTestSuiteListener( testSuiteListener );
110 	}
111 
112 	private JComponent buildToolbar()
113 	{
114 		cancelAction.setEnabled( false );
115 		runAction.setEnabled( testSuite.getTestCaseCount() > 0 );
116 		
117 		JXToolBar toolbar = UISupport.createToolbar();
118 		
119 		addToolbarActions( toolbar );
120 		toolbar.add( Box.createHorizontalGlue() );
121 		toolbar.add(  UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.TESTSUITEEDITOR_HELP_URL )));
122 		
123 		progressBar = new JProgressBar( 0, testSuite.getTestCaseCount() );
124 		JPanel progressPanel = UISupport.createProgressBarPanel(progressBar, 10, false );
125 		
126 		JPanel panel = new JPanel( new BorderLayout() );
127 	   
128       panel.add( toolbar, BorderLayout.PAGE_START );
129       panel.add( progressPanel, BorderLayout.CENTER );
130       
131 		return panel;
132 	}
133 
134 	protected void addToolbarActions( JXToolBar toolbar )
135 	{
136 		toolbar.add( UISupport.createToolbarButton( runAction ));
137 		toolbar.addRelatedGap();
138 		toolbar.add( UISupport.createToolbarButton( cancelAction ));
139 		
140 		ButtonGroup buttonGroup = new ButtonGroup();
141 		
142 		sequentialButton = new JToggleButton( UISupport.createImageIcon( "/sequential.gif" ), true );
143 		sequentialButton.setToolTipText( "The selected TestCases are run in sequence" );
144 		sequentialButton.setPreferredSize( UISupport.getPreferredButtonSize());
145 		sequentialButton.setSelected( testSuite.getRunType() == TestSuiteRunType.SEQUENTIAL );
146 		sequentialButton.addActionListener( new ActionListener() {
147 
148 			public void actionPerformed(ActionEvent e)
149 			{
150 				testSuite.setRunType( TestSuiteRunType.SEQUENTIAL );
151 			}} );
152 		
153 		buttonGroup.add( sequentialButton );
154 		
155 		parallellButton = new JToggleButton( UISupport.createImageIcon( "/parallell.gif" ));
156 		parallellButton.setToolTipText( "The selected TestCases are run in parallel" );
157 		parallellButton.setPreferredSize( UISupport.getPreferredButtonSize());
158 		parallellButton.setSelected( testSuite.getRunType() == TestSuiteRunType.PARALLEL );
159 		parallellButton.addActionListener( new ActionListener() {
160 
161 			public void actionPerformed(ActionEvent e)
162 			{
163 				testSuite.setRunType( TestSuiteRunType.PARALLEL );
164 			}} );
165 		
166 		buttonGroup.add( parallellButton );
167 		
168 		toolbar.addUnrelatedGap();
169 		toolbar.add( sequentialButton );
170 		toolbar.addRelatedGap();
171 		toolbar.add( parallellButton );
172 		
173 	}
174 	
175 	private JComponent buildContent()
176 	{
177 		JTabbedPane tabs = new JTabbedPane( JTabbedPane.TOP );
178 		
179 		testCaseList = buildTestCaseList( testSuite );
180 		
181       tabs.addTab( "TestCases",  new JScrollPane( testCaseList ));
182       tabs.addTab( "Description", buildDescriptionPanel() );
183       
184       return UISupport.createTabPanel( tabs, true );
185 	}
186 
187 	private Component buildDescriptionPanel()
188 	{
189    	JPanel panel = new JPanel( new BorderLayout() );
190    	descriptionArea = new JUndoableTextArea( testSuite.getDescription() );
191    	descriptionArea.getDocument().addDocumentListener( new DocumentListenerAdapter() 
192    	{
193 			public void update(Document document)
194 			{
195 				testSuite.setDescription( descriptionArea.getText() );
196 			}} );
197    	
198    	panel.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2));
199    	panel.add( new JScrollPane( descriptionArea ), BorderLayout.CENTER );
200    	
201 		return panel;
202 	}
203 	
204 	protected JTestCaseList buildTestCaseList(WsdlTestSuite testSuite)
205 	{
206 		return new JTestCaseList( testSuite );
207 	}
208 
209 	public Icon getIcon()
210 	{
211 		return getModelItem().getIcon();
212 	}
213 
214 	public WsdlTestSuite getModelItem()
215 	{
216 		return testSuite;
217 	}
218 
219 	public boolean onClose( boolean canCancel )
220 	{
221 		return true;
222 	}
223 
224 	public JComponent getComponent()
225 	{
226 		return this;
227 	}
228 
229 	public boolean dependsOn(ModelItem modelItem)
230 	{
231 		return modelItem == testSuite || modelItem == testSuite.getProject();
232 	}
233 
234 	public String getTitle()
235 	{
236 		return getModelItem().getName();
237 	}
238 	
239 	public String getDescription()
240 	{
241 		return "TestSuite: [" + getModelItem().getName() + "]";
242 	}
243 	
244 	protected void runTestSuite()
245 	{
246 		new Thread( testSuiteRunner, testSuite.getName() + " TestSuiteRunner" ).start();
247 	}
248 
249 	protected void beforeRun()
250 	{
251 		runAction.setEnabled( false );
252 		cancelAction.setEnabled( true );
253 		testCaseList.setEnabled( false );
254 	}
255 
256 	protected void afterRun()
257 	{
258 		runAction.setEnabled( true );
259 		cancelAction.setEnabled( false );
260 		testCaseList.setEnabled( true );
261 		
262 		progressBar.setString( "Finished" );
263 	}
264 	
265 	private final class InternalTestSuiteListener extends TestSuiteListenerAdapter
266 	{
267 		public void testCaseAdded(TestCase testCase)
268 		{
269 			runAction.setEnabled( testSuite.getTestCaseCount() > 0 );
270 		}
271 
272 		public void testCaseRemoved(TestCase testCase)
273 		{
274 			runAction.setEnabled( testSuite.getTestCaseCount() > 0 );
275 		}
276 	}
277 
278 	private class RunAction extends AbstractAction
279 	{
280 		public RunAction()
281 		{
282 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_testcase.gif" ));
283 			putValue( Action.SHORT_DESCRIPTION, "Runs the selected TestCases" );
284 		}
285 		
286 		public void actionPerformed(ActionEvent e)
287 		{
288 			runTestSuite();
289 		}
290 	}
291 	
292 	private class CancelAction extends AbstractAction
293 	{
294 		public CancelAction()
295 		{
296 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stop_testcase.gif" ));
297 			putValue( Action.SHORT_DESCRIPTION, "Cancels ongoing TestCase runs" );
298 		}
299 		
300 		public void actionPerformed(ActionEvent e)
301 		{
302 		   testSuiteRunner.cancel();
303 		}
304 	}
305 	
306 	/***
307 	 * Runs the selected testsuites..
308 	 * 
309 	 * @author Ole.Matzura
310 	 */
311 	
312 	public class TestSuiteRunner implements Runnable
313 	{
314 		private boolean canceled;
315 		private List<TestRunner> runners = new ArrayList<TestRunner>();
316 		private InternalTestRunListener internalTestRunListener = new InternalTestRunListener();
317 		
318 		public void cancel()
319 		{
320 			canceled = true;
321 			
322 			for( TestRunner runner : runners )
323 			{
324 				runner.cancel( "Canceled from TestSuite" );
325 			}
326 		}
327 		
328 		public void run()
329 		{
330 			canceled = false;
331 			beforeRun();
332 			
333 			int[] indices = testCaseList.getSelectedIndices();
334 			if( indices.length == 0 )
335 			{
336 				indices = new int[testSuite.getTestCaseCount()];
337 				for( int c = 0; c < indices.length; c++ )
338 					indices[c] = c;
339 			}
340 			
341 			progressBar.setValue( 0 );
342 			progressBar.setString( "" ); 
343 			progressBar.setMaximum( indices.length );
344 			
345 			TestSuiteRunType runType = testSuite.getRunType();
346 			
347 			for( int c = 0; c < indices.length; c++ )
348 			{
349 				TestCase testCase = (TestCase) testSuite.getTestCaseAt( indices[c] );
350 				if( SoapUI.getTestMonitor().hasRunningLoadTest( testCase ))
351 				{
352 					progressBar.setString( "Skipping " + testCase.getName() );
353 					progressBar.setValue( c+1 );
354 					continue;
355 				}
356 				
357 				if( runType == TestSuiteRunType.PARALLEL )
358 				{
359 					testCase.addTestRunListener( internalTestRunListener );
360 					progressBar.setString( "Starting " + testCase.getName() );
361 				}
362 				else
363 				{
364 					progressBar.setString( "Running " + testCase.getName() );
365 				}
366 				
367 				TestRunner runner = testCase.run( PropertiesMap.EMPTY_MAP, true );
368 				runners.add( runner );
369 				
370 				if( runType == TestSuiteRunType.SEQUENTIAL )
371 				{
372 					runner.waitUntilFinished();
373 					progressBar.setValue( c+1 );
374 					runners.remove( runner );
375 				}
376 				
377 				if( canceled )
378 					break;
379 			}
380 
381 			if( runners.isEmpty() )
382 				afterRun();
383 		}
384 		
385 		/***
386 		 * Waits for running tests to finish when running in parallel
387 		 */
388 		
389 		private class InternalTestRunListener extends TestRunListenerAdapter
390 		{
391 			public void afterRun(TestRunner testRunner, TestRunContext runContext)
392 			{
393 				runners.remove( testRunner );
394 				testRunner.getTestCase().removeTestRunListener( this );
395 				
396 				progressBar.setValue( progressBar.getValue()+1 );
397 				
398 				if( runners.isEmpty() )
399 					WsdlTestSuiteDesktopPanel.this.afterRun();
400 			}
401 		}
402 	}
403 }