Coverage Report - org.jbehave.ant.AbstractEmbedderTask
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractEmbedderTask
92%
112/121
72%
13/18
1.284
AbstractEmbedderTask$AntEmbedderMonitor
40%
28/70
12%
1/8
1.284
 
 1  
 package org.jbehave.ant;
 2  
 
 3  
 import java.io.File;
 4  
 import java.io.IOException;
 5  
 import java.net.MalformedURLException;
 6  
 import java.net.URL;
 7  
 import java.util.ArrayList;
 8  
 import java.util.List;
 9  
 import java.util.Properties;
 10  
 import java.util.concurrent.ExecutorService;
 11  
 
 12  
 import org.apache.tools.ant.Task;
 13  
 import org.apache.tools.ant.filters.StringInputStream;
 14  
 import org.jbehave.core.ConfigurableEmbedder;
 15  
 import org.jbehave.core.InjectableEmbedder;
 16  
 import org.jbehave.core.embedder.Embedder;
 17  
 import org.jbehave.core.embedder.EmbedderClassLoader;
 18  
 import org.jbehave.core.embedder.EmbedderControls;
 19  
 import org.jbehave.core.embedder.EmbedderMonitor;
 20  
 import org.jbehave.core.embedder.MetaFilter;
 21  
 import org.jbehave.core.embedder.NullEmbedderMonitor;
 22  
 import org.jbehave.core.embedder.UnmodifiableEmbedderControls;
 23  
 import org.jbehave.core.embedder.executors.ExecutorServiceFactory;
 24  
 import org.jbehave.core.failures.BatchFailures;
 25  
 import org.jbehave.core.io.StoryFinder;
 26  
 import org.jbehave.core.junit.AnnotatedEmbedderRunner;
 27  
 import org.jbehave.core.model.Meta;
 28  
 import org.jbehave.core.model.Story;
 29  
 import org.jbehave.core.model.StoryDuration;
 30  
 import org.jbehave.core.model.StoryMaps;
 31  
 import org.jbehave.core.reporters.ReportsCount;
 32  
 
 33  
 import static java.util.Arrays.asList;
 34  
 import static org.apache.tools.ant.Project.MSG_DEBUG;
 35  
 import static org.apache.tools.ant.Project.MSG_INFO;
 36  
 import static org.apache.tools.ant.Project.MSG_WARN;
 37  
 
 38  
 /**
 39  
  * Abstract task that holds all the configuration parameters to specify and load
 40  
  * stories.
 41  
  * 
 42  
  * @author Mauro Talevi
 43  
  */
 44  16
 public abstract class AbstractEmbedderTask extends Task {
 45  
 
 46  
     private static final String TEST_SCOPE = "test";
 47  
 
 48  16
     private String sourceDirectory = "src/main/java";
 49  
 
 50  16
     private String testSourceDirectory = "src/test/java";
 51  
 
 52  16
     private String outputDirectory = "target/classes";
 53  
 
 54  16
     private String testOutputDirectory = "target/test-classes";
 55  
 
 56  
     /**
 57  
      * The scope of the source, either "compile" or "test"
 58  
      */
 59  16
     private String scope = "compile";
 60  
 
 61  
     /**
 62  
      * Include filters, relative to the root source directory determined by the
 63  
      * scope
 64  
      */
 65  16
     private List<String> includes = new ArrayList<String>();
 66  
 
 67  
     /**
 68  
      * Exclude filters, relative to the root source directory determined by the
 69  
      * scope
 70  
      */
 71  16
     private List<String> excludes = new ArrayList<String>();
 72  
 
 73  
     /**
 74  
      * The boolean flag to skip running stories
 75  
      */
 76  16
     private boolean skip = false;
 77  
 
 78  
     /**
 79  
      * The boolean flag to ignore failure in stories
 80  
      */
 81  16
     private boolean ignoreFailureInStories = false;
 82  
 
 83  
     /**
 84  
      * The boolean flag to ignore failure in view
 85  
      */
 86  16
     private boolean ignoreFailureInView = false;
 87  
 
 88  
     /**
 89  
      * The boolean flag to generate view after stories
 90  
      */
 91  16
     private boolean generateViewAfterStories = true;
 92  
 
 93  
     /**
 94  
      * The boolean flag to run in batch mode
 95  
      */
 96  16
     private boolean batch = false;
 97  
 
 98  
     /**
 99  
      * The boolean flag to output failures in verbose mode
 100  
      */
 101  16
     private boolean verboseFailures = false;
 102  
 
 103  
     /**
 104  
      * The boolean flag to output filtering in verbose mode
 105  
      */
 106  16
     private boolean verboseFiltering = false;
 107  
 
 108  
     /**
 109  
      * The story timeout in secs
 110  
      */
 111  16
     long storyTimeoutInSecs = 300;
 112  
 
 113  
     /**
 114  
      * The boolean flag to fail on story timeout
 115  
      */
 116  16
     private boolean failOnStoryTimeout = false;
 117  
 
 118  
     /**
 119  
      * The number of threads
 120  
      */
 121  16
     private int threads = 1;
 122  
 
 123  
     /**
 124  
      * The embedder to run the stories
 125  
      */
 126  16
     private String embedderClass = Embedder.class.getName();
 127  
 
 128  
     /**
 129  
      * The implementation class of the {@link ExecutorServiceFactory}
 130  
      */
 131  
     private String executorsClass;
 132  
 
 133  
     /**
 134  
      * The class that is injected to provide embedder to run the stories.
 135  
      */
 136  
     private String injectableEmbedderClass;
 137  
 
 138  
     /**
 139  
      * The annotated embedder runner class to run the stories
 140  
      * 
 141  
      * @deprecated Obsolete
 142  
      */
 143  16
     String annotatedEmbedderRunnerClass = AnnotatedEmbedderRunner.class.getName();
 144  
 
 145  
     /**
 146  
      * Used to find story paths and class names
 147  
      */
 148  16
     private String storyFinderClass = StoryFinder.class.getName();
 149  
 
 150  
     /**
 151  
      * The meta filters
 152  
      */
 153  16
     private List<String> metaFilters = asList();
 154  
 
 155  
     /**
 156  
      * The system properties
 157  
      */
 158  16
     private Properties systemProperties = new Properties();
 159  
 
 160  
     /**
 161  
      * The classloader
 162  
      */
 163  
     private EmbedderClassLoader classLoader;
 164  
 
 165  
     /**
 166  
      * Determines if the scope of the source directory is "test"
 167  
      * 
 168  
      * @return A boolean <code>true</code> if test scoped
 169  
      */
 170  
     boolean isTestScope() {
 171  14
         return TEST_SCOPE.equals(scope);
 172  
     }
 173  
 
 174  
     String searchDirectory() {
 175  6
         if (isTestScope()) {
 176  1
             return testSourceDirectory;
 177  
         }
 178  5
         return sourceDirectory;
 179  
     }
 180  
 
 181  
     String outputDirectory() {
 182  8
         if (isTestScope()) {
 183  0
             return testOutputDirectory;
 184  
         }
 185  8
         return outputDirectory;
 186  
     }
 187  
 
 188  
     URL codeLocation() {
 189  8
         String outputDirectory = outputDirectory();
 190  
         try {
 191  8
             return outputDirectory != null ? new File(outputDirectory).toURI().toURL() : null;
 192  0
         } catch (MalformedURLException e) {
 193  0
             throw new IllegalArgumentException("Failed to create code location from " + outputDirectory, e);
 194  
         }
 195  
     }
 196  
 
 197  
     /**
 198  
      * Creates the EmbedderClassLoader with the classpath element of the
 199  
      * selected scope
 200  
      * 
 201  
      * @return A EmbedderClassLoader
 202  
      */
 203  
     protected EmbedderClassLoader classLoader() {
 204  8
         if (classLoader == null) {
 205  8
             classLoader = new EmbedderClassLoader(this.getClass().getClassLoader());
 206  
         }
 207  8
         return classLoader;
 208  
     }
 209  
 
 210  
     protected EmbedderMonitor embedderMonitor() {
 211  7
         return new AntEmbedderMonitor();
 212  
     }
 213  
 
 214  
     protected EmbedderControls embedderControls() {
 215  7
         return new UnmodifiableEmbedderControls(new EmbedderControls().doBatch(batch).doSkip(skip)
 216  
                 .doGenerateViewAfterStories(generateViewAfterStories).doIgnoreFailureInStories(ignoreFailureInStories)
 217  
                 .doIgnoreFailureInView(ignoreFailureInView).doVerboseFailures(verboseFailures)
 218  
                 .doVerboseFiltering(verboseFiltering).useStoryTimeoutInSecs(storyTimeoutInSecs)
 219  
                 .doFailOnStoryTimeout(failOnStoryTimeout).useThreads(threads));
 220  
     }
 221  
 
 222  
     /**
 223  
      * Finds story paths, using the {@link #newStoryFinder()}, in the
 224  
      * {@link #searchDirectory()} given specified {@link #includes} and
 225  
      * {@link #excludes}.
 226  
      * 
 227  
      * @return A List of story paths found
 228  
      */
 229  
     protected List<String> storyPaths() {
 230  2
         log("Searching for story paths including " + includes + " and excluding " + excludes, MSG_DEBUG);
 231  2
         List<String> storyPaths = newStoryFinder().findPaths(searchDirectory(), includes, excludes);
 232  2
         log("Found story paths: " + storyPaths, MSG_INFO);
 233  2
         return storyPaths;
 234  
     }
 235  
 
 236  
     /**
 237  
      * Finds class names, using the {@link #newStoryFinder()}, in the
 238  
      * {@link #searchDirectory()} given specified {@link #includes} and
 239  
      * {@link #excludes}.
 240  
      * 
 241  
      * @return A List of class names found
 242  
      */
 243  
     protected List<String> classNames() {
 244  3
         log("Searching for class names including " + includes + " and excluding " + excludes, MSG_DEBUG);
 245  3
         List<String> classNames = newStoryFinder().findClassNames(searchDirectory(), includes, excludes);
 246  3
         log("Found class names : " + classNames, MSG_INFO);
 247  3
         return classNames;
 248  
     }
 249  
 
 250  
     /**
 251  
      * Creates an instance of StoryFinder, using the {@link #storyFinderClass}
 252  
      * 
 253  
      * @return A StoryFinder
 254  
      */
 255  
     protected StoryFinder newStoryFinder() {
 256  6
         return classLoader().newInstance(StoryFinder.class, storyFinderClass);
 257  
     }
 258  
 
 259  
     /**
 260  
      * Creates an instance of Embedder, either using
 261  
      * {@link #injectableEmbedderClass} (if set) or defaulting to
 262  
      * {@link #embedderClass}.
 263  
      * 
 264  
      * @return An Embedder
 265  
      */
 266  
     protected Embedder newEmbedder() {
 267  7
         Embedder embedder = null;
 268  7
         EmbedderClassLoader classLoader = classLoader();
 269  7
         if (injectableEmbedderClass != null) {
 270  1
             embedder = classLoader.newInstance(InjectableEmbedder.class, injectableEmbedderClass).injectedEmbedder();
 271  
         } else {
 272  6
             embedder = classLoader.newInstance(Embedder.class, embedderClass);
 273  
         }
 274  
 
 275  7
         URL codeLocation = codeLocation();
 276  7
         if (codeLocation != null) {
 277  7
             embedder.configuration().storyReporterBuilder().withCodeLocation(codeLocation);
 278  
         }
 279  
 
 280  7
         embedder.useClassLoader(classLoader);
 281  7
         embedder.useEmbedderControls(embedderControls());
 282  7
         if (executorsClass != null) {
 283  1
             ExecutorServiceFactory executorServiceFactory = classLoader.newInstance(ExecutorServiceFactory.class,
 284  
                     executorsClass);
 285  1
             embedder.useExecutorService(executorServiceFactory.create(embedder.embedderControls()));
 286  
         }
 287  7
         embedder.useEmbedderMonitor(embedderMonitor());
 288  7
         if (!metaFilters.isEmpty()) {
 289  0
             embedder.useMetaFilters(metaFilters);
 290  
         }
 291  7
         if (!systemProperties.isEmpty()) {
 292  1
             embedder.useSystemProperties(systemProperties);
 293  
         }
 294  7
         return embedder;
 295  
     }
 296  
 
 297  7
     protected class AntEmbedderMonitor extends NullEmbedderMonitor {
 298  
         public void batchFailed(BatchFailures failures) {
 299  1
             log("Failed to run batch " + failures, MSG_WARN);
 300  1
         }
 301  
 
 302  
         public void beforeOrAfterStoriesFailed() {
 303  0
             log("Failed to run before or after stories steps", MSG_WARN);
 304  0
         }
 305  
 
 306  
         public void embeddableFailed(String name, Throwable cause) {
 307  1
             log("Failed to run embeddable " + name, cause, MSG_WARN);
 308  1
         }
 309  
 
 310  
         public void embeddableNotConfigurable(String name) {
 311  0
             log("Embeddable " + name + " must be an instance of " + ConfigurableEmbedder.class, MSG_WARN);
 312  0
         }
 313  
 
 314  
         public void embeddablesSkipped(List<String> classNames) {
 315  1
             log("Skipped embeddables " + classNames, MSG_INFO);
 316  1
         }
 317  
 
 318  
         public void metaNotAllowed(Meta meta, MetaFilter filter) {
 319  0
             log(meta + " excluded by filter '" + filter.asString() + "'", MSG_DEBUG);
 320  0
         }
 321  
 
 322  
         public void runningEmbeddable(String name) {
 323  1
             log("Running embeddable " + name, MSG_INFO);
 324  1
         }
 325  
 
 326  
         public void storyFailed(String path, Throwable cause) {
 327  1
             log("Failed to run story " + path, cause, MSG_WARN);
 328  1
         }
 329  
 
 330  
         public void storiesSkipped(List<String> storyPaths) {
 331  1
             log("Skipped stories " + storyPaths, MSG_INFO);
 332  1
         }
 333  
 
 334  
         public void storiesNotAllowed(List<Story> stories, MetaFilter filter, boolean verbose) {
 335  0
             StringBuffer sb = new StringBuffer();
 336  0
             sb.append(stories.size() + " stories excluded by filter: " + filter.asString() + "\n");
 337  0
             if (verbose) {
 338  0
                 for (Story story : stories) {
 339  0
                     sb.append(story.getPath()).append("\n");
 340  0
                 }
 341  
             }
 342  0
             log(sb.toString(), MSG_INFO);
 343  0
         }
 344  
 
 345  
         public void runningStory(String path) {
 346  1
             log("Running story " + path, MSG_INFO);
 347  1
         }
 348  
 
 349  
         public void runningWithAnnotatedEmbedderRunner(String className) {
 350  0
             log("Running with AnnotatedEmbedderRunner '" + className + "'", MSG_INFO);
 351  0
         }
 352  
 
 353  
         public void annotatedInstanceNotOfType(Object annotatedInstance, Class<?> type) {
 354  1
             log("Annotated instance " + annotatedInstance + " not of type " + type, MSG_WARN);
 355  1
         }
 356  
 
 357  
         public void generatingReportsView(File outputDirectory, List<String> formats, Properties viewProperties) {
 358  1
             log("Generating reports view to '" + outputDirectory + "' using formats '" + formats + "'"
 359  
                     + " and view properties '" + viewProperties + "'", MSG_INFO);
 360  1
         }
 361  
 
 362  
         public void reportsViewGenerationFailed(File outputDirectory, List<String> formats, Properties viewProperties,
 363  
                 Throwable cause) {
 364  1
             log("Failed to generate reports view to '" + outputDirectory + "' using formats '" + formats + "'"
 365  
                     + " and view properties '" + viewProperties + "'", cause, MSG_WARN);
 366  1
         }
 367  
 
 368  
         public void reportsViewGenerated(ReportsCount count) {
 369  1
             log("Reports view generated with " + count.getStories() + " stories (of which " + count.getStoriesPending()
 370  
                     + " pending) containing " + count.getScenarios() + " scenarios (of which "
 371  
                     + count.getScenariosPending() + " pending)", MSG_INFO);
 372  1
             if (count.getStoriesNotAllowed() > 0 || count.getScenariosNotAllowed() > 0) {
 373  1
                 log("Meta filters excluded " + count.getStoriesNotAllowed() + " stories and  "
 374  
                         + count.getScenariosNotAllowed() + " scenarios", MSG_INFO);
 375  
             }
 376  1
         }
 377  
 
 378  
         public void reportsViewFailures(ReportsCount count) {
 379  0
             log("Failures in reports view: " + count.getScenariosFailed() + " scenarios failed", MSG_WARN);
 380  0
         }
 381  
 
 382  
         public void reportsViewNotGenerated() {
 383  1
             log("Reports view not generated", MSG_INFO);
 384  1
         }
 385  
 
 386  
         public void mappingStory(String storyPath, List<String> metaFilters) {
 387  0
             log("Mapping story " + storyPath + " with meta filters " + metaFilters, MSG_INFO);
 388  0
         }
 389  
 
 390  
         public void generatingMapsView(File outputDirectory, StoryMaps storyMaps, Properties viewProperties) {
 391  0
             log("Generating maps view to '" + outputDirectory + "' using story maps '" + storyMaps + "'"
 392  
                     + " and view properties '" + viewProperties + "'", MSG_INFO);
 393  0
         }
 394  
 
 395  
         public void mapsViewGenerationFailed(File outputDirectory, StoryMaps storyMaps, Properties viewProperties,
 396  
                 Throwable cause) {
 397  0
             log("Failed to generate maps view to '" + outputDirectory + "' using story maps '" + storyMaps + "'"
 398  
                     + " and view properties '" + viewProperties + "'", cause, MSG_WARN);
 399  0
         }
 400  
 
 401  
         public void generatingNavigatorView(File outputDirectory, Properties viewProperties) {
 402  0
             log("Generating navigator view to '" + outputDirectory + "' using  properties '" + viewProperties + "'",
 403  
                     MSG_INFO);
 404  0
         }
 405  
 
 406  
         public void navigatorViewGenerationFailed(File outputDirectory, Properties viewProperties, Throwable cause) {
 407  0
             log("Failed to generating navigator view to '" + outputDirectory + "' using  properties '" + viewProperties
 408  
                     + "'", cause, MSG_WARN);
 409  0
         }
 410  
 
 411  
         public void navigatorViewNotGenerated() {
 412  0
             log("Navigator view not generated, as the CrossReference has not been declared in the StoryReporterBuilder",
 413  
                     MSG_WARN);
 414  0
         }
 415  
 
 416  
         public void processingSystemProperties(Properties properties) {
 417  0
             log("Processing system properties " + properties, MSG_INFO);
 418  0
         }
 419  
 
 420  
         public void systemPropertySet(String name, String value) {
 421  0
             log("System property '" + name + "' set to '" + value + "'", MSG_INFO);
 422  0
         }
 423  
 
 424  
         public void storyTimeout(Story story, StoryDuration storyDuration) {
 425  0
             log("Story " + story.getPath() + " duration of " + storyDuration.getDurationInSecs()
 426  
                     + " seconds has exceeded timeout of " + storyDuration.getTimeoutInSecs() + " seconds", MSG_INFO);
 427  0
         }
 428  
 
 429  
         public void usingThreads(int threads) {
 430  0
             log("Using " + threads + " threads", MSG_INFO);
 431  0
         }
 432  
 
 433  
         public void usingExecutorService(ExecutorService executorService) {
 434  0
             log("Using executor service " + executorService, MSG_INFO);
 435  0
         }
 436  
 
 437  
         public void usingControls(EmbedderControls embedderControls) {
 438  0
             log("Using controls " + embedderControls, MSG_INFO);
 439  0
         }
 440  
 
 441  
         @Override
 442  
         public String toString() {
 443  1
             return this.getClass().getSimpleName();
 444  
         }
 445  
 
 446  
     }
 447  
 
 448  
     // Setters used by Task to inject dependencies
 449  
 
 450  
     public void setSourceDirectory(String sourceDirectory) {
 451  5
         this.sourceDirectory = sourceDirectory;
 452  5
     }
 453  
 
 454  
     public void setTestSourceDirectory(String testSourceDirectory) {
 455  1
         this.testSourceDirectory = testSourceDirectory;
 456  1
     }
 457  
 
 458  
     public void setOutputDirectory(String outputDirectory) {
 459  2
         this.outputDirectory = outputDirectory;
 460  2
     }
 461  
 
 462  
     public void setTestOutputDirectory(String testOutputDirectory) {
 463  1
         this.testOutputDirectory = testOutputDirectory;
 464  1
     }
 465  
 
 466  
     public void setScope(String scope) {
 467  1
         this.scope = scope;
 468  1
     }
 469  
 
 470  
     public void setIncludes(String includesCSV) {
 471  5
         this.includes = asList(includesCSV.split(","));
 472  5
     }
 473  
 
 474  
     public void setExcludes(String excludesCSV) {
 475  5
         this.excludes = asList(excludesCSV.split(","));
 476  5
     }
 477  
 
 478  
     public void setBatch(boolean batch) {
 479  1
         this.batch = batch;
 480  1
     }
 481  
 
 482  
     public void setSkip(boolean skip) {
 483  1
         this.skip = skip;
 484  1
     }
 485  
 
 486  
     public void setIgnoreFailureInStories(boolean ignoreFailureInStories) {
 487  1
         this.ignoreFailureInStories = ignoreFailureInStories;
 488  1
     }
 489  
 
 490  
     public void setIgnoreFailureInView(boolean ignoreFailureInView) {
 491  1
         this.ignoreFailureInView = ignoreFailureInView;
 492  1
     }
 493  
 
 494  
     public void setGenerateViewAfterStories(boolean generateViewAfterStories) {
 495  1
         this.generateViewAfterStories = generateViewAfterStories;
 496  1
     }
 497  
 
 498  
     public void setVerboseFailures(boolean verboseFailures) {
 499  1
         this.verboseFailures = verboseFailures;
 500  1
     }
 501  
 
 502  
     public void setVerboseFiltering(boolean verboseFiltering) {
 503  1
         this.verboseFiltering = verboseFiltering;
 504  1
     }
 505  
 
 506  
     public void setStoryTimeoutInSecs(long storyTimeoutInSecs) {
 507  1
         this.storyTimeoutInSecs = storyTimeoutInSecs;
 508  1
     }
 509  
 
 510  
         public void setFailOnStoryTimeout(boolean failOnStoryTimeout) {
 511  1
                 this.failOnStoryTimeout = failOnStoryTimeout;
 512  1
         }
 513  
         
 514  
     public void setThreads(int threads) {
 515  1
         this.threads = threads;
 516  1
     }
 517  
 
 518  
     public void setEmbedderClass(String embedderClass) {
 519  1
         this.embedderClass = embedderClass;
 520  1
     }
 521  
 
 522  
     public void setExecutorsClass(String executorsClass) {
 523  1
         this.executorsClass = executorsClass;
 524  1
     }
 525  
 
 526  
     public void setInjectableEmbedderClass(String injectableEmbedderClass) {
 527  1
         this.injectableEmbedderClass = injectableEmbedderClass;
 528  1
     }
 529  
 
 530  
     public void setAnnotatedEmbedderRunnerClass(String annotatedEmbedderRunnerClass) {
 531  0
         this.annotatedEmbedderRunnerClass = annotatedEmbedderRunnerClass;
 532  0
     }
 533  
 
 534  
     public void setStoryFinderClass(String storyFinderClass) {
 535  1
         this.storyFinderClass = storyFinderClass;
 536  1
     }
 537  
 
 538  
     public void setMetaFilters(String metaFiltersCSV) {
 539  0
         this.metaFilters = asList(metaFiltersCSV.split(","));
 540  0
     }
 541  
 
 542  
     public void setSystemProperties(String systemPropertiesCSV) {
 543  1
         this.systemProperties = loadProperties(systemPropertiesCSV);
 544  1
     }
 545  
 
 546  
     private Properties loadProperties(String systemPropertiesCSV) {
 547  1
         Properties properties = new Properties();
 548  
         try {
 549  1
             properties.load(new StringInputStream(systemPropertiesCSV.replace(",", "\n")));
 550  0
         } catch (IOException e) {
 551  
             // return empty map
 552  1
         }
 553  1
         return properties;
 554  
     }
 555  
 
 556  
 }