├── .gitignore ├── LICENCE ├── README.md ├── clojure ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── clojure │ │ └── cucumber │ │ │ └── runtime │ │ │ └── clj.clj │ └── java │ │ └── cucumber │ │ └── runtime │ │ └── clojure │ │ └── Dummy.java │ └── test │ ├── java │ └── cucumber │ │ └── runtime │ │ └── clojure │ │ ├── ClojureSnippetTest.java │ │ └── RunCukesTest.java │ └── resources │ └── cucumber │ └── runtime │ └── clojure │ ├── belly.clj │ ├── cukes.feature │ ├── stepdefs.clj │ └── tables.feature ├── examples ├── .gitignore ├── README.md ├── pom.xml ├── project.clj ├── src │ └── clojure_cukes │ │ └── core.clj └── test │ ├── clojure_cukes │ └── test │ │ └── core.clj │ ├── features │ ├── cukes.feature │ └── step_definitions │ │ └── cuke_steps.clj │ └── java │ └── features │ └── RunCukesTest.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | **/*.iml 3 | 4 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (c) The Cucumber Organisation 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cucumber-Clojure 2 | 3 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.cucumber/cucumber-clojure/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.cucumber/cucumber-clojure) 4 | 5 | Cucumber-Clojure is a Cucumber implementation for [Clojure](http://www.clojure.org/). 6 | 7 | This document is the reference for features that are specific to Cucumber-Clojure. 8 | 9 | Please see the [general reference](https://cucumber.io/docs/reference) for features that are common to all Cucumber implementations. 10 | 11 | ## Step Definitions 12 | 13 | Clojure step definitions are defined by using the provided [macros](http://clojure.org/macros). For example: 14 | 15 | ```clojure 16 | (use 'clojure-cukes.core) 17 | (use 'clojure.test) 18 | 19 | (Given #"^I have (\d+) big cukes in my belly$" [cukes] 20 | (println cukes)) 21 | ``` 22 | 23 | You can use a [DataTable](https://cucumber.io/docs/reference#data-table) to define a list: 24 | 25 | ``` 26 | Given I have a table with its keys in a header row: 27 | | id | name | created-at | 28 | | 55 | "foo" | 1293884100000 | 29 | | 56 | "bar" | 1293884100000 | 30 | ``` 31 | 32 | Simply declare the following: 33 | 34 | ```clojure 35 | (Given #"^I have a table with its keys in a header row:$" [data] 36 | (reset! most-recent (table->rows data))) 37 | ``` 38 | 39 | In this case, the DataTable is flattened to a vector of hashes 40 | 41 | ```clojure 42 | [{:id 55, :name "foo", :created-at 1293884100000} 43 | {:id 56, :name "bar", :created-at 1293884100000}] 44 | ``` 45 | 46 | before invoking the step definition. 47 | 48 | ## Installation 49 | 50 | ### Maven 51 | To use cucumber-jvm-clojure in your project, add the following dependency to your `pom.xml`: 52 | 53 | ```xml 54 | 55 | io.cucumber 56 | cucumber-clojure 57 | 2.0.1 58 | test 59 | 60 | ``` 61 | 62 | 63 | ## Running 64 | 65 | There are several ways to run scenarios with Cucumber-Clojure: 66 | * lein-cucumber 67 | * JunitRunner 68 | 69 | ### lein-cucumber 70 | 71 | [Leiningen](http://leiningen.org/) uses [clojure.test](TODO) to run Cucumber. All you need is a single entry point: 72 | 73 | ```clojure 74 | (ns clojure-cukes.test.core 75 | (:use [clojure-cukes.core]) 76 | (:use [clojure.test])) 77 | 78 | (deftest run-cukes 79 | (. cucumber.api.cli.Main (main (into-array ["--plugin" "pretty" "--glue" "test/features/step_definitions" "test/features"])))) 80 | 81 | ``` 82 | 83 | You then need to add `[com.siili/lein-cucumber "1.0.7"]` to `:plugins` in your project.clj. This allows you to run all Cucumber features with `lein cucumber` 84 | 85 | ### JUnitRunner 86 | 87 | The instructions for the JUnitRunner can be found [here](https://cucumber.io/docs/reference/jvm#junit-runner) 88 | 89 | ## Miscellaneous 90 | 91 | This module needs further documentation. The following examples show supported features: 92 | 93 | * [examples](https://github.com/cucumber/cucumber-jvm-clojure/tree/master/examples/) 94 | * [clojure/src/test/resources/cucumber/runtime/clojure](https://github.com/cucumber/cucumber-jvm-clojure/tree/master/clojure/src/test/resources/cucumber/runtime/clojure). 95 | 96 | Contributions are most welcome. 97 | -------------------------------------------------------------------------------- /clojure/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /clojure/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | io.cucumber 6 | cucumber-jvm-clojure 7 | 2.0.2-SNAPSHOT 8 | 9 | 10 | cucumber-clojure 11 | jar 12 | Cucumber Clojure 13 | 14 | 15 | 16 | io.cucumber 17 | cucumber-core 18 | 19 | 20 | org.clojure 21 | clojure 22 | provided 23 | 24 | 25 | junit 26 | junit 27 | test 28 | 29 | 30 | io.cucumber 31 | cucumber-junit 32 | test 33 | 34 | 35 | 36 | 37 | 38 | com.theoryinpractise 39 | clojure-maven-plugin 40 | 41 | 42 | cucumber.* 43 | 44 | true 45 | 46 | 47 | 48 | compile 49 | compile 50 | 51 | compile 52 | 53 | 54 | 55 | test 56 | test 57 | 58 | test 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | coveralls.io 69 | 70 | 71 | 72 | org.codehaus.mojo 73 | cobertura-maven-plugin 74 | ${cobertura-maven-plugin.version} 75 | 76 | true 77 | 78 | 79 | 80 | 81 | maven-surefire-plugin 82 | 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /clojure/src/main/clojure/cucumber/runtime/clj.clj: -------------------------------------------------------------------------------- 1 | (ns cucumber.runtime.clj 2 | (:require (clojure [string :as str])) 3 | (:import (cucumber.runtime CucumberException 4 | JdkPatternArgumentMatcher 5 | StepDefinition 6 | HookDefinition 7 | TagPredicate) 8 | (cucumber.runtime.snippets Snippet 9 | SnippetGenerator) 10 | (clojure.lang RT)) 11 | (:gen-class :name cucumber.runtime.clj.Backend 12 | :implements [cucumber.runtime.Backend] 13 | :constructors 14 | {[cucumber.runtime.io.ResourceLoader] []} 15 | :init init 16 | :state state)) 17 | 18 | (def glue (atom nil)) 19 | 20 | (defn clojure-snippet [] 21 | (reify 22 | Snippet 23 | (template [_] 24 | (str 25 | "({0} #\"{1}\" [{3}]\n" 26 | " (comment {4} )\n" 27 | " (throw (cucumber.api.PendingException.)))\n")) 28 | (arguments [_ argumentTypes] 29 | (str/replace (SnippetGenerator/untypedArguments argumentTypes) 30 | "," "")) 31 | (namedGroupStart [_] nil) 32 | (namedGroupEnd [_] nil) 33 | (tableHint [_] nil) 34 | (escapePattern [_ pattern] 35 | (str/replace (str pattern) "\"" "\\\"")))) 36 | 37 | (def snippet-generator (SnippetGenerator. (clojure-snippet))) 38 | 39 | (defn load-script [path] 40 | (try 41 | (RT/load (str (.replaceAll path ".clj$" "")) true) 42 | (catch Throwable t 43 | (throw (CucumberException. t))))) 44 | 45 | (defn- -init [resource-loader] 46 | [[] (atom {:resource-loader resource-loader})]) 47 | 48 | (defn -loadGlue [cljb a-glue glue-paths] 49 | (reset! glue a-glue) 50 | (doseq [path glue-paths 51 | resource (.resources (:resource-loader @(.state cljb)) path ".clj")] 52 | (binding [*ns* (create-ns 'cucumber.runtime.clj)] 53 | (load-script (.getPath resource))))) 54 | 55 | (defn- -buildWorld [cljb]) 56 | 57 | (defn- -disposeWorld [cljb]) 58 | 59 | (defn- -getSnippet [cljb step keyword _] 60 | (.getSnippet snippet-generator step keyword nil)) 61 | 62 | (defn- -setUnreportedStepExecutor [cljb executor] 63 | "executor") 64 | 65 | (defn- location-str [{:keys [file line]}] 66 | (str file ":" line)) 67 | 68 | (defn add-step-definition [pattern fun location] 69 | (.addStepDefinition 70 | @glue 71 | (reify 72 | StepDefinition 73 | (matchedArguments [_ step] 74 | (.argumentsFrom (JdkPatternArgumentMatcher. pattern) 75 | (.getText step))) 76 | (getLocation [_ detail] 77 | (location-str location)) 78 | (getParameterCount [_] 79 | nil) 80 | (getParameterType [_ n argumentType] 81 | nil) 82 | (execute [_ locale args] 83 | (apply fun args)) 84 | (isDefinedAt [_ stack-trace-element] 85 | (and (= (.getLineNumber stack-trace-element) 86 | (:line location)) 87 | (= (.getFileName stack-trace-element) 88 | (:file location)))) 89 | (getPattern [_] 90 | (str pattern))))) 91 | 92 | (defmulti add-hook-definition (fn [t & _] t)) 93 | 94 | (defmethod add-hook-definition :before [_ tag-expression hook-fun location] 95 | (let [tp (TagPredicate. tag-expression)] 96 | (.addBeforeHook 97 | @glue 98 | (reify 99 | HookDefinition 100 | (getLocation [_ detail?] 101 | (location-str location)) 102 | (execute [hd scenario-result] 103 | (hook-fun)) 104 | (matches [hd tags] 105 | (.apply tp tags)) 106 | (getOrder [hd] 0) 107 | (isScenarioScoped [hd] false))))) 108 | 109 | (defmethod add-hook-definition :after [_ tag-expression hook-fun location] 110 | (let [tp (TagPredicate. tag-expression) 111 | max-parameter-count (->> hook-fun class .getDeclaredMethods 112 | (filter #(= "invoke" (.getName %))) 113 | (map #(count (.getParameterTypes %))) 114 | (apply max))] 115 | (.addAfterHook 116 | @glue 117 | (reify 118 | HookDefinition 119 | (getLocation [_ detail?] 120 | (location-str location)) 121 | (execute [hd scenario-result] 122 | (if (zero? max-parameter-count) 123 | (hook-fun) 124 | (hook-fun scenario-result))) 125 | (matches [hd tags] 126 | (.apply tp tags)) 127 | (getOrder [hd] 0) 128 | (isScenarioScoped [hd] false))))) 129 | 130 | (defmacro step-macros [& names] 131 | (cons 'do 132 | (for [name names] 133 | `(defmacro ~name [pattern# binding-form# & body#] 134 | `(add-step-definition ~pattern# 135 | (fn ~binding-form# ~@body#) 136 | '~{:file *file* 137 | :line (:line (meta ~'&form))}))))) 138 | (step-macros 139 | Given When Then And But) 140 | 141 | (defn- hook-location [file form] 142 | {:file file 143 | :line (:line (meta form))}) 144 | 145 | (defmacro Before [tags & body] 146 | `(add-hook-definition :before ~tags (fn [] ~@body) ~(hook-location *file* &form))) 147 | 148 | (defmacro After [tags & body] 149 | `(add-hook-definition :after ~tags (fn [] ~@body) ~(hook-location *file* &form))) 150 | 151 | (defn ^:private update-keys [f m] 152 | (reduce-kv #(assoc %1 (f %2) %3) {} m)) 153 | 154 | (defn ^:private update-values [f m] 155 | (reduce-kv #(assoc %1 %2 (f %3)) {} m)) 156 | 157 | (defn read-cuke-str 158 | "Using the clojure reader is often a good way to interpret literal values 159 | in feature files. This function makes some cucumber-specific adjustments 160 | to basic reader behavior. This is particulary appropriate when reading a 161 | table, for example: reading | \"1\" | 1 | we should intepret 1 as an int 162 | and \"1\" as a string. This is used by kv-table->map and table->rows." 163 | [string] 164 | (if (re-matches #"^:.*|\d+(\.\d+)?" string) 165 | (read-string string) 166 | (str/replace string #"\"" ""))) 167 | 168 | (defn kv-table->map 169 | "Reads a table of the form | key | value | 170 | For example, given: 171 | | from | 1293884100000 | 172 | | to | 1293884100000 | 173 | It evaluates to the clojure literal: 174 | {:from 1293884100000, :to 1293884100000}" 175 | [data] 176 | (->> (into {} (map vec (.raw data))) 177 | (update-values read-cuke-str) 178 | (update-keys keyword))) 179 | 180 | (defn table->rows 181 | "Reads a cucumber table of the form 182 | | key-1 | key-2 | ... | key-n | 183 | | val-1 | val-2 | ... | val-n | 184 | For example, given: 185 | | id | name | created-at | 186 | | 55 | \"foo\" | 1293884100000 | 187 | | 56 | \"bar\" | 1293884100000 | 188 | It evaluates to the clojure literal: 189 | [{:id 55, :name \"foo\", :created-at 1293884100000} 190 | {:id 56, :name \"bar\", :created-at 1293884100000}]" 191 | [data] 192 | (let [data (map seq (.raw data)) 193 | header-keys (map keyword (first data)) 194 | remove-blank (fn [m,k,v] (if (seq (str v)) (assoc m k v) m)) 195 | row->hash (fn [row] (apply hash-map 196 | (interleave header-keys 197 | (map read-cuke-str row))))] 198 | (map (fn [row-vals] (reduce-kv remove-blank {} (row->hash row-vals))) 199 | (next data)))) 200 | -------------------------------------------------------------------------------- /clojure/src/main/java/cucumber/runtime/clojure/Dummy.java: -------------------------------------------------------------------------------- 1 | package cucumber.runtime.clojure; 2 | 3 | // Nothing to see here, just a workaround for https://github.com/cucumber/cucumber-jvm/issues/270 4 | public class Dummy { 5 | } 6 | -------------------------------------------------------------------------------- /clojure/src/test/java/cucumber/runtime/clojure/ClojureSnippetTest.java: -------------------------------------------------------------------------------- 1 | package cucumber.runtime.clojure; 2 | 3 | import cucumber.runtime.Backend; 4 | import cucumber.runtime.io.ResourceLoader; 5 | import gherkin.pickles.Argument; 6 | import gherkin.pickles.PickleCell; 7 | import gherkin.pickles.PickleLocation; 8 | import gherkin.pickles.PickleRow; 9 | import gherkin.pickles.PickleStep; 10 | import gherkin.pickles.PickleTable; 11 | import org.junit.Test; 12 | 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | import static java.util.Arrays.asList; 17 | import static org.junit.Assert.assertEquals; 18 | 19 | public class ClojureSnippetTest { 20 | private static final List NO_ARGUMENTS = Collections.emptyList(); 21 | private static final List NO_LOCATIONS = Collections.emptyList(); 22 | 23 | @Test 24 | public void generatesPlainSnippet() throws Exception { 25 | PickleStep step = new PickleStep("I have 4 cukes in my \"big\" belly", NO_ARGUMENTS, NO_LOCATIONS); 26 | String snippet = newBackend().getSnippet(step, "Given", null); 27 | String expected = "" + 28 | "(Given #\"^I have (\\d+) cukes in my \\\"([^\\\"]*)\\\" belly$\" [arg1 arg2]\n" + 29 | " (comment Write code here that turns the phrase above into concrete actions )\n" + 30 | " (throw (cucumber.api.PendingException.)))\n"; 31 | assertEquals(expected, snippet); 32 | } 33 | 34 | @Test 35 | public void generatesSnippetWithDataTable() throws Exception { 36 | PickleTable dataTable = new PickleTable(asList(new PickleRow(asList(new PickleCell(null, "col1"))))); 37 | PickleStep step = new PickleStep("I have:", asList((Argument)dataTable), NO_LOCATIONS); 38 | String snippet = (newBackend()).getSnippet(step, "Given", null); 39 | String expected = "" + 40 | "(Given #\"^I have:$\" [arg1]\n" + 41 | " (comment Write code here that turns the phrase above into concrete actions )\n" + 42 | " (throw (cucumber.api.PendingException.)))\n"; 43 | assertEquals(expected, snippet); 44 | } 45 | 46 | private Backend newBackend() throws Exception { 47 | return (Backend) Class.forName("cucumber.runtime.clj.Backend").getConstructor(ResourceLoader.class).newInstance(new Object[]{null}); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /clojure/src/test/java/cucumber/runtime/clojure/RunCukesTest.java: -------------------------------------------------------------------------------- 1 | package cucumber.runtime.clojure; 2 | 3 | import cucumber.api.junit.Cucumber; 4 | import org.junit.runner.RunWith; 5 | 6 | @RunWith(Cucumber.class) 7 | public class RunCukesTest { 8 | } 9 | -------------------------------------------------------------------------------- /clojure/src/test/resources/cucumber/runtime/clojure/belly.clj: -------------------------------------------------------------------------------- 1 | (ns cucumber.runtime.clojure.belly) 2 | 3 | (def cukes (ref (vector))) 4 | 5 | (defn eat [num] 6 | (dosync (alter cukes conj num))) 7 | 8 | (defn last-meal [] 9 | (last @cukes)) 10 | 11 | -------------------------------------------------------------------------------- /clojure/src/test/resources/cucumber/runtime/clojure/cukes.feature: -------------------------------------------------------------------------------- 1 | Feature: Cukes 2 | 3 | Scenario: in the belly 4 | Given I have 4 cukes in my belly 5 | Then there are 4 cukes in my belly 6 | 7 | Scenario: in the belly (list) 8 | Given I have this many cukes in my belly: 9 | | 13 | 10 | Then there are 13 cukes in my belly 11 | 12 | Scenario: unimplemented steps 13 | Given 5 unimplemented step 14 | 15 | @foo 16 | Scenario: 17 | Given I have 4 cukes in my belly 18 | -------------------------------------------------------------------------------- /clojure/src/test/resources/cucumber/runtime/clojure/stepdefs.clj: -------------------------------------------------------------------------------- 1 | (use 'cucumber.runtime.clojure.belly) 2 | 3 | (def some-state (atom "'Before' hasn't run.")) 4 | 5 | (Before [] 6 | (reset! some-state "'Before' has run.") 7 | (println "Executing 'Before'.")) 8 | 9 | (Before ["@foo"] 10 | (println "Executing 'Tagged Before'")) 11 | 12 | (After [] 13 | (println (str "Executing 'After' " @some-state))) 14 | 15 | (Given #"^I have (\d+) cukes in my belly$" [cuke-count] 16 | (eat (Float. cuke-count))) 17 | 18 | (Given #"^I have this many cukes in my belly:$" [cuke-table] 19 | (doseq [x (.raw cuke-table)] (eat (Float. (first x))))) 20 | 21 | (When #"^there are (\d+) cukes in my belly$" [expected] 22 | (assert (= (last-meal) (Float. expected)))) 23 | 24 | (Then #"^the (.*) contains (.*)$" [container ingredient] 25 | (assert (= "glass" container))) 26 | 27 | (When #"^I add (.*)$" [liquid] 28 | (assert (= "milk" liquid))) 29 | 30 | (Given #"^(\d+) unimplemented step$" [arg1] 31 | (comment Express the Regexp above with the code you wish you had ) 32 | (throw (cucumber.api.PendingException. "This is pending. Seeing a stacktrace here is normal."))) 33 | 34 | (def most-recent (atom nil)) 35 | 36 | (Given #"^I have a kv table:$" [data] 37 | (reset! most-recent (kv-table->map data))) 38 | 39 | (Given #"^I have a table with its keys in a header row:$" [data] 40 | (reset! most-recent (table->rows data))) 41 | 42 | (Then #"^the clojure literal equivalent should be:$" [literal-as-string] 43 | (assert (= @most-recent (read-string literal-as-string)))) 44 | -------------------------------------------------------------------------------- /clojure/src/test/resources/cucumber/runtime/clojure/tables.feature: -------------------------------------------------------------------------------- 1 | Feature: tables 2 | 3 | Scenario: a key-value table 4 | Given I have a kv table: 5 | | my-first-key | 1 | 6 | | another-key | "a string" | 7 | | yak | :a-kw | 8 | Then the clojure literal equivalent should be: 9 | """ 10 | {:my-first-key 1, :another-key "a string", :yak :a-kw} 11 | """ 12 | 13 | Scenario: a table 14 | Given I have a table with its keys in a header row: 15 | | id | name | created-at | 16 | | 55 | "foo" | 1293884100000 | 17 | | 56 | "bar" | 1293884100000 | 18 | Then the clojure literal equivalent should be: 19 | """ 20 | [{:id 55, :name "foo", :created-at 1293884100000} 21 | {:id 56, :name "bar", :created-at 1293884100000}] 22 | """ 23 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # clojure-cukes 2 | 3 | Just a little example illustrating how to use Cucumber with Clojure and Leiningen. 4 | 5 | Please note that the example uses [lein-cucumber](https://github.com/nilswloka/lein-cucumber), which requires Leiningen 2. 6 | 7 | ## Running cukes 8 | 9 | ``` 10 | lein deps 11 | lein cucumber 12 | ``` -------------------------------------------------------------------------------- /examples/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.cucumber 7 | cucumber-jvm-clojure 8 | 2.0.2-SNAPSHOT 9 | 10 | 11 | clojure-examples 12 | clojure 13 | Cucumber Clojure Examples 14 | A demo of Cucumber with Clojure 15 | 16 | test/java 17 | 18 | 19 | test/features 20 | features 21 | 22 | 23 | 24 | 25 | com.theoryinpractise 26 | clojure-maven-plugin 27 | 1.8.1 28 | true 29 | 30 | 31 | src 32 | 33 | 34 | test/java 35 | 36 | 37 | 38 | 39 | maven-deploy-plugin 40 | 41 | true 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.clojure 49 | clojure 50 | 51 | 52 | io.cucumber 53 | cucumber-clojure 54 | test 55 | 56 | 57 | io.cucumber 58 | cucumber-junit 59 | test 60 | 61 | 62 | junit 63 | junit 64 | test 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /examples/project.clj: -------------------------------------------------------------------------------- 1 | (defproject clojure_cukes "1.0.X" 2 | :description "A demo of Cucumber with Clojure and Leiningen" 3 | :dependencies [[org.clojure/clojure "1.8.0"]] 4 | :plugins [[com.siili/lein-cucumber "1.0.7"]] 5 | :cucumber-feature-paths ["test/features/"] 6 | :profiles 7 | {:dev 8 | {:dependencies [[com.siili/lein-cucumber "1.0.7"]]}} 9 | ) 10 | -------------------------------------------------------------------------------- /examples/src/clojure_cukes/core.clj: -------------------------------------------------------------------------------- 1 | (ns clojure-cukes.core) 2 | 3 | (def belly (atom [])) 4 | 5 | (defn mood [] 6 | (let [cukes (->> @belly 7 | (filter #(= "cukes" %)) 8 | count)] 9 | (cond 10 | (> cukes 3) :happy 11 | (= cukes 2) :meh 12 | (= cukes 1) :sad 13 | :else :hungry))) 14 | 15 | (defn eat [things] 16 | (swap! belly concat things)) 17 | -------------------------------------------------------------------------------- /examples/test/clojure_cukes/test/core.clj: -------------------------------------------------------------------------------- 1 | (ns clojure-cukes.test.core 2 | (:use [clojure-cukes.core]) 3 | (:use [clojure.test]) 4 | (:use [leiningen.cucumber]) 5 | (:import [cucumber.api.cli Main])) 6 | 7 | (deftest run-cukes 8 | (. cucumber.api.cli.Main (main (into-array ["--format" "pretty" "--glue" "test" "test/features"])))) 9 | -------------------------------------------------------------------------------- /examples/test/features/cukes.feature: -------------------------------------------------------------------------------- 1 | Feature: Cukes 2 | An example of testing Clojure with cucumber. To see a failure try changing 3 | the last 'Then' of 'eat 1 cuke' "meh" to "happy". 4 | 5 | Scenario: in the belly 6 | Given I have 4 big "cukes" in my belly 7 | Then I am "happy" 8 | 9 | Scenario: eat 1 cuke 10 | Given I have 0 big "cukes" in my belly 11 | Then I am "hungry" 12 | When I eat 1 "cukes" 13 | Then I am "sad" 14 | When I eat 1 "cukes" 15 | Then I am "meh" 16 | -------------------------------------------------------------------------------- /examples/test/features/step_definitions/cuke_steps.clj: -------------------------------------------------------------------------------- 1 | (use 'clojure-cukes.core) 2 | (use 'clojure.test) 3 | 4 | (Given #"^I have (\d+) big \"([^\"]*)\" in my belly$" [n, thing] 5 | (reset! belly (repeat (read-string n) thing))) 6 | 7 | (When #"I eat (\d+) \"([^\"]*)\"" [n, thing] 8 | (eat (repeat (read-string n) thing))) 9 | 10 | (Then #"^I am \"([^\"]*)\"$" [mood-name] 11 | (assert (= (name (mood)) mood-name))) 12 | -------------------------------------------------------------------------------- /examples/test/java/features/RunCukesTest.java: -------------------------------------------------------------------------------- 1 | package features; 2 | 3 | import cucumber.api.CucumberOptions; 4 | import cucumber.api.junit.Cucumber; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(Cucumber.class) 8 | @CucumberOptions(format = {"pretty", "html:target/cucumber", "rerun:target/rerun.txt"}) 9 | public class RunCukesTest { 10 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | io.cucumber 4 | cucumber-jvm-clojure 5 | 2.0.2-SNAPSHOT 6 | pom 7 | Cucumber JVM Clojure 8 | http://cucumber.io/ 9 | 10 | 11 | org.sonatype.oss 12 | oss-parent 13 | 7 14 | 15 | 16 | 17 | ${minimum.maven.version} 18 | 19 | 20 | 21 | UTF-8 22 | UTF-8 23 | 3.3 24 | ${project.build.directory} 25 | 26 | 27 | 1.8.0 28 | 2.0.1 29 | 4.12 30 | 31 | 32 | 33 | 34 | MIT License 35 | http://www.opensource.org/licenses/mit-license 36 | repo 37 | 38 | 39 | 40 | scm:git:git://github.com/cucumber/cucumber-jvm.git 41 | scm:git:git@github.com:cucumber/cucumber-jvm.git 42 | git://github.com/cucumber/cucumber-jvm.git 43 | cucumber-jvm-2.0.0 44 | 45 | 46 | 47 | 48 | 49 | org.clojure 50 | clojure 51 | ${clojure.version} 52 | 53 | 54 | io.cucumber 55 | cucumber-clojure 56 | ${project.version} 57 | 58 | 59 | io.cucumber 60 | cucumber-core 61 | ${cucumber.version} 62 | 63 | 64 | io.cucumber 65 | cucumber-junit 66 | ${cucumber.version} 67 | 68 | 69 | junit 70 | junit 71 | ${junit.version} 72 | 73 | 74 | 75 | 76 | 80 | 81 | 82 | sonatype.org 83 | https://oss.sonatype.org/content/repositories/releases 84 | 85 | 86 | 87 | 88 | clojure 89 | examples 90 | 91 | 92 | 93 | 94 | release-sign-artifacts 95 | 96 | 97 | performRelease 98 | true 99 | 100 | 101 | 102 | 103 | 104 | org.apache.maven.plugins 105 | maven-release-plugin 106 | 107 | v@{project.version} 108 | 109 | 110 | 111 | 112 | org.apache.maven.plugins 113 | maven-gpg-plugin 114 | 115 | true 116 | 117 | 118 | 119 | sign-artifacts 120 | verify 121 | 122 | sign 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | travis-disable-deploy-by-default 134 | 135 | false 136 | 137 | env.TRAVIS 138 | true 139 | 140 | 141 | 142 | true 143 | 144 | 145 | 146 | travis-enable-deploy-if-not-pull-request 147 | 148 | false 149 | 150 | env.TRAVIS_PULL_REQUEST 151 | false 152 | 153 | 154 | 155 | false 156 | 157 | 158 | 159 | coveralls.io 160 | 161 | 162 | 163 | 164 | org.codehaus.mojo 165 | cobertura-maven-plugin 166 | ${cobertura-maven-plugin.version} 167 | 168 | 169 | xml 170 | 171 | 172 | true 173 | 174 | true 175 | 176 | 177 | 178 | 179 | 180 | org.eluder.coveralls 181 | coveralls-maven-plugin 182 | 4.3.0 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | org.apache.maven.plugins 196 | maven-clean-plugin 197 | 3.0.0 198 | 199 | 200 | 201 | . 202 | 203 | **/*.ser 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | org.apache.maven.plugins 212 | maven-compiler-plugin 213 | 3.6.2 214 | 215 | UTF-8 216 | 1.6 217 | 1.6 218 | -Werror 219 | 220 | 221 | 222 | 223 | org.apache.maven.plugins 224 | maven-gpg-plugin 225 | 1.6 226 | 227 | 228 | 229 | org.apache.maven.plugins 230 | maven-javadoc-plugin 231 | 3.0.0-M1 232 | 233 | false 234 | cucumber.runtime,cucumber.runtime.* 235 | 236 | http://docs.oracle.com/javase/7/docs/api/ 237 | http://junit.sourceforge.net/javadoc/ 238 | 239 | 240 | 241 | Main API Packages 242 | cucumber.api:cucumber.api.* 243 | 244 | 245 | I18n - Java 246 | cucumber.api.java.* 247 | 248 | 249 | 250 | java 251 | 252 | 253 | 254 | 255 | org.apache.maven.plugins 256 | maven-jar-plugin 257 | 3.0.2 258 | 259 | 260 | 261 | org.apache.maven.plugins 262 | maven-project-info-reports-plugin 263 | 2.9 264 | 265 | 266 | 267 | org.apache.maven.plugins 268 | maven-release-plugin 269 | 2.5.3 270 | 271 | 272 | 273 | org.apache.maven.plugins 274 | maven-site-plugin 275 | 3.6 276 | 277 | 278 | 279 | org.apache.maven.plugins 280 | maven-resources-plugin 281 | 3.0.2 282 | 283 | 284 | 285 | org.apache.maven.plugins 286 | maven-source-plugin 287 | 3.0.1 288 | 289 | 290 | bind-sources 291 | 292 | jar 293 | 294 | 295 | 296 | 297 | 298 | 299 | org.apache.maven.plugins 300 | maven-surefire-plugin 301 | 2.20 302 | 303 | -Duser.language=en 304 | -Xmx1024m 305 | -XX:MaxPermSize=256m 306 | -Dfile.encoding=UTF-8 307 | false 308 | 309 | 310 | 311 | 312 | 313 | com.theoryinpractise 314 | clojure-maven-plugin 315 | 1.8.1 316 | 317 | 318 | org.apache.maven.plugins 319 | maven-deploy-plugin 320 | 2.8.2 321 | 322 | 323 | org.apache.maven.plugins 324 | maven-install-plugin 325 | 2.5.2 326 | 327 | 328 | org.apache.maven.plugins 329 | maven-enforcer-plugin 330 | 3.0.0-M1 331 | 332 | 333 | 334 | 335 | 336 | 337 | org.apache.maven.plugins 338 | maven-enforcer-plugin 339 | 340 | 341 | enforce 342 | 343 | 344 | 345 | 1.7.0-9 346 | 347 | 348 | [${minimum.maven.version},) 349 | 350 | 351 | Best Practice is to always define plugin versions! 352 | true 353 | true 354 | true 355 | clean,deploy,site 356 | org.codehaus.mojo 357 | 358 | 359 | 360 | commons-logging 361 | 362 | log4j 363 | 364 | 365 | 366 | 367 | 368 | 369 | enforce 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | org.apache.maven.wagon 379 | wagon-ssh 380 | 2.10 381 | 382 | 383 | 384 | 385 | --------------------------------------------------------------------------------