1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.tools;
14
15 import java.io.File;
16 import java.io.FileOutputStream;
17 import java.io.PrintWriter;
18 import java.io.StringWriter;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.apache.commons.cli.CommandLine;
26
27 import com.eviware.soapui.SoapUI;
28 import com.eviware.soapui.impl.wsdl.WsdlProject;
29 import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
30 import com.eviware.soapui.impl.wsdl.testcase.WsdlProjectRunner;
31 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
32 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner;
33 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestSuiteRunner;
34 import com.eviware.soapui.impl.wsdl.teststeps.WsdlRunTestCaseTestStep;
35 import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
36 import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStepResult;
37 import com.eviware.soapui.model.iface.Attachment;
38 import com.eviware.soapui.model.iface.MessageExchange;
39 import com.eviware.soapui.model.project.ProjectFactoryRegistry;
40 import com.eviware.soapui.model.support.ModelSupport;
41 import com.eviware.soapui.model.support.ProjectRunListenerAdapter;
42 import com.eviware.soapui.model.testsuite.Assertable;
43 import com.eviware.soapui.model.testsuite.AssertionError;
44 import com.eviware.soapui.model.testsuite.ProjectRunContext;
45 import com.eviware.soapui.model.testsuite.ProjectRunner;
46 import com.eviware.soapui.model.testsuite.TestAssertion;
47 import com.eviware.soapui.model.testsuite.TestCase;
48 import com.eviware.soapui.model.testsuite.TestCaseRunContext;
49 import com.eviware.soapui.model.testsuite.TestCaseRunner;
50 import com.eviware.soapui.model.testsuite.TestStep;
51 import com.eviware.soapui.model.testsuite.TestStepResult;
52 import com.eviware.soapui.model.testsuite.TestSuite;
53 import com.eviware.soapui.model.testsuite.TestSuiteRunner;
54 import com.eviware.soapui.model.testsuite.Assertable.AssertionStatus;
55 import com.eviware.soapui.model.testsuite.TestRunner.Status;
56 import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
57 import com.eviware.soapui.report.JUnitReportCollector;
58 import com.eviware.soapui.support.StringUtils;
59 import com.eviware.soapui.support.Tools;
60 import com.eviware.soapui.support.types.StringToObjectMap;
61
62 /***
63 * Standalone test-runner used from maven-plugin, can also be used from
64 * command-line (see xdocs) or directly from other classes.
65 * <p>
66 * For standalone usage, set the project file (with setProjectFile) and other
67 * desired properties before calling run
68 * </p>
69 *
70 * @author Ole.Matzura
71 */
72
73 public class SoapUITestCaseRunner extends AbstractSoapUITestRunner
74 {
75 public static final String SOAPUI_EXPORT_SEPARATOR = "soapui.export.separator";
76
77 public static final String TITLE = "soapUI " + SoapUI.SOAPUI_VERSION + " TestCase Runner";
78
79 private String testSuite;
80 private String testCase;
81 private List<TestAssertion> assertions = new ArrayList<TestAssertion>();
82 private Map<TestAssertion, WsdlTestStepResult> assertionResults = new HashMap<TestAssertion, WsdlTestStepResult>();
83
84
85 private List<TestCase> failedTests = new ArrayList<TestCase>();
86
87 private int testSuiteCount;
88 private int testCaseCount;
89 private int testStepCount;
90 private int testAssertionCount;
91
92 private boolean printReport;
93 private boolean exportAll;
94 private boolean ignoreErrors;
95 private boolean junitReport;
96 private int exportCount;
97 private int maxErrors = 5;
98 private JUnitReportCollector reportCollector;
99
100 private String projectPassword;
101 private boolean saveAfterRun;
102
103 /***
104 * Runs the tests in the specified soapUI project file, see soapUI xdocs for
105 * details.
106 *
107 * @param args
108 * @throws Exception
109 */
110
111 public static void main( String[] args ) throws Exception
112 {
113 System.exit( new SoapUITestCaseRunner().runFromCommandLine( args ) );
114 }
115
116 protected boolean processCommandLine( CommandLine cmd )
117 {
118 String message = "";
119 if( cmd.hasOption( "e" ) )
120 setEndpoint( cmd.getOptionValue( "e" ) );
121
122 if( cmd.hasOption( "s" ) )
123 {
124 String testSuite = getCommandLineOptionSubstSpace( cmd, "s" );
125 setTestSuite( testSuite );
126 }
127
128 if( cmd.hasOption( "c" ) )
129 {
130 String testCase = getCommandLineOptionSubstSpace( cmd, "c" );
131 setTestCase( testCase );
132 }
133
134 if( cmd.hasOption( "u" ) )
135 setUsername( cmd.getOptionValue( "u" ) );
136
137 if( cmd.hasOption( "p" ) )
138 setPassword( cmd.getOptionValue( "p" ) );
139
140 if( cmd.hasOption( "w" ) )
141 setWssPasswordType( cmd.getOptionValue( "w" ) );
142
143 if( cmd.hasOption( "d" ) )
144 setDomain( cmd.getOptionValue( "d" ) );
145
146 if( cmd.hasOption( "h" ) )
147 setHost( cmd.getOptionValue( "h" ) );
148
149 if( cmd.hasOption( "f" ) )
150 setOutputFolder( getCommandLineOptionSubstSpace( cmd, "f" ) );
151
152 if( cmd.hasOption( "t" ) )
153 setSettingsFile( getCommandLineOptionSubstSpace( cmd, "t" ) );
154
155 if( cmd.hasOption( "x" ) )
156 {
157 setProjectPassword( cmd.getOptionValue( "x" ) );
158 }
159
160 if( cmd.hasOption( "v" ) )
161 {
162 setSoapUISettingsPassword( cmd.getOptionValue( "v" ) );
163 }
164
165 if( cmd.hasOption( "D" ) )
166 {
167 setSystemProperties( cmd.getOptionValues( "D" ) );
168 }
169
170 if( cmd.hasOption( "G" ) )
171 {
172 setGlobalProperties( cmd.getOptionValues( "G" ) );
173 }
174
175 if( cmd.hasOption( "P" ) )
176 {
177 setProjectProperties( cmd.getOptionValues( "P" ) );
178 }
179
180 setIgnoreError( cmd.hasOption( "I" ) );
181 setEnableUI( cmd.hasOption( "i" ) );
182 setPrintReport( cmd.hasOption( "r" ) );
183 setExportAll( cmd.hasOption( "a" ) );
184 if( cmd.hasOption( "A" ) )
185 {
186 setExportAll( true );
187 System.setProperty( SOAPUI_EXPORT_SEPARATOR, File.separator );
188 }
189
190 setJUnitReport( cmd.hasOption( "j" ) );
191
192 if( cmd.hasOption( "m" ) )
193 setMaxErrors( Integer.parseInt( cmd.getOptionValue( "m" ) ) );
194
195 setSaveAfterRun( cmd.hasOption( "S" ) );
196
197 if( message.length() > 0 )
198 {
199 log.error( message );
200 return false;
201 }
202
203 return true;
204 }
205
206 public void setMaxErrors( int maxErrors )
207 {
208 this.maxErrors = maxErrors;
209 }
210
211 protected int getMaxErrors()
212 {
213 return maxErrors;
214 }
215
216 public void setSaveAfterRun( boolean saveAfterRun )
217 {
218 this.saveAfterRun = saveAfterRun;
219 }
220
221 public void setProjectPassword( String projectPassword )
222 {
223 this.projectPassword = projectPassword;
224 }
225
226 public String getProjectPassword()
227 {
228 return projectPassword;
229 }
230
231 protected SoapUIOptions initCommandLineOptions()
232 {
233 SoapUIOptions options = new SoapUIOptions( "testrunner" );
234 options.addOption( "e", true, "Sets the endpoint" );
235 options.addOption( "s", true, "Sets the testsuite" );
236 options.addOption( "c", true, "Sets the testcase" );
237 options.addOption( "u", true, "Sets the username" );
238 options.addOption( "p", true, "Sets the password" );
239 options.addOption( "w", true, "Sets the WSS password type, either 'Text' or 'Digest'" );
240 options.addOption( "i", false, "Enables Swing UI for scripts" );
241 options.addOption( "d", true, "Sets the domain" );
242 options.addOption( "h", true, "Sets the host" );
243 options.addOption( "r", false, "Prints a small summary report" );
244 options.addOption( "f", true, "Sets the output folder to export results to" );
245 options.addOption( "j", false, "Sets the output to include JUnit XML reports" );
246 options.addOption( "m", false, "Sets the maximum number of TestStep errors to save for each testcase" );
247 options.addOption( "a", false, "Turns on exporting of all results" );
248 options.addOption( "A", false, "Turns on exporting of all results using folders instead of long filenames" );
249 options.addOption( "t", true, "Sets the soapui-settings.xml file to use" );
250 options.addOption( "x", true, "Sets project password for decryption if project is encrypted" );
251 options.addOption( "v", true, "Sets password for soapui-settings.xml file" );
252 options.addOption( "D", true, "Sets system property with name=value" );
253 options.addOption( "G", true, "Sets global property with name=value" );
254 options.addOption( "P", true, "Sets or overrides project property with name=value" );
255 options.addOption( "I", false, "Do not stop if error occurs, ignore them" );
256 options.addOption( "S", false, "Saves the project after running the tests" );
257
258 return options;
259 }
260
261 /***
262 * Add console appender to groovy log
263 */
264
265 public void setExportAll( boolean exportAll )
266 {
267 this.exportAll = exportAll;
268 }
269
270 public void setJUnitReport( boolean junitReport )
271 {
272 this.junitReport = junitReport;
273 if( junitReport )
274 reportCollector = createJUnitReportCollector();
275 }
276
277 protected JUnitReportCollector createJUnitReportCollector()
278 {
279 return new JUnitReportCollector( maxErrors );
280 }
281
282 public SoapUITestCaseRunner()
283 {
284 super( SoapUITestCaseRunner.TITLE );
285 }
286
287 public SoapUITestCaseRunner( String title )
288 {
289 super( title );
290 }
291
292 /***
293 * Controls if a short test summary should be printed after the test runs
294 *
295 * @param printReport
296 * a flag controlling if a summary should be printed
297 */
298
299 public void setPrintReport( boolean printReport )
300 {
301 this.printReport = printReport;
302 }
303
304 public void setIgnoreError( boolean ignoreErrors )
305 {
306 this.ignoreErrors = ignoreErrors;
307 }
308
309 public boolean runRunner() throws Exception
310 {
311 initGroovyLog();
312
313 assertions.clear();
314
315 String projectFile = getProjectFile();
316
317 WsdlProject project = ( WsdlProject )ProjectFactoryRegistry.getProjectFactory( "wsdl" ).createNew( projectFile,
318 getProjectPassword() );
319
320 if( project.isDisabled() )
321 throw new Exception( "Failed to load soapUI project file [" + projectFile + "]" );
322
323 initProject( project );
324 ensureOutputFolder( project );
325
326 log.info( "Running soapUI tests in project [" + project.getName() + "]" );
327
328 long startTime = System.nanoTime();
329
330 List<TestCase> testCasesToRun = new ArrayList<TestCase>();
331
332
333 if( testSuite != null && project.getTestSuiteByName( testSuite ) == null )
334 throw new Exception( "TestSuite with name [" + testSuite + "] is missing in Project [" + project.getName()
335 + "]" );
336
337
338
339 for( int c = 0; c < project.getTestSuiteCount(); c++ )
340 {
341 TestSuite suite = project.getTestSuiteAt( c );
342 for( int i = 0; i < suite.getTestCaseCount(); i++ )
343 {
344 TestCase tc = suite.getTestCaseAt( i );
345 if( ( testSuite == null || suite.getName().equals( suite.getName() ) ) && testCase != null
346 && tc.getName().equals( testCase ) )
347 testCasesToRun.add( tc );
348
349 addListeners( tc );
350 }
351 }
352
353 try
354 {
355
356 if( testCase != null && testCasesToRun.size() == 0 )
357 {
358 if( testSuite == null )
359 throw new Exception( "TestCase with name [" + testCase + "] is missing in Project [" + project.getName()
360 + "]" );
361 else
362 throw new Exception( "TestCase with name [" + testCase + "] in TestSuite [" + testSuite
363 + "] is missing in Project [" + project.getName() + "]" );
364 }
365
366
367 if( testCasesToRun.size() > 0 )
368 {
369 for( TestCase testCase : testCasesToRun )
370 runTestCase( ( WsdlTestCase )testCase );
371 }
372 else if( testSuite != null )
373 {
374 WsdlTestSuite ts = project.getTestSuiteByName( testSuite );
375 if( ts == null )
376 throw new Exception( "TestSuite with name [" + testSuite + "] not found in project" );
377 else
378 runSuite( ts );
379 }
380 else
381 {
382 runProject( project );
383 }
384
385 long timeTaken = ( System.nanoTime() - startTime ) / 1000000;
386
387 if( printReport )
388 {
389 printReport( timeTaken );
390 }
391
392 exportReports( project );
393
394 if( saveAfterRun && !project.isRemote() )
395 {
396 try
397 {
398 project.save();
399 }
400 catch( Throwable t )
401 {
402 log.error( "Failed to save project", t );
403 }
404 }
405
406 if( ( assertions.size() > 0 || failedTests.size() > 0 ) && !ignoreErrors )
407 {
408 throwFailureException();
409 }
410
411 return true;
412 }
413 finally
414 {
415 for( int c = 0; c < project.getTestSuiteCount(); c++ )
416 {
417 TestSuite suite = project.getTestSuiteAt( c );
418 for( int i = 0; i < suite.getTestCaseCount(); i++ )
419 {
420 TestCase tc = suite.getTestCaseAt( i );
421 removeListeners( tc );
422 }
423 }
424 }
425 }
426
427 protected void removeListeners( TestCase tc )
428 {
429 tc.removeTestRunListener( this );
430 if( junitReport )
431 tc.removeTestRunListener( reportCollector );
432 }
433
434 protected void runProject( WsdlProject project )
435 {
436
437 InternalProjectRunListener projectRunListener = new InternalProjectRunListener();
438 project.addProjectRunListener( projectRunListener );
439
440 try
441 {
442 log.info( ( "Running Project [" + project.getName() + "], runType = " + project.getRunType() ) );
443 WsdlProjectRunner runner = project.run( new StringToObjectMap(), false );
444 log.info( "Project [" + project.getName() + "] finished with status [" + runner.getStatus() + "] in "
445 + runner.getTimeTaken() + "ms" );
446 }
447 catch( Exception e )
448 {
449 e.printStackTrace();
450 }
451 finally
452 {
453 project.removeProjectRunListener( projectRunListener );
454 }
455 }
456
457 protected void initProject( WsdlProject project ) throws Exception
458 {
459 initProjectProperties( project );
460 }
461
462 protected void exportReports( WsdlProject project ) throws Exception
463 {
464 if( junitReport )
465 {
466 exportJUnitReports( reportCollector, getAbsoluteOutputFolder( project ), project );
467 }
468 }
469
470 protected void addListeners( TestCase tc )
471 {
472 tc.addTestRunListener( this );
473 if( junitReport )
474 tc.addTestRunListener( reportCollector );
475 }
476
477 protected void throwFailureException() throws Exception
478 {
479 StringBuffer buf = new StringBuffer();
480
481 for( int c = 0; c < assertions.size(); c++ )
482 {
483 TestAssertion assertion = assertions.get( c );
484 Assertable assertable = assertion.getAssertable();
485 if( assertable instanceof WsdlTestStep )
486 failedTests.remove( ( ( WsdlTestStep )assertable ).getTestCase() );
487
488 buf.append( assertion.getName() + " in [" + assertable.getModelItem().getName() + "] failed;\n" );
489 buf.append( Arrays.toString( assertion.getErrors() ) + "\n" );
490
491 WsdlTestStepResult result = assertionResults.get( assertion );
492 StringWriter stringWriter = new StringWriter();
493 PrintWriter writer = new PrintWriter( stringWriter );
494 result.writeTo( writer );
495 buf.append( stringWriter.toString() );
496 }
497
498 while( !failedTests.isEmpty() )
499 {
500 buf.append( "TestCase [" + failedTests.remove( 0 ).getName() + "] failed without assertions\n" );
501 }
502
503 throw new Exception( buf.toString() );
504 }
505
506 public void exportJUnitReports( JUnitReportCollector collector, String folder, WsdlProject project )
507 throws Exception
508 {
509 collector.saveReports( folder == null ? "" : folder );
510 }
511
512 public void printReport( long timeTaken )
513 {
514 System.out.println();
515 System.out.println( "SoapUI " + SoapUI.SOAPUI_VERSION + " TestCaseRunner Summary" );
516 System.out.println( "-----------------------------" );
517 System.out.println( "Time Taken: " + timeTaken + "ms" );
518 System.out.println( "Total TestSuites: " + testSuiteCount );
519 System.out.println( "Total TestCases: " + testCaseCount + " (" + failedTests.size() + " failed)" );
520 System.out.println( "Total TestSteps: " + testStepCount );
521 System.out.println( "Total Request Assertions: " + testAssertionCount );
522 System.out.println( "Total Failed Assertions: " + assertions.size() );
523 System.out.println( "Total Exported Results: " + exportCount );
524 }
525
526 /***
527 * Run tests in the specified TestSuite
528 *
529 * @param suite
530 * the TestSuite to run
531 */
532
533 protected void runSuite( WsdlTestSuite suite )
534 {
535 try
536 {
537 log.info( ( "Running TestSuite [" + suite.getName() + "], runType = " + suite.getRunType() ) );
538 WsdlTestSuiteRunner runner = suite.run( new StringToObjectMap(), false );
539 log.info( "TestSuite [" + suite.getName() + "] finished with status [" + runner.getStatus() + "] in "
540 + ( runner.getTimeTaken() ) + "ms" );
541 }
542 catch( Exception e )
543 {
544 e.printStackTrace();
545 }
546 finally
547 {
548 testSuiteCount++ ;
549 }
550 }
551
552 /***
553 * Runs the specified TestCase
554 *
555 * @param testCase
556 * the testcase to run
557 * @param context
558 */
559
560 protected void runTestCase( WsdlTestCase testCase )
561 {
562 try
563 {
564 log.info( "Running TestCase [" + testCase.getName() + "]" );
565 WsdlTestCaseRunner runner = testCase.run( new StringToObjectMap(), false );
566 log.info( "TestCase [" + testCase.getName() + "] finished with status [" + runner.getStatus() + "] in "
567 + ( runner.getTimeTaken() ) + "ms" );
568 }
569 catch( Exception e )
570 {
571 e.printStackTrace();
572 }
573 }
574
575 /***
576 * Sets the testcase to run
577 *
578 * @param testCase
579 * the testcase to run
580 */
581
582 public void setTestCase( String testCase )
583 {
584 this.testCase = testCase;
585 }
586
587 /***
588 * Sets the TestSuite to run. If not set all TestSuites in the specified
589 * project file are run
590 *
591 * @param testSuite
592 * the testSuite to run.
593 */
594
595 public void setTestSuite( String testSuite )
596 {
597 this.testSuite = testSuite;
598 }
599
600 public void beforeRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
601 {
602 log.info( "Running soapUI testcase [" + testRunner.getTestCase().getName() + "]" );
603 }
604
605 public void beforeStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStep currentStep )
606 {
607 super.beforeStep( testRunner, runContext, currentStep );
608
609 if( currentStep != null )
610 log.info( "running step [" + currentStep.getName() + "]" );
611 }
612
613 public void afterStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult result )
614 {
615 super.afterStep( testRunner, runContext, result );
616 TestStep currentStep = runContext.getCurrentStep();
617
618 if( currentStep instanceof Assertable )
619 {
620 Assertable requestStep = ( Assertable )currentStep;
621 for( int c = 0; c < requestStep.getAssertionCount(); c++ )
622 {
623 TestAssertion assertion = requestStep.getAssertionAt( c );
624 log.info( "Assertion [" + assertion.getName() + "] has status " + assertion.getStatus() );
625 if( assertion.getStatus() == AssertionStatus.FAILED )
626 {
627 for( AssertionError error : assertion.getErrors() )
628 log.error( "ASSERTION FAILED -> " + error.getMessage() );
629
630 assertions.add( assertion );
631 assertionResults.put( assertion, ( WsdlTestStepResult )result );
632 }
633
634 testAssertionCount++ ;
635 }
636 }
637
638 String countPropertyName = currentStep.getName() + " run count";
639 Long count = ( Long )runContext.getProperty( countPropertyName );
640 if( count == null )
641 {
642 count = new Long( 0 );
643 }
644
645 runContext.setProperty( countPropertyName, new Long( count.longValue() + 1 ) );
646
647 if( result.getStatus() == TestStepStatus.FAILED || exportAll )
648 {
649 try
650 {
651 String exportSeparator = System.getProperty( SOAPUI_EXPORT_SEPARATOR, "-" );
652
653 TestCase tc = currentStep.getTestCase();
654 String nameBase = StringUtils.createFileName( tc.getTestSuite().getName(), '_' ) + exportSeparator
655 + StringUtils.createFileName( tc.getName(), '_' ) + exportSeparator
656 + StringUtils.createFileName( currentStep.getName(), '_' ) + "-" + count.longValue() + "-"
657 + result.getStatus();
658
659 WsdlTestCaseRunner callingTestCaseRunner = ( WsdlTestCaseRunner )runContext
660 .getProperty( "#CallingTestCaseRunner#" );
661
662 if( callingTestCaseRunner != null )
663 {
664 WsdlTestCase ctc = callingTestCaseRunner.getTestCase();
665 WsdlRunTestCaseTestStep runTestCaseTestStep = ( WsdlRunTestCaseTestStep )runContext
666 .getProperty( "#CallingRunTestCaseStep#" );
667
668 nameBase = StringUtils.createFileName( ctc.getTestSuite().getName(), '_' ) + exportSeparator
669 + StringUtils.createFileName( ctc.getName(), '_' ) + exportSeparator
670 + StringUtils.createFileName( runTestCaseTestStep.getName(), '_' ) + exportSeparator
671 + StringUtils.createFileName( tc.getTestSuite().getName(), '_' ) + exportSeparator
672 + StringUtils.createFileName( tc.getName(), '_' ) + exportSeparator
673 + StringUtils.createFileName( currentStep.getName(), '_' ) + "-" + count.longValue() + "-"
674 + result.getStatus();
675 }
676
677 String absoluteOutputFolder = getAbsoluteOutputFolder( ModelSupport.getModelItemProject( tc ) );
678 String fileName = absoluteOutputFolder + File.separator + nameBase + ".txt";
679
680 if( result.getStatus() == TestStepStatus.FAILED )
681 log.error( currentStep.getName() + " failed, exporting to [" + fileName + "]" );
682
683 new File( fileName ).getParentFile().mkdirs();
684
685 PrintWriter writer = new PrintWriter( fileName );
686 result.writeTo( writer );
687 writer.close();
688
689
690 if( result instanceof MessageExchange )
691 {
692 Attachment[] attachments = ( ( MessageExchange )result ).getResponseAttachments();
693 if( attachments != null && attachments.length > 0 )
694 {
695 for( int c = 0; c < attachments.length; c++ )
696 {
697 fileName = nameBase + "-attachment-" + ( c + 1 ) + ".";
698
699 Attachment attachment = attachments[c];
700 String contentType = attachment.getContentType();
701 if( !"application/octet-stream".equals( contentType ) && contentType != null
702 && contentType.indexOf( '/' ) != -1 )
703 {
704 fileName += contentType.substring( contentType.lastIndexOf( '/' ) + 1 );
705 }
706 else
707 {
708 fileName += "dat";
709 }
710
711 fileName = absoluteOutputFolder + File.separator + fileName;
712
713 FileOutputStream outFile = new FileOutputStream( fileName );
714 Tools.writeAll( outFile, attachment.getInputStream() );
715 outFile.close();
716 }
717 }
718 }
719
720 exportCount++ ;
721 }
722 catch( Exception e )
723 {
724 log.error( "Error saving failed result: " + e, e );
725 }
726 }
727
728 testStepCount++ ;
729 }
730
731 public void afterRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
732 {
733 log.info( "Finished running soapUI testcase [" + testRunner.getTestCase().getName() + "], time taken: "
734 + testRunner.getTimeTaken() + "ms, status: " + testRunner.getStatus() );
735
736 if( testRunner.getStatus() == Status.FAILED )
737 {
738 failedTests.add( testRunner.getTestCase() );
739 }
740
741 testCaseCount++ ;
742 }
743
744 private class InternalProjectRunListener extends ProjectRunListenerAdapter
745 {
746 public void afterTestSuite( ProjectRunner projectRunner, ProjectRunContext runContext, TestSuiteRunner testRunner )
747 {
748 testSuiteCount++ ;
749 }
750 }
751 }