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