From 6762f16fada850f610611c7d3088d4dc5dd441fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Mon, 27 Jun 2011 23:25:17 +0100 Subject: [PATCH] Our first cucumber-features scenario is passing. --- .gitignore | 2 + .gitmodules | 3 + .rvmrc | 1 + Gemfile | 4 + Gemfile.lock | 43 ++++++++ Rakefile | 7 ++ .../main/java/cucumber/junit/Cucumber.java | 9 +- .../src/main/java/cucumber/junit/Feature.java | 12 ++ .../java/cucumber/junit/RunnerBuilder.java | 7 +- .../main/java/cucumber/runtime/Runtime.java | 4 +- cucumber-features | 1 + .../cucumber_java_mappings.rb | 104 ++++++++++++++++++ ..._runner.java => cucumber_runner_Test.java} | 7 +- .../junit => }/cucumber_runner.feature | 0 14 files changed, 195 insertions(+), 9 deletions(-) create mode 100644 .gitmodules create mode 100644 .rvmrc create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 Rakefile create mode 100644 core/src/main/java/cucumber/junit/Feature.java create mode 160000 cucumber-features create mode 100644 java/src/test/resources/cucumber-features/cucumber_java_mappings.rb rename picocontainer/src/test/java/cucumber/runtime/junit/{cucumber_runner.java => cucumber_runner_Test.java} (61%) rename picocontainer/src/test/resources/{cucumber/runtime/junit => }/cucumber_runner.feature (100%) diff --git a/.gitignore b/.gitignore index 83573ee09a..23dde485aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ target *.ipr *.iws +tmp/ +doc/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..98464175e9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "cucumber-features"] + path = cucumber-features + url = git://github.com/cucumber/cucumber-features.git diff --git a/.rvmrc b/.rvmrc new file mode 100644 index 0000000000..92a100e317 --- /dev/null +++ b/.rvmrc @@ -0,0 +1 @@ +rvm @cucumber --create diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..9f5fbddac0 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source 'http://rubygems.org' + +gem 'cucumber', '1.0.0' +gem 'aruba', '0.4.3' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..b543155218 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,43 @@ +GEM + remote: http://rubygems.org/ + specs: + aruba (0.4.3) + bcat (>= 0.6.1) + childprocess (>= 0.1.9) + cucumber (>= 0.10.7) + rdiscount (>= 1.6.8) + rspec (>= 2.6.0) + bcat (0.6.1) + rack (~> 1.0) + builder (3.0.0) + childprocess (0.1.9) + ffi (~> 1.0.6) + cucumber (1.0.0) + builder (>= 2.1.2) + diff-lcs (>= 1.1.2) + gherkin (~> 2.4.1) + json (>= 1.4.6) + term-ansicolor (>= 1.0.5) + diff-lcs (1.1.2) + ffi (1.0.9) + gherkin (2.4.1) + json (>= 1.4.6) + json (1.5.3) + rack (1.3.0) + rdiscount (1.6.8) + rspec (2.6.0) + rspec-core (~> 2.6.0) + rspec-expectations (~> 2.6.0) + rspec-mocks (~> 2.6.0) + rspec-core (2.6.4) + rspec-expectations (2.6.0) + diff-lcs (~> 1.1.2) + rspec-mocks (2.6.0) + term-ansicolor (1.0.5) + +PLATFORMS + ruby + +DEPENDENCIES + aruba (= 0.4.3) + cucumber (= 1.0.0) diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000000..c8f14acf7a --- /dev/null +++ b/Rakefile @@ -0,0 +1,7 @@ +require 'cucumber/rake/task' + +Cucumber::Rake::Task.new(:picocontainer) do |t| + t.cucumber_opts = '-r java/src/test/resources/cucumber-features -r cucumber-features cucumber-features' +end + +task :default => :picocontainer \ No newline at end of file diff --git a/core/src/main/java/cucumber/junit/Cucumber.java b/core/src/main/java/cucumber/junit/Cucumber.java index 5786b996bf..4c2858561e 100644 --- a/core/src/main/java/cucumber/junit/Cucumber.java +++ b/core/src/main/java/cucumber/junit/Cucumber.java @@ -22,7 +22,7 @@ public class Cucumber extends ParentRunner { private static Runtime runtime(Class testClass) { String packageName = testClass.getName().substring(0, testClass.getName().lastIndexOf(".")); - final Runtime runtime = new Runtime(); + final Runtime runtime = new Runtime(packageName); java.lang.Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { @@ -44,7 +44,12 @@ public Cucumber(Class featureClass) throws InitializationError { public Cucumber(Class featureClass, final Runtime runtime) throws InitializationError { // Why aren't we passing the class to super? I don't remember, but there is probably a good reason. super(null); - pathName = featureClass.getName().replace('.', '/') + ".feature"; + cucumber.junit.Feature featureAnnotation = (cucumber.junit.Feature) featureClass.getAnnotation(cucumber.junit.Feature.class); + if(featureAnnotation != null) { + pathName = featureAnnotation.value(); + } else { + pathName = featureClass.getName().replace('.', '/') + ".feature"; + } builder = new RunnerBuilder(runtime, children); feature = parseFeature(); } diff --git a/core/src/main/java/cucumber/junit/Feature.java b/core/src/main/java/cucumber/junit/Feature.java new file mode 100644 index 0000000000..eb4b2c68ab --- /dev/null +++ b/core/src/main/java/cucumber/junit/Feature.java @@ -0,0 +1,12 @@ +package cucumber.junit; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface Feature { + String value(); +} diff --git a/core/src/main/java/cucumber/junit/RunnerBuilder.java b/core/src/main/java/cucumber/junit/RunnerBuilder.java index 5cec3d6793..3b559c72e5 100644 --- a/core/src/main/java/cucumber/junit/RunnerBuilder.java +++ b/core/src/main/java/cucumber/junit/RunnerBuilder.java @@ -2,6 +2,7 @@ import cucumber.runtime.CucumberException; import cucumber.runtime.Runtime; +import gherkin.GherkinParser; import gherkin.formatter.Formatter; import gherkin.formatter.model.*; import org.junit.runners.ParentRunner; @@ -14,7 +15,7 @@ class RunnerBuilder implements Formatter { private final Runtime runtime; private final List children; private List scenarioRunners = new ArrayList(); - private Feature feature; + private gherkin.formatter.model.Feature feature; private ScenarioRunner scenarioRunner; public RunnerBuilder(Runtime runtime, List children) { @@ -25,7 +26,7 @@ public RunnerBuilder(Runtime runtime, List children) { public void uri(String uri) { } - public void feature(Feature feature) { + public void feature(gherkin.formatter.model.Feature feature) { this.feature = feature; } @@ -57,7 +58,7 @@ public void eof() { public void syntaxError(String state, String event, List legalEvents, String uri, int line) { } - public Feature getFeature() { + public gherkin.formatter.model.Feature getFeature() { return feature; } diff --git a/core/src/main/java/cucumber/runtime/Runtime.java b/core/src/main/java/cucumber/runtime/Runtime.java index 348efb43b0..7459368030 100644 --- a/core/src/main/java/cucumber/runtime/Runtime.java +++ b/core/src/main/java/cucumber/runtime/Runtime.java @@ -21,8 +21,8 @@ public Runtime(Backend... backends) { this.backends = asList(backends); } - public Runtime() { - backends = Classpath.instantiateSubclasses(Backend.class, "cucumber.runtime"); + public Runtime(String packageName) { + backends = Classpath.instantiateSubclasses(Backend.class, packageName); } public StepDefinitionMatch stepDefinitionMatch(Step step) { diff --git a/cucumber-features b/cucumber-features new file mode 160000 index 0000000000..5dcb569f6e --- /dev/null +++ b/cucumber-features @@ -0,0 +1 @@ +Subproject commit 5dcb569f6e2d8d4a6803893298d769a100a06b19 diff --git a/java/src/test/resources/cucumber-features/cucumber_java_mappings.rb b/java/src/test/resources/cucumber-features/cucumber_java_mappings.rb new file mode 100644 index 0000000000..5e410acc1c --- /dev/null +++ b/java/src/test/resources/cucumber-features/cucumber_java_mappings.rb @@ -0,0 +1,104 @@ +require 'erb' + +module CucumberJavaMappings + def features_dir + "src/test/resources" + end + + def run_scenario(scenario_name) + write_pom + write_test_unit_classes + run_simple "mvn test", false + end + + def write_pom + write_file('pom.xml', <<-EOF) + + 4.0.0 + + + cucumber + parent + ../../pom.xml + 0.4.3-SNAPSHOT + + + cucumber-picocontainer-test + 0.4.3-SNAPSHOT + jar + Cucumber: PicoContainer Test + + + + cucumber + picocontainer + 0.4.3-SNAPSHOT + + + +EOF + end + + @@mappings_counter = 1 + + def write_passing_mapping(step_name) + erb = ERB.new(<<-EOF, nil, '-') +package cucumber.test; + +import cucumber.annotation.EN.Given; + +public class Mappings<%= @@mappings_counter %> { + @Given("<%= step_name -%>") + public void <%= step_name.gsub(/ /, '_') -%>() { + // ARUBA_IGNORE_START + try { + new java.io.FileWriter("<%= step_file(step_name) %>"); + } catch(java.io.IOException e) { + throw new RuntimeException(e); + } + // ARUBA_IGNORE_END + } +} + +EOF + write_file("src/test/java/cucumber/test/Mappings#{@@mappings_counter}.java", erb.result(binding)) + @@mappings_counter += 1 + end + + def write_test_unit_classes + features = in_current_dir do + Dir.chdir(features_dir) do + Dir["**/*.feature"] + end + end + features.each do |feature| + class_name = File.basename(feature).match(/(.*)\.feature$/)[1] + "_Test" + write_file("src/test/java/cucumber/test/#{class_name}.java", <<-EOF) +package cucumber.test; + +import cucumber.junit.Cucumber; +import cucumber.junit.Feature; +import org.junit.runner.RunWith; + +@RunWith(Cucumber.class) +@Feature("#{feature}") +public class #{class_name} {} +EOF + end + end + + def assert_passing_scenario + 2 tests because we have 2 steps + assert_partial_output("Tests run: 2, Failures: 0, Errors: 0, Skipped: 0", all_output) + assert_success true + end +end + +World(CucumberJavaMappings) + +Before do + @aruba_timeout_seconds = 10 +end diff --git a/picocontainer/src/test/java/cucumber/runtime/junit/cucumber_runner.java b/picocontainer/src/test/java/cucumber/runtime/junit/cucumber_runner_Test.java similarity index 61% rename from picocontainer/src/test/java/cucumber/runtime/junit/cucumber_runner.java rename to picocontainer/src/test/java/cucumber/runtime/junit/cucumber_runner_Test.java index aca269e875..5e18a80429 100644 --- a/picocontainer/src/test/java/cucumber/runtime/junit/cucumber_runner.java +++ b/picocontainer/src/test/java/cucumber/runtime/junit/cucumber_runner_Test.java @@ -1,14 +1,17 @@ package cucumber.runtime.junit; import cucumber.junit.Cucumber; +import cucumber.junit.Feature; import org.junit.runner.RunWith; /** * In order to run a Cucumber Feature from JUnit - all you need is an empty class annotated like below. - * The class must be named the same as the feature file and be in the same package. + * The @Feature annotation is not required if the test class is named the same as the feature file and + * in the same package. * * You can write this stub class by hand, but Cucumber will also have a tool that can generate them * from .feature sources. */ @RunWith(Cucumber.class) -public class cucumber_runner {} +@Feature("cucumber_runner.feature") +public class cucumber_runner_Test {} diff --git a/picocontainer/src/test/resources/cucumber/runtime/junit/cucumber_runner.feature b/picocontainer/src/test/resources/cucumber_runner.feature similarity index 100% rename from picocontainer/src/test/resources/cucumber/runtime/junit/cucumber_runner.feature rename to picocontainer/src/test/resources/cucumber_runner.feature