package org.jbehave.core.configuration; import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.lang.reflect.Type; import java.util.List; import org.hamcrest.Matchers; import org.jbehave.core.ConfigurableEmbedder; import org.jbehave.core.InjectableEmbedder; import org.jbehave.core.annotations.Configure; import org.jbehave.core.annotations.UsingEmbedder; import org.jbehave.core.annotations.UsingPaths; import org.jbehave.core.annotations.UsingSteps; import org.jbehave.core.configuration.AnnotationBuilder.InstantiationFailed; import org.jbehave.core.embedder.Embedder; import org.jbehave.core.embedder.EmbedderControls; import org.jbehave.core.i18n.LocalizedKeywords; import org.jbehave.core.steps.CandidateSteps; import org.jbehave.core.steps.ParameterConverters.ParameterConverter; import org.jbehave.core.steps.Steps; import org.jbehave.core.steps.scan.GivenOnly; import org.jbehave.core.steps.scan.GivenWhen; import org.jbehave.core.steps.scan.GivenWhenThen; import org.junit.Test; public class AnnotationBuilderBehaviour { @Test public void shouldReturnDependencies() { AnnotationBuilder annotated = new AnnotationBuilder(Annotated.class); assertThat(annotated.annotatedClass().getName(), equalTo(Annotated.class.getName())); assertThat(annotated.annotationFinder(), instanceOf(AnnotationFinder.class)); assertThat(annotated.annotationMonitor(), instanceOf(PrintStreamAnnotationMonitor.class)); } @Test public void shouldBuildDefaultEmbedderIfAnnotationNotPresent() { AnnotationBuilder notAnnotated = new AnnotationBuilder(NotAnnotated.class); assertThat(notAnnotated.buildEmbedder(), is(notNullValue())); } @Test public void shouldBuildEmbedderWithAnnotatedControls() { AnnotationBuilder annotated = new AnnotationBuilder(AnnotedEmbedderControls.class); EmbedderControls embedderControls = annotated.buildEmbedder().embedderControls(); assertThat(embedderControls.batch(), is(true)); assertThat(embedderControls.generateViewAfterStories(), is(true)); assertThat(embedderControls.ignoreFailureInStories(), is(true)); assertThat(embedderControls.ignoreFailureInView(), is(true)); assertThat(embedderControls.skip(), is(true)); assertThat(embedderControls.storyTimeouts(), equalTo("**/longs/*.story:60,**/shorts/*.story:10")); assertThat(embedderControls.failOnStoryTimeout(), is(true)); assertThat(embedderControls.threads(), equalTo(2)); assertThat(embedderControls.verboseFailures(), is(true)); assertThat(embedderControls.verboseFiltering(), is(true)); } @Test public void shouldBuildWithCustomConfiguration() { AnnotationBuilder annotated = new AnnotationBuilder(AnnotatedCustomConfiguration.class); assertThat(annotated.buildConfiguration(), instanceOf(MyConfiguration.class)); } @Test public void shouldBuildCandidateSteps() { AnnotationBuilder annotated = new AnnotationBuilder(Annotated.class); assertThatStepsInstancesAre(annotated.buildCandidateSteps(), MySteps.class, MyOtherSteps.class); } @Test public void shouldBuildCandidateStepsAsEmptyListIfAnnotationOrAnnotatedValuesNotPresent() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); AnnotationBuilder notAnnotated = new AnnotationBuilder(NotAnnotated.class, new PrintStreamAnnotationMonitor( new PrintStream(baos))); assertThatStepsInstancesAre(notAnnotated.buildCandidateSteps()); AnnotationBuilder annotatedWithoutSteps = new AnnotationBuilder(AnnotatedWithoutSteps.class); assertThatStepsInstancesAre(annotatedWithoutSteps.buildCandidateSteps()); assertThat(baos.toString().trim(), is(equalTo("Annotation " + UsingSteps.class + " not found in " + NotAnnotated.class))); } @Test public void shouldInheritStepsInstances() { AnnotationBuilder annotated = new AnnotationBuilder(AnnotatedInheriting.class); assertThatStepsInstancesAre(annotated.buildCandidateSteps(), MyOtherOtherSteps.class, MySteps.class, MyOtherSteps.class); } @Test public void shouldNotInheritStepsInstances() { AnnotationBuilder builderAnnotated = new AnnotationBuilder(AnnotatedNotInheriting.class); assertThatStepsInstancesAre(builderAnnotated.buildCandidateSteps(), MyOtherOtherSteps.class); } @Test public void shouldNotIgnoreFailingStepsInstances() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); AnnotationBuilder annotatedFailing = new AnnotationBuilder(AnnotatedFailing.class, new PrintStreamAnnotationMonitor(new PrintStream(baos))); try { assertThatStepsInstancesAre(annotatedFailing.buildCandidateSteps(), MySteps.class); fail("Exception was not thrown"); } catch (RuntimeException e) { assertThat(baos.toString(), containsString("Element creation failed")); assertThat(baos.toString(), containsString("RuntimeException")); } } private void assertThatStepsInstancesAre(List<CandidateSteps> candidateSteps, Class<?>... stepsClasses) { for (Class<?> stepsClass : stepsClasses) { boolean found = false; for (CandidateSteps steps : candidateSteps) { Object instance = ((Steps) steps).instance(); if (instance.getClass() == stepsClass) { found = true; } } assertThat(found, is(true)); } } @Test public void shouldCreateEmbeddableInstanceFromInjectableEmbedder() { AnnotationBuilder annotatedInjectable = new AnnotationBuilder(AnnotedInjectable.class); Object instance = annotatedInjectable.embeddableInstance(); assertThat(instance, Matchers.instanceOf(InjectableEmbedder.class)); Embedder embedder = ((InjectableEmbedder) instance).injectedEmbedder(); assertThat(embedder.configuration().keywords(), instanceOf(MyKeywords.class)); assertThat(embedder.metaFilters(), equalTo(asList("+embedder injectable"))); assertThat(embedder.systemProperties().getProperty("one"), equalTo("One")); assertThat(embedder.systemProperties().getProperty("two"), equalTo("Two")); assertThatStepsInstancesAre(embedder.stepsFactory().createCandidateSteps(), MySteps.class); } @Test public void shouldCreateEmbeddableInstanceFromInjectableEmbedderWithoutStepsFactory() { AnnotationBuilder annotatedInjectable = new AnnotationBuilder(AnnotedInjectableWithoutStepsFactory.class); Object instance = annotatedInjectable.embeddableInstance(); assertThat(instance, Matchers.instanceOf(InjectableEmbedder.class)); Embedder embedder = ((InjectableEmbedder) instance).injectedEmbedder(); assertThat(embedder.configuration().keywords(), instanceOf(MyKeywords.class)); assertThat(embedder.metaFilters(), equalTo(asList("+embedder injectable"))); assertThatStepsInstancesAre(embedder.candidateSteps(), MySteps.class); } @Test public void shouldCreateEmbeddableInstanceFromConfigurableEmbedder() { AnnotationBuilder annotatedConfigurable = new AnnotationBuilder(AnnotedConfigurable.class); Object instance = annotatedConfigurable.embeddableInstance(); assertThat(instance, Matchers.instanceOf(ConfigurableEmbedder.class)); Embedder embedder = ((ConfigurableEmbedder) instance).configuredEmbedder(); assertThat(embedder.configuration().keywords(), instanceOf(MyKeywords.class)); assertThat(embedder.metaFilters(), equalTo(asList("+embedder configurable"))); assertThatStepsInstancesAre(embedder.stepsFactory().createCandidateSteps(), MySteps.class); } @Test public void shouldCreateEmbeddableInstanceFromConfigurableEmbedderWithoutStepsFactory() { AnnotationBuilder annotatedConfigurable = new AnnotationBuilder(AnnotedConfigurableWithoutStepsFactory.class); Object instance = annotatedConfigurable.embeddableInstance(); assertThat(instance, Matchers.instanceOf(ConfigurableEmbedder.class)); Embedder embedder = ((ConfigurableEmbedder) instance).configuredEmbedder(); assertThat(embedder.configuration().keywords(), instanceOf(MyKeywords.class)); assertThat(embedder.metaFilters(), equalTo(asList("+embedder configurable"))); assertThatStepsInstancesAre(embedder.candidateSteps(), MySteps.class); } @Test public void shouldFindStoryPaths() { assertThat(new AnnotationBuilder(AnnotatedWithPaths.class).findPaths().size(), greaterThan(0)); assertThat(new AnnotationBuilder(AnnotedConfigurable.class).findPaths().size(), equalTo(0)); } @Test public void shouldNotCreateEmbeddableInstanceForAnnotatedClassThatIsNotInstantiable() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); AnnotationBuilder annotatedPrivate = new AnnotationBuilder(AnnotatedPrivate.class, new PrintStreamAnnotationMonitor(new PrintStream(baos))); try { annotatedPrivate.embeddableInstance(); fail("Exception was not thrown"); } catch (InstantiationFailed e) { assertThat(baos.toString(), containsString("Element creation failed")); assertThat(baos.toString(), containsString("IllegalAccessException")); } } @Test public void shouldBuildCandidateStepsFromPackages() { AnnotationBuilder annotatedWithPackages = new AnnotationBuilder(AnnotatedWithPackages.class); List<CandidateSteps> candidateSteps = annotatedWithPackages.buildCandidateSteps(); assertThatStepsInstancesAre(candidateSteps, GivenOnly.class, GivenWhen.class, GivenWhenThen.class); } @Configure(parameterConverters = { MyParameterConverter.class }) @UsingSteps(instances = { MySteps.class, MyOtherSteps.class }) static class Annotated { } static class MyParameterConverter implements ParameterConverter { public boolean accept(Type type) { return true; } public Object convertValue(String value, Type type) { return value + "Converted"; } } @UsingSteps(instances = { MyOtherOtherSteps.class }) static class AnnotatedInheriting extends Annotated { } @UsingSteps(instances = { MyOtherOtherSteps.class }, inheritInstances = false) static class AnnotatedNotInheriting extends Annotated { } @UsingSteps(instances = { MySteps.class, MyFailingSteps.class }) static class AnnotatedFailing { } @UsingSteps() static class AnnotatedWithoutSteps { } @Configure @UsingSteps(packages = { "org.jbehave.core.steps.scan" }) static class AnnotatedWithPackages { } static class NotAnnotated { } static class MySteps { } static class MyOtherSteps { } static class MyOtherOtherSteps { } static class MyFailingSteps { public MyFailingSteps() { throw new RuntimeException(); } } @Configure(using = MyConfiguration.class) static class AnnotatedCustomConfiguration extends InjectableEmbedder { public void run() throws Throwable { } } static class MyConfiguration extends Configuration { } @UsingEmbedder(batch = true, generateViewAfterStories = true, ignoreFailureInStories = true, ignoreFailureInView = true, skip = true, verboseFailures = true, verboseFiltering = true, storyTimeouts = "**/longs/*.story:60,**/shorts/*.story:10", failOnStoryTimeout = true, threads = 2) @UsingSteps(instances = { MySteps.class }) static class AnnotedEmbedderControls extends InjectableEmbedder { public void run() throws Throwable { } } @Configure(keywords = MyKeywords.class) @UsingEmbedder(metaFilters = "+embedder injectable", systemProperties = "one=One,two=Two") @UsingSteps(instances = { MySteps.class }) static class AnnotedInjectable extends InjectableEmbedder { public void run() throws Throwable { } } @Configure(keywords = MyKeywords.class) @UsingEmbedder(metaFilters = "+embedder injectable", stepsFactory = false) @UsingSteps(instances = { MySteps.class }) static class AnnotedInjectableWithoutStepsFactory extends InjectableEmbedder { public void run() throws Throwable { } } @Configure(keywords = MyKeywords.class) @UsingEmbedder(metaFilters = "+embedder configurable") @UsingSteps(instances = { MySteps.class }) static class AnnotedConfigurable extends ConfigurableEmbedder { public void run() throws Throwable { } } @Configure(keywords = MyKeywords.class) @UsingEmbedder(metaFilters = "+embedder configurable", stepsFactory = false) @UsingSteps(instances = { MySteps.class }) static class AnnotedConfigurableWithoutStepsFactory extends ConfigurableEmbedder { public void run() throws Throwable { } } static class MyKeywords extends LocalizedKeywords { } @Configure() @UsingEmbedder() @UsingSteps(instances = { MySteps.class }) private static class AnnotatedPrivate extends ConfigurableEmbedder { public void run() throws Throwable { } } @UsingPaths(searchIn = "src/test/java", includes = { "**/stories/*story" }) private static class AnnotatedWithPaths { } }