View Javadoc

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