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