forked from nilswloka/lein-cucumber
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
234 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
language: clojure | ||
lein: lein2 | ||
script: lein2 cucumber |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,45 @@ | ||
[![Build Status](https://secure.travis-ci.org/nilswloka/lein-cucumber.png)](http://travis-ci.org/nilswloka/lein-cucumber) | ||
|
||
# lein-cucumber | ||
|
||
This is a very simple leiningen plugin for use with [cucumber-jvm](https://github.com/cucumber/cucumber-jvm). | ||
This is a leiningen plugin for use with [cucumber-jvm](https://github.com/cucumber/cucumber-jvm). | ||
|
||
## Usage | ||
|
||
1. Add `[lein-cucumber "0.2.0"]` to `:dev-dependencies` in your project.clj | ||
1. Add `[lein-cucumber "1.0.0]` to `:plugins` in your project.clj | ||
2. Run `lein deps` to fetch all dependencies. | ||
3. Run all Cucumber features with `lein cucumber` | ||
3. Run all Cucumber features with `lein2 cucumber` | ||
|
||
## Please note | ||
|
||
In the current version, you cannot specify any configuration options. The following settings are hard-coded into the plugin: | ||
lein-cucumber requires Leiningen 2. | ||
|
||
## Configuration | ||
|
||
Feature paths are resolved in the following order: | ||
|
||
1. Command line options (e.g. `lein2 cucumber my-features`) override all other settings. | ||
2. If no command line options for feature paths are given, the `:cucumber-feature-paths` parameter in your project.clj will be used (e.g. `:cucumber-feature-paths ["test/features/"]`). | ||
3. If neither command line options nor a parameter is used, lein-cucumber looks for features in the `features/` directory. | ||
|
||
Glue paths are resolved similarily: | ||
|
||
* A progress report will be printed to the console. | ||
* The complete report (formatted with `PrettyFormatter`) will be written to `test-reports/cucumber.out`. Consider adding `:extra-files-to-clean ["test-reports"]` to your project.clj. | ||
1. Command line options (e.g. `lein2 cucumber --glue somewhere/my_stepdefs`) override all other settings. | ||
2. If no command line options for glue paths are given, step definitions will be loaded from `step_definitions/` directories inside your feature directories. | ||
|
||
## Other settings | ||
|
||
The following settings are hard-coded into the plugin: | ||
|
||
* A summary report will be printed to the console. | ||
* The complete report (formatted with `CucumberPrettyFormatter`) will be written to `test-reports/cucumber.out` inside your project's target directory (usually `target/`). | ||
* Leiningen will exit with the exit status of the cucumber-jvm [runtime](https://github.com/cucumber/cucumber-jvm/blob/master/core/src/main/java/cucumber/runtime/Runtime.java). | ||
* Put your `.feature` files into `features/` (feature-paths can be configured in project.clj using the `:cucumber-feature-path` parameter, e.g `:cucumber-feature-path ["test/features/"]`.) | ||
* Put your step definitions into `features/step_definitions/` | ||
|
||
See https://github.com/cucumber/cucumber-jvm/tree/master/clojure/src/test/resources/cucumber/runtime/clojure for an example specification. | ||
See https://github.com/nilswloka/cucumber-jvm/tree/new-clojure-example/examples/clojure_cukes for an example project. | ||
|
||
## Unlicense | ||
|
||
Written by Nils Wloka, 2012. For licensing information, see UNLICENSE. | ||
Written by Nils Wloka, 2012. For licensing information, see UNLICENSE. [![endorse](http://api.coderwall.com/nilswloka/endorsecount.png)](http://coderwall.com/nilswloka) | ||
Contributions by [Robert P. Levy](https://github.com/rplevy-draker) and [Michael van Acken](https://github.com/mva). | ||
Please have a look at http://unlicense.org if you plan to contribute. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
Feature: lein-cucumber works | ||
|
||
Scenario: No features | ||
Given a lein-cucumber project without special configuration | ||
And no features in the "features" directory | ||
When I run lein-cucumber without command line arguments | ||
Then the output should include "No features found" | ||
|
||
Scenario: Features, but no step definitions | ||
Given a lein-cucumber project without special configuration | ||
And a feature in the "features" directory | ||
And no step definitions in the "features/step_definitions" directory | ||
When I run lein-cucumber without command line arguments | ||
Then the output should include "You can implement missing steps with the snippets below:" | ||
|
||
Scenario: Features and step definitions | ||
Given a lein-cucumber project without special configuration | ||
And a feature in the "features" directory | ||
And a step definition in the "features/step_definitions" directory | ||
When I run lein-cucumber without command line arguments | ||
Then the step should be executed | ||
And the output should include "." | ||
|
||
Scenario: Specify feature directory in project.clj | ||
Given a lein-cucumber project with the following parameters: | ||
| :cucumber-feature-paths | | ||
| ["test/features/"] | | ||
And a feature in the "test/features/" directory | ||
And a step definition in the "test/features/step_definitions" directory | ||
When I run lein-cucumber without command line arguments | ||
Then the step should be executed | ||
|
||
Scenario: Specify feature directory via command line | ||
Given a lein-cucumber project without special configuration | ||
And a feature in the "foo" directory | ||
And a step definition in the "foo/step_definitions" directory | ||
When I run lein-cucumber with arguments "foo" | ||
Then the step should be executed | ||
|
||
Scenario: Specify glue directory via command line | ||
Given a lein-cucumber project without special configuration | ||
And a feature in the "features" directory | ||
And a step definition in the "foo" directory | ||
When I run lein-cucumber with arguments "--glue foo" | ||
Then the step should be executed |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
(use 'clojure.java.io) | ||
(use 'clojure.java.shell) | ||
(use 'leiningen.cucumber) | ||
(require '[leiningen.core.project :as project]) | ||
(require '[leiningen.core.user :as user]) | ||
(import '[org.apache.commons.io FileUtils]) | ||
(import '[java.io StringWriter]) | ||
|
||
(def project-directory | ||
(file "target" "test_project")) | ||
|
||
(def feature-content | ||
"Feature: test-feature\n Scenario: A test\n Given a step\n") | ||
|
||
(def step-content | ||
'(Given #"^a step$" [] (println "{{{STEP EXECUTED}}}"))) | ||
|
||
(def result (atom "")) | ||
|
||
(defn- project-configuration | ||
([] '(defproject test-project "0.1.0" | ||
:description "A test project")) | ||
([parameters] | ||
(seq (concat (project-configuration) parameters)))) | ||
|
||
(defn- create-project [project-file-content] | ||
(let [project-file (file project-directory "project.clj")] | ||
(.mkdirs project-directory) | ||
(FileUtils/cleanDirectory project-directory) | ||
(spit project-file project-file-content))) | ||
|
||
(defn- create-empty-directory [path] | ||
(let [empty-directory (file project-directory path)] | ||
(.mkdirs empty-directory) | ||
(FileUtils/cleanDirectory empty-directory))) | ||
|
||
(defn- create-file [path name content] | ||
(let [the-file (file project-directory path name)] | ||
(make-parents the-file) | ||
(delete-file the-file true) | ||
(spit the-file content))) | ||
|
||
(defn- read-project [] | ||
(with-redefs [user/profiles (constantly {})] | ||
(project/read "target/test_project/project.clj"))) | ||
|
||
(defn- writing-to-result [f] | ||
(let [out-writer (java.io.StringWriter.)] | ||
(with-redefs [*out* out-writer] | ||
(f) | ||
(reset! result (.toString out-writer))))) | ||
|
||
(defn- assert-output-includes [text] | ||
(assert (.contains @result text))) | ||
|
||
(Given #"^a lein-cucumber project without special configuration$" [] | ||
(create-project (project-configuration))) | ||
|
||
(Given #"^a lein-cucumber project with the following parameters:$" [parameter-table] | ||
(let [parameters (map (comp read-string first) (.raw parameter-table))] | ||
(create-project (project-configuration parameters)))) | ||
|
||
(Given #"^no features in the \"([^\"]*)\" directory$" [path] | ||
(create-empty-directory path)) | ||
|
||
(Given #"^no step definitions in the \"([^\"]*)\" directory$" [path] | ||
(create-empty-directory path)) | ||
|
||
(Given #"^a feature in the \"([^\"]*)\" directory$" [path] | ||
(create-file path "test.feature" feature-content)) | ||
|
||
(Given #"^a step definition in the \"([^\"]*)\" directory$" [path] | ||
(create-file path "test_steps.clj" step-content)) | ||
|
||
(When #"^I run lein-cucumber without command line arguments$" [] | ||
(writing-to-result | ||
(fn [] (cucumber (read-project))))) | ||
|
||
(When #"^I run lein-cucumber with arguments \"([^\"]*)\"$" [args] | ||
(writing-to-result | ||
(fn [] (apply cucumber (concat (vector (read-project)) (re-seq #"\S+\b" args)))))) | ||
|
||
(Then #"^the output should include \"([^\"]*)\"$" [expected-output] | ||
(assert-output-includes expected-output)) | ||
|
||
(Then #"^the step should be executed" [] | ||
(assert-output-includes "{{{STEP EXECUTED}}}")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
(defproject lein-cucumber "0.2.0" | ||
(defproject lein-cucumber "1.0.0" | ||
:description "Run cucumber-jvm specifications with leiningen" | ||
:dependencies [[info.cukes/cucumber-clojure "1.0.0.RC21"]] | ||
:eval-in-leiningen true | ||
:dependencies [[info.cukes/cucumber-clojure "1.0.4"] | ||
[leiningen-core "2.0.0-preview3"]] | ||
:profiles {:test {:dependencies [[commons-io "2.0"]]}} | ||
:plugins [[lein-cucumber "1.0.0"]] | ||
:eval-in :leiningen | ||
:license {:name "Unlicense" | ||
:url "http://unlicense.org/" | ||
:distribution :repo}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,41 @@ | ||
(ns leiningen.cucumber | ||
(:use [leiningen.compile :only [eval-in-project]]) | ||
(:require [leiningen.core :as core])) | ||
(:use [clojure.java.io]) | ||
(:use [leiningen.core.eval :only [eval-in-project]]) | ||
(:require [leiningen.core.project :as project]) | ||
(:import [cucumber.runtime RuntimeOptions])) | ||
|
||
(defn- configure-feature-paths [runtime-options feature-paths] | ||
(when (.. runtime-options featurePaths (isEmpty)) | ||
(.. runtime-options featurePaths (addAll feature-paths)))) | ||
|
||
(defn- configure-glue-paths [runtime-options glue-paths feature-paths] | ||
(when (.. runtime-options glue (isEmpty)) | ||
(if (empty? glue-paths) | ||
(.. runtime-options glue (addAll (into [] (map #(str (file % "step_definitions/")) feature-paths)))) | ||
(.. runtime-options glue (addAll glue-paths))))) | ||
|
||
(defn create-partial-runtime-options [{:keys [cucumber-feature-paths target-path cucumber-glue-paths] :or {cucumber-feature-paths ["features"]}} args] | ||
(let [runtime-options (RuntimeOptions. (into-array String args))] | ||
(configure-feature-paths runtime-options cucumber-feature-paths) | ||
(configure-glue-paths runtime-options cucumber-glue-paths (.featurePaths runtime-options)) | ||
runtime-options)) | ||
|
||
(defn cucumber | ||
"Runs Cucumber features in test/features with glue in test/features/step_definitions" | ||
[project] | ||
[project & args] | ||
(let [runtime (gensym "runtime") | ||
feature-paths (:cucumber-feature-path project)] | ||
runtime-options (create-partial-runtime-options project args) | ||
glue-paths (vec (.glue runtime-options)) | ||
feature-paths (vec (.featurePaths runtime-options)) | ||
target-path (:target-path project) | ||
project (project/merge-profiles project [:test])] | ||
(eval-in-project | ||
project | ||
(-> project | ||
(update-in [:dependencies] conj | ||
['lein-cucumber "1.0.0"] | ||
['info.cukes/cucumber-clojure "1.0.4"]) | ||
(update-in [:source-paths] (partial apply conj) glue-paths)) | ||
`(do | ||
(let [~runtime (leiningen.cucumber.util/run-cucumber! ~feature-paths)] | ||
(println) | ||
~(when-not core/*interactive?* | ||
`(System/exit (.exitStatus ~runtime))))) | ||
nil | ||
nil | ||
'(require 'leiningen.cucumber.util)))) | ||
(let [~runtime (leiningen.cucumber.util/run-cucumber! ~feature-paths ~glue-paths ~target-path ~(vec args))] | ||
(leiningen.core.main/exit (.exitStatus ~runtime)))) | ||
'(require 'leiningen.cucumber.util 'leiningen.core.main)))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,40 @@ | ||
(ns leiningen.cucumber.util | ||
(:use [clojure.java.io]) | ||
(:import [gherkin.formatter PrettyFormatter]) | ||
(:import [cucumber.formatter FormatterFactory MultiFormatter]) | ||
(:import [cucumber.formatter CucumberPrettyFormatter ProgressFormatter]) | ||
(:import [cucumber.io FileResourceLoader]) | ||
(:import [cucumber.cli DefaultRuntimeFactory]) | ||
(:import [cucumber.runtime.snippets SummaryPrinter]) | ||
(:import [java.io File]) | ||
(:import [java.util ArrayList])) | ||
(:import [cucumber.runtime.model CucumberFeature]) | ||
(:import [cucumber.runtime RuntimeOptions CucumberException])) | ||
|
||
(defn- report-writer [] | ||
(let [report-directory (file "test-reports") | ||
report-file (file report-directory "cucumber.out")] | ||
(defn- report-writer [target-path] | ||
(let [report-file (file target-path "test-reports" "cucumber.out")] | ||
(make-parents report-file) | ||
(writer report-file))) | ||
|
||
(defn- create-multi-formatter [] | ||
(let [classloader (.getContextClassLoader (Thread/currentThread)) | ||
formatter-factory (FormatterFactory. classloader) | ||
multi-formatter (MultiFormatter. classloader) | ||
out (report-writer) | ||
formatter (PrettyFormatter. out true true)] | ||
(doto multi-formatter | ||
(.add formatter) | ||
(.add (.createFormatter formatter-factory "progress" System/out))) | ||
multi-formatter)) | ||
|
||
(defn- create-runtime [stepdef-paths] | ||
(let [runtime-factory (DefaultRuntimeFactory.) | ||
classloader (.getContextClassLoader (Thread/currentThread)) | ||
glue-paths (ArrayList. stepdef-paths) | ||
file-resource-loader (FileResourceLoader.)] | ||
(.createRuntime runtime-factory file-resource-loader glue-paths classloader false))) | ||
(defn- create-runtime-options [feature-paths glue-paths target-path args] | ||
(let [runtime-options (RuntimeOptions. (into-array String args))] | ||
(when (.. runtime-options featurePaths (isEmpty)) | ||
(.. runtime-options featurePaths (addAll feature-paths))) | ||
(when (.. runtime-options glue (isEmpty)) | ||
(.. runtime-options glue (addAll glue-paths))) | ||
(doto (.formatters runtime-options) | ||
(.add (CucumberPrettyFormatter. (report-writer target-path))) | ||
(.add (ProgressFormatter. *out*))) | ||
runtime-options)) | ||
|
||
(defn- gen-stepdef-paths [feature-paths] | ||
(map (fn [path] | ||
(format "%s%sstep_definitions" path (if (= (last path) \/) "" "/"))) | ||
feature-paths)) | ||
(defn- create-runtime [runtime-options] | ||
(let [classloader (.getContextClassLoader (Thread/currentThread)) | ||
resource-loader (FileResourceLoader.)] | ||
(cucumber.runtime.Runtime. resource-loader classloader runtime-options))) | ||
|
||
(defn run-cucumber! [feature-paths] | ||
(let [multi-formatter (create-multi-formatter) | ||
feature-paths (if (some identity feature-paths) | ||
feature-paths ["features"]) | ||
runtime (create-runtime (gen-stepdef-paths feature-paths)) | ||
formatter (.formatterProxy multi-formatter) | ||
reporter (.reporterProxy multi-formatter) | ||
summary-printer (SummaryPrinter. System/out)] | ||
(.run runtime (ArrayList. feature-paths) (ArrayList.) formatter reporter) | ||
(.done formatter) | ||
(.print summary-printer runtime) | ||
(.close formatter) | ||
(defn run-cucumber! [feature-paths glue-paths target-path args] | ||
(let [runtime-options (create-runtime-options feature-paths glue-paths | ||
target-path args) | ||
runtime (create-runtime runtime-options)] | ||
(println "Running cucumber...") | ||
(println "Looking for features in: " (vec (.featurePaths runtime-options))) | ||
(println "Looking for glue in: " (vec (.glue runtime-options))) | ||
(try | ||
(.run runtime) | ||
(catch CucumberException e | ||
(println (.getMessage e)))) | ||
runtime)) |