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