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