View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 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 com.eviware.soapui.SoapUI;
16  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
17  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
18  import com.eviware.soapui.impl.wsdl.actions.testsuite.AddNewTestCaseAction;
19  import com.eviware.soapui.impl.wsdl.panels.testcase.TestRunLog;
20  import com.eviware.soapui.impl.wsdl.panels.testcase.TestRunLog.TestRunLogTestRunListener;
21  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AbstractGroovyEditorModel;
22  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.PropertyHolderTable;
23  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
24  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestScenario;
25  import com.eviware.soapui.model.ModelItem;
26  import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
27  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
28  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
29  import com.eviware.soapui.model.testsuite.TestCase;
30  import com.eviware.soapui.model.testsuite.TestRunner;
31  import com.eviware.soapui.model.testsuite.TestSuite.TestSuiteRunType;
32  import com.eviware.soapui.settings.UISettings;
33  import com.eviware.soapui.support.DocumentListenerAdapter;
34  import com.eviware.soapui.support.StringUtils;
35  import com.eviware.soapui.support.UISupport;
36  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
37  import com.eviware.soapui.support.components.*;
38  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
39  
40  import javax.swing.*;
41  import javax.swing.text.Document;
42  import java.awt.*;
43  import java.awt.event.ActionEvent;
44  import java.awt.event.ActionListener;
45  
46  /***
47   * DesktopPanel for WsdlTestSuite
48   * 
49   * @author Ole.Matzura
50   */
51  
52  @SuppressWarnings("serial")
53  public class WsdlTestSuiteDesktopPanel extends ModelItemDesktopPanel<WsdlTestSuite>
54  {
55  	private JProgressBar progressBar;
56  	private JTestSuiteTestCaseList testCaseList;
57  	private RunAction runAction = new RunAction();
58  	private CancelAction cancelAction = new CancelAction();
59  	private TestSuiteRunner testSuiteRunner = new TestSuiteRunner();
60  	private JToggleButton sequentialButton;
61  	private JToggleButton parallellButton;
62  	private final InternalTestSuiteListener testSuiteListener = new InternalTestSuiteListener();
63  	private JTextArea descriptionArea;
64  	private boolean failedTests;
65  	private PropertyHolderTable propertiesTable;
66  	private TestRunLog testRunLog;
67  	private GroovyEditorComponent tearDownGroovyEditor;
68  	private GroovyEditorComponent setupGroovyEditor;
69     private JInspectorPanel testCaseListInspectorPanel;
70  
71     public WsdlTestSuiteDesktopPanel(WsdlTestSuite testSuite)
72  	{
73  		super( testSuite );
74  
75  		buildUI();
76  		testSuite.addTestSuiteListener( testSuiteListener );
77  	}
78  
79  	private void buildUI()
80  	{
81  		add( buildToolbar(), BorderLayout.NORTH );
82  		add( buildContent(), BorderLayout.CENTER );
83  		
84  		setPreferredSize( new Dimension( 500, 500 ));
85  	}
86  
87  	private JComponent buildContent()
88  	{
89  		JInspectorPanel inspectorPanel = JInspectorPanelFactory.build( buildTabs() );
90  		inspectorPanel.addInspector( new JComponentInspector( buildRunLog(), "TestSuite Log", 
91  					"Log of executed TestCases and TestSteps", true ));
92  
93        if( StringUtils.hasContent( getModelItem().getDescription() ) && getModelItem().getSettings().getBoolean( UISettings.SHOW_DESCRIPTIONS ))
94        {
95           testCaseListInspectorPanel.setCurrentInspector( "Description" );
96        }
97  
98  		return inspectorPanel.getComponent();
99  	}
100 	
101 	private JComponent buildRunLog()
102 	{
103 		testRunLog = new TestRunLog( getModelItem().getSettings() );
104 		return testRunLog;
105 	}
106 
107 	protected JTestSuiteTestCaseList getTestCaseList()
108 	{
109 		return testCaseList;
110 	}
111 
112 	@Override
113 	public void addNotify()
114 	{
115 		super.addNotify();
116 		getModelItem().addTestSuiteListener( testSuiteListener );
117 	}
118 
119 	@Override
120 	public void removeNotify()
121 	{
122 		super.removeNotify();
123 		getModelItem().removeTestSuiteListener( testSuiteListener );
124 	}
125 
126 	private JComponent buildToolbar()
127 	{
128 		cancelAction.setEnabled( false );
129 		runAction.setEnabled( getModelItem().getTestCaseCount() > 0 );
130 		
131 		JXToolBar toolbar = UISupport.createToolbar();
132 		
133 		addToolbarActions( toolbar );
134 		toolbar.addGlue();
135 		toolbar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.TESTSUITE_HELP_URL )));
136 		
137 		progressBar = new JProgressBar( 0, getModelItem().getTestCaseCount() );
138 		JPanel progressPanel = UISupport.createProgressBarPanel(progressBar, 10, false );
139 		
140 		JPanel panel = new JPanel( new BorderLayout() );
141 	   
142       panel.add( toolbar, BorderLayout.PAGE_START );
143       panel.add( progressPanel, BorderLayout.CENTER );
144       
145 		return panel;
146 	}
147 
148 	protected void addToolbarActions( JXToolBar toolbar )
149 	{
150 		toolbar.add( UISupport.createToolbarButton( runAction ));
151 		toolbar.add( UISupport.createToolbarButton( cancelAction ));
152 		
153 		toolbar.addRelatedGap();
154 		
155 		ButtonGroup buttonGroup = new ButtonGroup();
156 		
157 		sequentialButton = new JToggleButton( UISupport.createImageIcon( "/sequential.gif" ), true );
158 		sequentialButton.setToolTipText( "The selected TestCases are run in sequence" );
159 		sequentialButton.setPreferredSize( UISupport.getPreferredButtonSize());
160 		sequentialButton.setSelected( getModelItem().getRunType() == TestSuiteRunType.SEQUENTIAL );
161 		sequentialButton.addActionListener( new ActionListener() {
162 
163 			public void actionPerformed(ActionEvent e)
164 			{
165 				getModelItem().setRunType( TestSuiteRunType.SEQUENTIAL );
166 			}} );
167 		
168 		buttonGroup.add( sequentialButton );
169 		
170 		parallellButton = new JToggleButton( UISupport.createImageIcon( "/parallell.gif" ));
171 		parallellButton.setToolTipText( "The selected TestCases are run in parallel" );
172 		parallellButton.setPreferredSize( UISupport.getPreferredButtonSize());
173 		parallellButton.setSelected( getModelItem().getRunType() == TestSuiteRunType.PARALLEL );
174 		parallellButton.addActionListener( new ActionListener() {
175 
176 			public void actionPerformed(ActionEvent e)
177 			{
178 				getModelItem().setRunType( TestSuiteRunType.PARALLEL );
179 			}} );
180 		
181 		buttonGroup.add( parallellButton );
182 		
183 		toolbar.addUnrelatedGap();
184 		toolbar.add( sequentialButton );
185 		toolbar.addRelatedGap();
186 		toolbar.add( parallellButton );
187 	}
188 	
189 	private JComponent buildTabs()
190 	{
191 		JTabbedPane tabs = new JTabbedPane( JTabbedPane.TOP );
192       testCaseListInspectorPanel = JInspectorPanelFactory.build( buildTestCaseList( getModelItem() ) );
193 		
194 		tabs.addTab( "TestCases", testCaseListInspectorPanel.getComponent() );
195 		
196       addTabs( tabs, testCaseListInspectorPanel );
197       tabs.setTabLayoutPolicy( JTabbedPane.SCROLL_TAB_LAYOUT );
198       
199       return UISupport.createTabPanel( tabs, true );
200 	}
201 
202 	protected void addTabs( JTabbedPane tabs, JInspectorPanel inspectorPanel )
203 	{
204 		inspectorPanel.addInspector( new JFocusableComponentInspector<JPanel>( buildDescriptionPanel(), 
205 					descriptionArea, "Description", "Description for this TestSuite", true ));
206 		
207 		inspectorPanel.addInspector( new JComponentInspector( buildPropertiesPanel(), "Properties", "TestSuite level properties", true ) );
208 		inspectorPanel.addInspector( new GroovyEditorInspector( buildSetupScriptPanel(), "Setup Script", "Script to run before running TestSuite") );
209 		inspectorPanel.addInspector( new GroovyEditorInspector( buildTearDownScriptPanel(), "TearDown Script", "Script to run after running TestSuite" ) );
210 	}
211 	
212 	protected GroovyEditorComponent buildTearDownScriptPanel()
213 	{
214 		tearDownGroovyEditor = new GroovyEditorComponent( new TearDownScriptGroovyEditorModel(), null );
215 		return tearDownGroovyEditor;
216 	}
217 
218 	protected GroovyEditorComponent buildSetupScriptPanel()
219 	{
220 		setupGroovyEditor = new GroovyEditorComponent( new SetupScriptGroovyEditorModel(), null );
221 		return setupGroovyEditor;
222 	}
223 
224 	private JComponent buildPropertiesPanel()
225 	{
226 		JPanel panel = new JPanel( new BorderLayout() );
227 		propertiesTable = createPropertyHolderTable();
228 		panel.add( new JScrollPane( propertiesTable ), BorderLayout.CENTER );
229 		return panel;
230 	}
231 
232 	protected PropertyHolderTable createPropertyHolderTable()
233 	{
234 		return new PropertyHolderTable( getModelItem() );
235 	}
236 
237 	private JPanel buildDescriptionPanel()
238 	{
239    	JPanel panel = new JPanel( new BorderLayout() );
240    	descriptionArea = new JUndoableTextArea( getModelItem().getDescription() );
241    	descriptionArea.getDocument().addDocumentListener( new DocumentListenerAdapter() 
242    	{
243 			public void update(Document document)
244 			{
245 				getModelItem().setDescription( descriptionArea.getText() );
246 			}} );
247    	
248    	panel.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2));
249    	panel.add( new JScrollPane( descriptionArea ), BorderLayout.CENTER );
250    	UISupport.addTitledBorder( panel, "TestSuite Description" );
251    	
252 		return panel;
253 	}
254 	
255 	protected JComponent buildTestCaseList(WsdlTestSuite testSuite)
256 	{
257 		testCaseList = new JTestSuiteTestCaseList( testSuite );
258 		
259 		JPanel p = new JPanel( new BorderLayout() );
260 		
261 		p.add( buildTestCaseListToolbar(), BorderLayout.NORTH );
262 		p.add( new JScrollPane( testCaseList), BorderLayout.CENTER );
263 		
264 		return p;
265 	}
266 
267 	private Component buildTestCaseListToolbar()
268 	{
269 		JXToolBar toolbar = UISupport.createToolbar();
270 		toolbar.add( UISupport.createToolbarButton( 
271 					SwingActionDelegate.createDelegate( AddNewTestCaseAction.SOAPUI_ACTION_ID, getModelItem(), null, "/testCase.gif" )));
272 		toolbar.addGlue();
273 		toolbar.add(UISupport.createToolbarButton( new ShowOnlineHelpAction(HelpUrls.TESTSUITEEDITOR_HELP_URL)));
274 		return toolbar;
275 	}
276 
277 	public boolean onClose( boolean canCancel )
278 	{
279 		propertiesTable.release();
280 		
281 		setupGroovyEditor.getEditor().release();
282 		tearDownGroovyEditor.getEditor().release();
283 		
284 		testRunLog.release();
285 		
286 		return super.release();
287 	}
288 
289 	public JComponent getComponent()
290 	{
291 		return this;
292 	}
293 
294 	public boolean dependsOn(ModelItem modelItem)
295 	{
296 		return modelItem == getModelItem() || modelItem == getModelItem().getProject();
297 	}
298 
299 	protected void runTestSuite()
300 	{
301 		new Thread( testSuiteRunner, getModelItem().getName() + " TestSuiteRunner" ).start();
302 	}
303 
304 	protected void beforeRun()
305 	{
306 		runAction.setEnabled( false );
307 		cancelAction.setEnabled( true );
308 		testCaseList.setEnabled( false );
309 		progressBar.setForeground( Color.GREEN.darker() );
310 		
311 		failedTests = false;
312 	}
313 
314 	protected void afterRun()
315 	{
316 		runAction.setEnabled( true );
317 		cancelAction.setEnabled( false );
318 		testCaseList.setEnabled( true );
319 		
320 		progressBar.setString( failedTests ? "Failed" : testSuiteRunner.isCanceled() ? "Canceled" : "Passed" );
321 		progressBar.setForeground( failedTests ? Color.RED : Color.GREEN.darker() );
322 	}
323 	
324 	private final class InternalTestSuiteListener extends TestSuiteListenerAdapter
325 	{
326 		public void testCaseAdded(TestCase testCase)
327 		{
328 			runAction.setEnabled( getModelItem().getTestCaseCount() > 0 );
329 		}
330 
331 		public void testCaseRemoved(TestCase testCase)
332 		{
333 			runAction.setEnabled( getModelItem().getTestCaseCount() > 0 );
334 		}
335 	}
336 
337 	private class RunAction extends AbstractAction
338 	{
339 		public RunAction()
340 		{
341 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_testcase.gif" ));
342 			putValue( Action.SHORT_DESCRIPTION, "Runs the selected TestCases" );
343 		}
344 		
345 		public void actionPerformed(ActionEvent e)
346 		{
347 			runTestSuite();
348 		}
349 	}
350 	
351 	private class CancelAction extends AbstractAction
352 	{
353 		public CancelAction()
354 		{
355 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stop_testcase.gif" ));
356 			putValue( Action.SHORT_DESCRIPTION, "Cancels ongoing TestCase runs" );
357 		}
358 		
359 		public void actionPerformed(ActionEvent e)
360 		{
361 		   testSuiteRunner.cancel();
362 		}
363 	}
364 	
365 	/***
366 	 * Runs the selected testsuites..
367 	 * 
368 	 * @author Ole.Matzura
369 	 */
370 	
371 	public class TestSuiteRunner extends WsdlTestScenario
372 	{
373 		private TestRunLogTestRunListener runLogListener;
374 		private int finishCount;
375 
376 		public TestSuiteRunner()
377 		{
378 			super( TestSuiteRunType.SEQUENTIAL );
379 		}
380 		
381 		public void run()
382 		{
383 			setRunType( getModelItem().getRunType() );
384 			
385 			removeAllTestCases();
386 
387 			testCaseList.reset();
388 			
389 			for( TestCase testCase : getModelItem().getTestCaseList() )
390 			{
391 				if( !testCase.isDisabled() )
392 					addTestCase( testCase );
393 			}
394 			
395 			super.run();
396 		}
397 
398 		protected PropertyExpansionContext createContext()
399 		{
400 			return new DefaultPropertyExpansionContext( getModelItem() );
401 		}
402 		
403 		public void beforeRun( PropertyExpansionContext context )
404 		{
405 			super.beforeRun( context );
406 			
407 			WsdlTestSuiteDesktopPanel.this.beforeRun();
408 			
409 			progressBar.setMaximum( getTestCaseCount() );
410 			progressBar.setValue( 0 );
411 			progressBar.setString( "" ); 
412 			finishCount = 0;
413 			
414 			if( runLogListener == null )
415 				runLogListener = new TestRunLog.TestRunLogTestRunListener( testRunLog, false );
416 			
417 			testRunLog.clear();
418 			
419 			if( getRunType() == TestSuiteRunType.PARALLEL )
420 				testRunLog.addText( "<log disabled during parallell execution>" );
421 			
422 			context = new DefaultPropertyExpansionContext( getModelItem() );
423 			try
424 			{
425 				getModelItem().runSetupScript( context );
426 			}
427 			catch( Exception e )
428 			{
429 				SoapUI.logError( e );
430 			}
431 		}
432 
433 		@Override
434 		protected void afterTestCase( TestCase testCase, TestRunner runner )
435 		{
436 			super.afterTestCase( testCase, runner );
437 			progressBar.setValue( ++finishCount );
438 			if( runner.getStatus() == TestRunner.Status.FAILED )
439 				failedTests = true;
440 			
441 			if( getRunType() == TestSuiteRunType.SEQUENTIAL )
442 				testCase.removeTestRunListener( runLogListener );
443 		}
444 
445 		@Override
446 		protected void beforeTestCase( TestCase testCase )
447 		{
448 			super.beforeTestCase( testCase );
449 			progressBar.setString( "Running " + testCase.getName() );
450 			
451 			if( getRunType() == TestSuiteRunType.SEQUENTIAL )
452 				testCase.addTestRunListener( runLogListener );
453 		}
454 
455 		protected void afterRun(PropertyExpansionContext context)
456 		{
457 			super.afterRun( context );
458 			
459 			try
460 			{
461 				getModelItem().runTearDownScript( context );
462 			}
463 			catch( Exception e )
464 			{
465 				SoapUI.logError( e );
466 			}
467 			finally
468 			{
469 				WsdlTestSuiteDesktopPanel.this.afterRun();
470 			}
471 		}
472 	}
473 	
474 	private class SetupScriptGroovyEditorModel extends AbstractGroovyEditorModel
475 	{
476 		public SetupScriptGroovyEditorModel()
477 		{
478 			super( new String[] {"log", "context", "testSuite" }, getModelItem().getSettings(), "Setup" );
479 		}
480 		
481 		public String getScript()
482 		{
483 			return getModelItem().getSetupScript();
484 		}
485 
486 		public void setScript( String text )
487 		{
488 			getModelItem().setSetupScript( text );
489 		}
490 		
491 		@Override
492 		public Action createRunAction()
493 		{
494 			return new AbstractAction(){
495 
496 				public void actionPerformed( ActionEvent e )
497 				{
498 					try
499 					{
500 						getModelItem().runSetupScript( null );
501 					}
502 					catch( Exception e1 )
503 					{
504 						UISupport.showErrorMessage( e1 );
505 					}
506 				}};
507 		}
508 	}
509 	
510 	private class TearDownScriptGroovyEditorModel extends AbstractGroovyEditorModel
511 	{
512 		public TearDownScriptGroovyEditorModel()
513 		{
514 			super( new String[] {"log", "context", "testSuite" }, getModelItem().getSettings(), "TearDown" );
515 		}
516 		
517 		public String getScript()
518 		{
519 			return getModelItem().getTearDownScript();
520 		}
521 
522 		public void setScript( String text )
523 		{
524 			getModelItem().setTearDownScript( text );
525 		}
526 		
527 		@Override
528 		public Action createRunAction()
529 		{
530 			return new AbstractAction(){
531 
532 				public void actionPerformed( ActionEvent e )
533 				{
534 					try
535 					{
536 						getModelItem().runTearDownScript( null );
537 					}
538 					catch( Exception e1 )
539 					{
540 						UISupport.showErrorMessage( e1 );
541 					}
542 				}};
543 		}
544 	}
545 }