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.testcase;
14  
15  import java.awt.event.ActionEvent;
16  import java.util.ArrayList;
17  import java.util.HashSet;
18  import java.util.List;
19  import java.util.Set;
20  
21  import javax.swing.AbstractAction;
22  import javax.swing.Action;
23  
24  import org.apache.log4j.Logger;
25  
26  import com.eviware.soapui.config.LoadTestConfig;
27  import com.eviware.soapui.config.TestCaseConfig;
28  import com.eviware.soapui.config.TestStepConfig;
29  import com.eviware.soapui.impl.actions.ShowDesktopPanelAction;
30  import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
31  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
32  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
33  import com.eviware.soapui.impl.wsdl.actions.testcase.AddNewLoadTestAction;
34  import com.eviware.soapui.impl.wsdl.actions.testcase.ClearTestCaseAction;
35  import com.eviware.soapui.impl.wsdl.actions.testcase.CloneTestCaseAction;
36  import com.eviware.soapui.impl.wsdl.actions.testcase.RemoveTestCaseAction;
37  import com.eviware.soapui.impl.wsdl.actions.testcase.RenameTestCaseAction;
38  import com.eviware.soapui.impl.wsdl.actions.testcase.TestCaseOptionsAction;
39  import com.eviware.soapui.impl.wsdl.loadtest.LoadTestAssertion;
40  import com.eviware.soapui.impl.wsdl.loadtest.WsdlLoadTest;
41  import com.eviware.soapui.impl.wsdl.loadtest.assertions.TestStepStatusAssertion;
42  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
43  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
44  import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepFactory;
45  import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepRegistry;
46  import com.eviware.soapui.model.support.PropertiesMap;
47  import com.eviware.soapui.model.testsuite.LoadTest;
48  import com.eviware.soapui.model.testsuite.TestCase;
49  import com.eviware.soapui.model.testsuite.TestRunListener;
50  import com.eviware.soapui.model.testsuite.TestStep;
51  import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
52  import com.eviware.soapui.support.UISupport;
53  import com.eviware.soapui.support.action.ActionList;
54  import com.eviware.soapui.support.action.ActionSupport;
55  import com.eviware.soapui.support.action.DefaultActionList;
56  
57  /***
58   * TestCase implementation for WSDL projects
59   *  
60   * @author Ole.Matzura
61   */
62  
63  public class WsdlTestCase extends AbstractWsdlModelItem<TestCaseConfig> implements TestCase
64  {
65     private final static Logger logger = Logger.getLogger( WsdlTestCase.class );
66     public final static String KEEP_SESSION_PROPERTY = WsdlTestCase.class.getName() + "@keepSession";
67     public final static String FAIL_ON_ERROR_PROPERTY = WsdlTestCase.class.getName() + "@failOnError";
68     public final static String FAIL_ON_ERRORS_PROPERTY = WsdlTestCase.class.getName() + "@failOnErrors";
69     public final static String DISCARD_OK_RESULTS = WsdlTestCase.class.getName() + "@discardOkResults";
70  	private static final String SEARCH_PROPERTIES_PROPERTY = WsdlTestCase.class.getName() + "@searchProperties";
71  	
72  	private final WsdlTestSuite testSuite;
73     private List<WsdlTestStep> testSteps = new ArrayList<WsdlTestStep>();
74     private List<WsdlLoadTest> loadTests = new ArrayList<WsdlLoadTest>();
75     private Set<TestRunListener> testRunListeners = new HashSet<TestRunListener>();
76  	private DefaultActionList createActions;
77  	
78     public WsdlTestCase(WsdlTestSuite testSuite, TestCaseConfig config)
79     {
80     	super( config, testSuite, "/testCase.gif" );
81     	
82        this.testSuite = testSuite;
83        
84        List<TestStepConfig> testStepConfigs = config.getTestStepList();
85        for (TestStepConfig tsc : testStepConfigs )
86        {
87           WsdlTestStep testStep = createTestStepFromConfig(tsc);
88           if( testStep != null )
89           {
90              ensureUniqueName( testStep );
91           	testSteps.add( testStep );
92           }
93        }
94        
95        for( TestStep step : testSteps )
96        {
97        	WsdlTestStep testStep = (WsdlTestStep) step;
98        	testStep.postInit( testStep.getConfig() );
99        }
100    
101       List<LoadTestConfig> loadTestConfigs = config.getLoadTestList();
102       for (LoadTestConfig tsc : loadTestConfigs)
103       {
104          WsdlLoadTest loadTest = new WsdlLoadTest( this, tsc );
105 			loadTests.add( loadTest);
106       }
107 
108       addAction( new ShowDesktopPanelAction( "Open TestCase Editor", 
109       		"Opens the TestCase Editor for this TestCase", this ));
110       addAction( ActionSupport.SEPARATOR_ACTION );
111       addAction( new AddNewLoadTestAction( this ));
112       addAction( new CloneTestCaseAction( this ));
113       addAction( new ClearTestCaseAction( this ));
114       addAction( ActionSupport.SEPARATOR_ACTION );
115       addAction( new TestCaseOptionsAction( this ));
116 
117       createActions = new DefaultActionList( "New Step" );
118 		WsdlTestStepRegistry registry = WsdlTestStepRegistry.getInstance();
119 		WsdlTestStepFactory[] factories = (WsdlTestStepFactory[]) registry.getFactories();
120 
121 		for (int c = 0; c < factories.length; c++)
122 		{
123 			if (factories[c].canCreate())
124 				createActions.addAction( new AddTestStepAction(factories[c]));
125 		}
126 
127 		addAction( new ActionSupport.ActionListAction( createActions ));
128       addAction( ActionSupport.SEPARATOR_ACTION );
129       addAction( new RenameTestCaseAction( this ) );
130       addAction( new RemoveTestCaseAction( this ) );
131       addAction( ActionSupport.SEPARATOR_ACTION );
132       addAction( new ShowOnlineHelpAction( HelpUrls.TESTCASE_HELP_URL ));
133       
134       // init default configs
135       if( !config.isSetFailOnError() )
136       	config.setFailOnError( true );
137       
138       if( !config.isSetFailTestCaseOnErrors() )
139       	config.setFailTestCaseOnErrors( true );
140 
141       if( !config.isSetKeepSession() )
142       	config.setKeepSession( false );
143       
144       // add listeners for aborting on errors
145       
146       /*
147       addTestRunListener( new TestRunListenerAdapter() {
148 
149 			public void afterStep(TestRunner testRunner, TestRunContext runContext, TestStepResult result)
150 			{
151 				if( result.getStatus() == TestStepStatus.FAILED )
152 				{
153 					if( getFailOnError()  )
154 					{
155 						testRunner.fail( "Cancelling due to failed test step" );
156 					}
157 					else
158 					{
159 						runContext.setProperty( TestRunner.Status.class.getName(), TestRunner.Status.FAILED );
160 					}
161 				}
162 			}
163 
164 			public void afterRun(TestRunner testRunner, TestRunContext runContext)
165 			{
166 				if( runContext.getProperty( TestRunner.Status.class.getName() ) == TestRunner.Status.FAILED )
167 				{
168 					testRunner.fail( "Cancelling due to failed test step" );
169 				}
170 			}
171       } 
172       
173       );*/
174    }
175 
176    public boolean getKeepSession()
177    {
178    	return getConfig().getKeepSession();
179    }
180    
181    public void setKeepSession( boolean keepSession )
182    {
183    	boolean old = getKeepSession();
184    	if( old != keepSession )
185    	{
186    		getConfig().setKeepSession( keepSession );
187    		notifyPropertyChanged( KEEP_SESSION_PROPERTY, old, keepSession );
188    	}
189    }
190    
191    public boolean getFailOnError()
192    {
193    	return getConfig().getFailOnError();
194    }
195    
196    public boolean getFailTestCaseOnErrors()
197    {
198    	return getConfig().getFailTestCaseOnErrors();
199    }
200    
201    public void setFailOnError( boolean failOnError )
202    {
203    	boolean old = getFailOnError();
204    	if( old != failOnError )
205    	{
206    		getConfig().setFailOnError( failOnError );
207    		notifyPropertyChanged( FAIL_ON_ERROR_PROPERTY, old, failOnError );
208    	}
209    }
210    
211    public void setFailTestCaseOnErrors( boolean failTestCaseOnErrors )
212    {
213    	boolean old = getFailTestCaseOnErrors();
214    	if( old != failTestCaseOnErrors )
215    	{
216    		getConfig().setFailTestCaseOnErrors( failTestCaseOnErrors );
217    		notifyPropertyChanged( FAIL_ON_ERRORS_PROPERTY, old, failTestCaseOnErrors );
218    	}
219    }
220    
221    public boolean getSearchProperties()
222    {
223    	return getConfig().getSearchProperties();
224    }
225    
226    public void setSearchProperties( boolean searchProperties )
227    {
228    	boolean old = getSearchProperties();
229    	if( old != searchProperties )
230    	{
231    		getConfig().setSearchProperties( searchProperties );
232    		notifyPropertyChanged( SEARCH_PROPERTIES_PROPERTY, old, searchProperties );
233    	}
234    }
235    
236    public boolean getDiscardOkResults()
237    {
238    	return getConfig().getDiscardOkResults();
239    }
240    
241    public void setDiscardOkResults( boolean discardOkResults )
242    {
243    	boolean old = getDiscardOkResults();
244    	if( old != discardOkResults )
245    	{
246    		getConfig().setDiscardOkResults( discardOkResults );
247    		notifyPropertyChanged( DISCARD_OK_RESULTS, old, discardOkResults );
248    	}
249    }
250    
251 	private WsdlTestStep createTestStepFromConfig(TestStepConfig tsc )
252 	{
253 		WsdlTestStepFactory factory = WsdlTestStepRegistry.getInstance().getFactory( tsc.getType() );
254 		if( factory != null )
255 		{
256 			WsdlTestStep testStep = factory.buildTestStep( this, tsc );
257 			return testStep;
258 		}
259 		else 
260 		{
261 			logger.error( "Failed to create test step for [" + tsc.getName() + "]" );
262 			return null;
263 		}
264 	}
265 
266 	private boolean ensureUniqueName(WsdlTestStep testStep)
267 	{
268 		String name = testStep.getName();
269 		while( name == null || getTestStepByName( name ) != null )
270 		{
271 			if( name == null )
272 				name = testStep.getName();
273 			else
274 			{
275 				int cnt = 0;
276 				
277 				while( getTestStepByName( name ) != null )
278 				{
279 					cnt++;
280 					name = testStep.getName() + " " + cnt;
281 				}
282 				
283 				if( cnt == 0 )
284 					break;
285 			}
286 			
287 			name = UISupport.prompt( "TestStep name must be unique, please specify new name for step\n" +
288 					"[" + testStep.getName() + "] in TestCase [" + getTestSuite().getProject().getName() + "->" +
289 					getTestSuite().getName() + "->" + getName() + "]", 
290 					"Change TestStep name", name);
291 			
292 			if( name == null )
293 				return false;
294 		}
295 		
296 		if( !name.equals( testStep.getName() ))
297 			testStep.setName( name );
298 		
299 		return true;
300 	}
301 
302    public WsdlLoadTest addNewLoadTest( String name )
303    {
304       WsdlLoadTest loadTest = new WsdlLoadTest( this, getConfig().addNewLoadTest());
305       loadTest.setStartDelay( 0 );
306       loadTest.setName( name );
307       loadTests.add( loadTest );
308       
309       loadTest.addAssertion( TestStepStatusAssertion.STEP_STATUS_TYPE, 
310       		LoadTestAssertion.ANY_TEST_STEP, false );
311 
312       ((WsdlTestSuite)getTestSuite()).fireLoadTestAdded( loadTest );
313       
314       return loadTest;
315    }
316    
317 	public void removeLoadTest(WsdlLoadTest loadTest)
318 	{
319 		int ix = loadTests.indexOf( loadTest );
320 
321 		loadTests.remove( ix );
322 		
323 		try
324 		{
325 			((WsdlTestSuite)getTestSuite()).fireLoadTestRemoved( loadTest );
326 		}
327 		finally
328 		{
329 			loadTest.release();
330 			getConfig().removeLoadTest( ix );
331 		}
332 	} 
333 
334    public WsdlTestSuite getTestSuite()
335    {
336       return testSuite;
337    }
338 
339    public WsdlTestStep cloneStep( WsdlTestStep testStep, String name )
340    {
341    	return testStep.clone( this, name );
342    }
343    
344    public TestStepStatus getStatus()
345    {
346       return TestStepStatus.UNKNOWN;
347    }
348 
349    public WsdlTestStep getTestStepAt(int index)
350    {
351       return testSteps.get( index );
352    }
353 
354    public int getTestStepCount()
355    {
356       return testSteps.size();
357    }
358 
359    public WsdlLoadTest getLoadTestAt(int index)
360    {
361       return loadTests.get( index );
362    }
363 
364    public LoadTest getLoadTestByName(String loadTestName)
365 	{
366 		return (LoadTest) getWsdlModelItemByName( loadTests, loadTestName );
367 	}
368 
369 	public int getLoadTestCount()
370    {
371       return loadTests.size();
372    }
373    
374    public WsdlTestStep addTestStep( TestStepConfig stepConfig )
375    {
376    	return insertTestStep( stepConfig, -1 );
377    }
378    
379    public WsdlTestStep addTestStep( String type, String name  )
380    {
381    	TestStepConfig newStepConfig = WsdlTestStepRegistry.getInstance().getFactory( type ).createNewTestStep( this, name );
382    	if( newStepConfig != null ) 
383    	{
384    		return addTestStep( newStepConfig);
385   		}
386    	else return null;
387    }
388    
389    public WsdlTestStep insertTestStep( String type, String name, int index  )
390    {
391    	TestStepConfig newStepConfig = WsdlTestStepRegistry.getInstance().getFactory( type ).createNewTestStep( this, name );
392    	if( newStepConfig != null )
393    	{
394    		return insertTestStep( newStepConfig, index );
395    	}
396    	else return null;
397    }
398    
399    public WsdlTestStep insertTestStep( TestStepConfig stepConfig, int ix )
400    {
401    	TestStepConfig newStepConfig = ix == -1 ? getConfig().addNewTestStep() : getConfig().insertNewTestStep( ix );
402    	newStepConfig.set( stepConfig );
403    	WsdlTestStep testStep = createTestStepFromConfig( newStepConfig );
404    	
405    	if( !ensureUniqueName( testStep ))
406    		return null;
407    	
408       if( ix == -1 )
409       	testSteps.add( testStep );
410       else
411       	testSteps.add( ix, testStep );
412       
413       testStep.postInit( testStep.getConfig() );
414       
415       if( getTestSuite() != null )
416       	((WsdlTestSuite)getTestSuite()).fireTestStepAdded( testStep, ix == -1 ? testSteps.size()-1 : ix  );
417       
418       return testStep;
419    }
420    
421    public void removeTestStep(WsdlTestStep testStep)
422    {
423       int ix = testSteps.indexOf( testStep );
424       if( ix == -1 )
425       {
426          logger.error( "TestStep [" + testStep.getName() + "] passed to removeTestStep in testCase [" + 
427                getName() + "] not found" );
428          return;
429       }
430       
431       testSteps.remove( ix );
432 
433       try
434       {
435       	((WsdlTestSuite)getTestSuite()).fireTestStepRemoved( testStep, ix );
436       }
437       finally
438       {
439       	testStep.release();
440       
441 	      for( int c = 0; c < getConfig().sizeOfTestStepArray(); c++ ) 
442 	      {
443 	      	if( testStep.getConfig() == getConfig().getTestStepArray( c ))
444 	      	{
445 	      		getConfig().removeTestStep( c );
446 	      		break;
447 	      	}
448 	      }
449       }
450    }
451    
452    public WsdlTestCaseRunner run( PropertiesMap properties, boolean async ) 
453    {
454    	WsdlTestCaseRunner runner = new WsdlTestCaseRunner( this, properties );
455    	runner.start( async );
456    	return runner;
457 	}
458 
459 	public void addTestRunListener(TestRunListener listener) {
460 		if( listener == null )
461 			throw new RuntimeException( "listener must not be null" );
462 		
463 		testRunListeners.add( listener );
464 	}
465 
466 	public void removeTestRunListener(TestRunListener listener) {
467 		testRunListeners.remove( listener );
468 	}
469 	
470 	public TestRunListener [] getTestRunListeners()
471 	{
472 		return testRunListeners.toArray( new TestRunListener[testRunListeners.size()]);
473 	}
474 
475 	WsdlTestStep[] getTestSteps() 
476 	{
477 		return testSteps.toArray( new WsdlTestStep[testSteps.size()] );
478  	}
479 
480 	public int getIndexOfTestStep(TestStep step)
481 	{
482 		return testSteps.indexOf( step );
483 	}
484 	
485 	/***
486 	 * Moves a step by the specified offset, a bit awkward since xmlbeans doesn't support reordering
487 	 * of arrays, we need to create copies of the contained XmlObjects
488 	 * 
489 	 * @param ix
490 	 * @param offset
491 	 */
492 	
493 	public void moveTestStep(int ix, int offset)
494 	{
495 		if( offset == 0 ) return;
496 		WsdlTestStep step = (WsdlTestStep) testSteps.get( ix );
497 
498 		testSteps.remove( ix );
499 		testSteps.add( ix+offset, step );
500 
501 		TestStepConfig [] configs = new TestStepConfig[testSteps.size()];
502 		
503 		for( int c = 0; c < testSteps.size(); c++ )
504 		{
505 			if( offset > 0 )
506 			{
507 				if( c < ix )
508 					configs[c] = (TestStepConfig) getConfig().getTestStepArray(c).copy();
509 				else if( c < (ix+offset))
510 					configs[c] = (TestStepConfig) getConfig().getTestStepArray(c+1).copy();
511 				else if( c == ix+offset )
512 					configs[c] = (TestStepConfig) getConfig().getTestStepArray(ix).copy();
513 				else
514 					configs[c] = (TestStepConfig) getConfig().getTestStepArray(c).copy();
515 			}
516 			else
517 			{
518 				if( c < ix+offset )
519 					configs[c] = (TestStepConfig) getConfig().getTestStepArray(c).copy();
520 				else if( c == ix+offset )
521 					configs[c] = (TestStepConfig) getConfig().getTestStepArray(ix).copy();
522 				else if( c <= ix )
523 					configs[c] = (TestStepConfig) getConfig().getTestStepArray(c-1).copy();
524 				else
525 					configs[c] = (TestStepConfig) getConfig().getTestStepArray(c).copy();				
526 			}
527 		}
528 		
529 		getConfig().setTestStepArray( configs );
530 		for( int c = 0; c < configs.length; c++ )
531 		{
532 			((WsdlTestStep) testSteps.get( c )).resetConfigOnMove( getConfig().getTestStepArray( c ));
533 		}
534 		
535 		((WsdlTestSuite)getTestSuite()).fireTestStepMoved(step, ix, offset );
536 	}
537 	
538 	public int getIndexOfLoadTest( LoadTest loadTest )
539 	{
540 		return loadTests.indexOf( loadTest );
541 	}
542 
543 
544 	public int getTestStepIndexByName(String stepName)
545 	{
546 		for( int c = 0; c < testSteps.size(); c++ )
547 		{
548 			if( testSteps.get( c ).getName().equals( stepName ))
549 				return c;
550 		}
551 		
552 		return -1;
553 	}
554 	
555 	public TestStep findPreviousStepOfType( TestStep referenceStep, Class stepClass )
556 	{
557 		int currentStepIndex = getIndexOfTestStep( referenceStep );
558 		int ix = currentStepIndex - 1 ;
559 		while( ix >= 0 && !getTestStepAt( ix ).getClass().equals( stepClass ))
560 		{
561 			ix--;
562 		}
563 		
564 		return ix < 0 ? null : getTestStepAt( ix );
565 	}
566 	
567 	public TestStep findNextStepOfType( TestStep referenceStep, Class stepClass )
568 	{
569 		int currentStepIndex = getIndexOfTestStep( referenceStep );
570 		int ix = currentStepIndex + 1 ;
571 		while( ix < getTestStepCount() && !getTestStepAt( ix ).getClass().equals( stepClass ))
572 		{
573 			ix++;
574 		}
575 		
576 		return ix >= getTestStepCount() ? null : getTestStepAt( ix );
577 	}
578 
579 	public List<TestStep> getTestStepList()
580 	{
581 		List<TestStep> result = new ArrayList<TestStep>();
582 		for( TestStep step : testSteps )
583 			result.add( step );
584 			
585 		return result;
586 	}
587 	
588 	public List<TestStep> getTestStepsOfType( Class<? extends WsdlTestStep> stepType )
589 	{
590 		List<TestStep> result = new ArrayList<TestStep>();
591 		for( TestStep step : testSteps )
592 			if( step.getClass().isAssignableFrom( stepType ) )
593 				result.add( step );
594 			
595 		return result;
596 	}
597 
598 	public WsdlTestStep getTestStepByName(String stepName)
599 	{
600 		return (WsdlTestStep)getWsdlModelItemByName( testSteps, stepName );
601 	}
602 
603 	public WsdlLoadTest cloneLoadTest(WsdlLoadTest loadTest, String name)
604 	{
605 		LoadTestConfig loadTestConfig = getConfig().addNewLoadTest();
606 		loadTestConfig.set( loadTest.getConfig().copy());
607 		
608 		WsdlLoadTest newLoadTest = new WsdlLoadTest( this, loadTestConfig );
609 		newLoadTest.setName( name );
610 	   loadTests.add( newLoadTest );
611 
612 	   ((WsdlTestSuite)getTestSuite()).fireLoadTestAdded( newLoadTest );
613 	      
614 	   return newLoadTest;
615 	}
616 
617 	public void release()
618 	{
619 		super.release();
620 		
621 		for( WsdlTestStep testStep : testSteps )
622 			testStep.release();
623 		
624 		for( WsdlLoadTest loadTest : loadTests )
625 			loadTest.release();
626 	}
627 	
628 	public class AddTestStepAction extends AbstractAction
629 	{
630 		private final WsdlTestStepFactory factory;
631 
632 		public AddTestStepAction(WsdlTestStepFactory factory)
633 		{
634 			super(factory.getTestStepName());
635 			putValue(Action.SHORT_DESCRIPTION, factory.getTestStepDescription());
636 			this.factory = factory;
637 			putValue( Action.SMALL_ICON, factory.getTestStepIcon() );
638 		}
639 
640 		public void actionPerformed(ActionEvent e)
641 		{
642 			String name = UISupport.prompt( "Specify name for new step", "Add Step", factory.getTestStepName());
643 			if( name != null )
644 			{
645 				TestStepConfig newTestStepConfig = factory.createNewTestStep(WsdlTestCase.this, name);
646 				if( newTestStepConfig != null )
647 				{
648 					WsdlTestStep testStep = addTestStep(newTestStepConfig);
649 					UISupport.selectAndShow( testStep );
650 				}
651 			}
652 		}
653 	}
654 
655 	public ActionList getCreateActions()
656 	{
657 		return createActions;
658 	}
659 }