{"id":29097389,"url":"https://github.com/lambdaisland/kaocha-cucumber","last_synced_at":"2026-03-14T17:46:06.247Z","repository":{"id":41435432,"uuid":"155923859","full_name":"lambdaisland/kaocha-cucumber","owner":"lambdaisland","description":"Cucumber support for Kaocha","archived":false,"fork":false,"pushed_at":"2023-05-08T16:41:43.000Z","size":121,"stargazers_count":41,"open_issues_count":3,"forks_count":11,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-06-08T21:35:38.319Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lambdaisland.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2018-11-02T21:34:42.000Z","updated_at":"2025-05-01T13:53:51.000Z","dependencies_parsed_at":"2024-04-17T14:20:24.112Z","dependency_job_id":null,"html_url":"https://github.com/lambdaisland/kaocha-cucumber","commit_stats":{"total_commits":91,"total_committers":10,"mean_commits":9.1,"dds":"0.37362637362637363","last_synced_commit":"0414b33d55b83e33bbbcfc1bc8e27b6479bd72c5"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/lambdaisland/kaocha-cucumber","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaisland%2Fkaocha-cucumber","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaisland%2Fkaocha-cucumber/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaisland%2Fkaocha-cucumber/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaisland%2Fkaocha-cucumber/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lambdaisland","download_url":"https://codeload.github.com/lambdaisland/kaocha-cucumber/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaisland%2Fkaocha-cucumber/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260159093,"owners_count":22967332,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-28T13:42:06.291Z","updated_at":"2026-03-14T17:46:01.205Z","avatar_url":"https://github.com/lambdaisland.png","language":"Clojure","funding_links":["http://opencollective.com/lambda-island"],"categories":[],"sub_categories":[],"readme":"# lambdaisland/kaocha-cucumber\n\n\u003c!-- badges --\u003e\n[![CircleCI](https://circleci.com/gh/lambdaisland/kaocha-cucumber.svg?style=svg)](https://circleci.com/gh/lambdaisland/kaocha-cucumber) [![cljdoc badge](https://cljdoc.org/badge/lambdaisland/kaocha-cucumber)](https://cljdoc.org/d/lambdaisland/kaocha-cucumber) [![Clojars Project](https://img.shields.io/clojars/v/lambdaisland/kaocha-cucumber.svg)](https://clojars.org/lambdaisland/kaocha-cucumber) [![codecov](https://codecov.io/gh/lambdaisland/kaocha-cucumber/branch/master/graph/badge.svg)](https://codecov.io/gh/lambdaisland/kaocha-cucumber)\n\u003c!-- /badges --\u003e\n\nKaocha support for Cucumber tests.\n\n[Cucumber](https://cucumber.io) is a \"Behavior Driven Development\" tool, a way\nto write \"feature\" tests in a human readable format known as Gherkin syntax.\n\nThis project adds Cucumber support to\n[Kaocha](https://github.com/lambdaisland/kaocha), allowing to write and Cucumber\ntests using Clojure.\n\n## Getting started\n\nThis assumes you already have Kaocha setup, including a `tests.edn` and\n`bin/kaocha` wrapper.\n\nStart by adding `lambdaisland/kaocha-cucumber` to your project,\n\n``` clojure\n;; deps.edn\n{:paths [,,,]\n :deps {,,,}\n :aliases\n {:test {:extra-deps {lambdaisland/kaocha { ,,, }\n                      lambdaisland/kaocha-cucumber { ,,, }}}}}\n```\n\nCreate a directory which will contain your Cucumber tests (`*.feature` files),\nand one which will contain step definitions (`*.clj` files).\n\n``` shell\nmkdir -p test/features test/steps_definitions\n```\n\nNow add a Cucumber test suite to `tests.edn`\n\n``` clojure\n#kaocha/v1\n{:tests [{:id           :unit\n          :type         :kaocha.type/clojure.test\n          :source-paths [\"src\"]\n          :test-paths   [\"test/unit\"]}\n\n         {:id                  :features\n          :type                :kaocha.type/cucumber\n          :source-paths        [\"src\"]\n          :test-paths          [\"test/features\"]\n          :cucumber/glue-paths [\"test/steps_definitions\"]\n          :cucumber/locale     \"de-DE\"  ; optional. Currently only for number\n                                        ; format parsing, passed to\n                                        ; java.util.Locale/forLanguageTag\n          }]}\n```\n\nFinally create a file `test/features/coffeeshop.feature` with the following contents\n\n``` feature\nFeature: Coffee shop order fulfilment\n\n  The coffee shop contains a counter where people can place orders.\n\n  Background:\n    Given the following price list\n      | Matcha Latte | 4.00 |\n      | Green Tea    | 3.50 |\n\n  Scenario: Getting change\n    When I order a Matcha Latte\n    And pay with $5.00\n    Then I get $1.00 back\n```\n\nAnd run it\n\n``` shell\nbin/kaocha features\n```\n\nSince the steps aren't implemented yet, Kaocha will tell you what you're\nmissing.\n\n```\n$ bin/kaocha features\n[(P)]\n\nPENDING in test.features.coffeeshop/line-10 (test/features/coffeeshop.feature:10)\nYou can implement missing steps with the snippets below:\n(When \"I order a Matcha Latte\" [state]\n  ;; Write code here that turns the phrase above into concrete actions\n  (pending!))\n\n(And \"pay with ${double}\" [state double1]\n  ;; Write code here that turns the phrase above into concrete actions\n  (pending!))\n\n(Then \"I get ${double} back\" [state double1]\n  ;; Write code here that turns the phrase above into concrete actions\n  (pending!))\n\n1 tests, 0 assertions, 1 pending, 0 failures.\n```\n\nCreate a file `test/step_definitions/coffeeshop_steps.clj`, copy the sample code\nsnippets over, and add a namespace declaration, pulling in\n`lambdaisland.cucumber.dsl` and `clojure.test`.\n\n\n``` clojure\n(ns coffeeshop-steps\n  (:require [lambdaisland.cucumber.dsl :refer :all]\n            [clojure.test :refer :all]))\n\n(Given \"the following price list\" [state table]\n  (assoc state\n         :price-list\n         (into {}\n               (map (fn [[k v]]\n                      [k (Double/parseDouble v)]))\n               table)))\n\n(When \"I order a (.*)\" [state product]\n  (update state :order conj product))\n\n(And \"pay with ${double}\" [{:keys [price-list order] :as state} paid]\n  (doseq [product order]\n    (is (contains? price-list product)))\n\n  (let [total (apply + (map price-list order))]\n    (is (\u003c= total paid))\n\n    (assoc state\n           :total total\n           :paid paid\n           :change (- paid total))))\n\n(Then \"I get ${double} back\" [{:keys [change] :as state} expected]\n  (is (= expected change))\n  state)\n```\n\nEach [step](https://docs.cucumber.io/cucumber/step-definitions/) is followed by\na pattern, a string which is interpreted as either a [regular\nexpression](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)\nor a [Cucumber\nexpression](https://docs.cucumber.io/cucumber/cucumber-expressions/), and then\nfollowed by an argument list (binding form) and a function body.\n\nThe first argument is always the current state. This is a map that is passed\nfrom one step to the next as it is executed. The first step receives an empty\nmap, the next step receives the return value from the first step, etc.\n\nAny remaining arguments correspond with capturing groups or \"output parameters\"\nin the pattern.\n\nInside the step definitions you use `clojure.test` style assertions.\n\nHere's the complete file structure of this example:\n\n```\n.\n├── bin\n│   └── kaocha\n├── deps.edn\n├── test\n│   ├── features\n│   │   └── coffeeshop.feature\n│   └── step_definitions\n│       └── coffeeshop_steps.clj\n└── tests.edn\n```\n## Running through a REPL\n\nWhen running through a REPL, we need to disable the glue-cache. Otherwise, after \nwe change the **steps_definitions**, we will still run the old steps.\n\nThe disable command is `(reset! lambdaisland.cucumber.jvm/glue-cache nil)`.\n\nExample:\n\n```\nClojure 1.10.3\nOpenJDK 64-Bit Server VM 17.0.6+10-LTS\nInterrupt: Control+C\nExit:      Control+D or (exit) or (quit)\nuser=\u003e (require '[lambdaisland.cucumber.jvm])\nnil\nuser=\u003e (require '[kaocha.repl :as k])\nnil\n;; First time to run\nuser=\u003e (k/run :features)\n\nPENDING in coffeeshop/getting-change (test/features/coffeeshop.feature:10)\nYou can implement missing steps with the snippets below:\n(Then \"I get ${double} back\" [state double1]\n  ;; Write code here that turns the phrase above into concrete actions\n  (pending!))\n\n1 tests, 2 assertions, 1 pending, 0 failures.\n\nPENDING coffeeshop/getting-change (test/features/coffeeshop.feature:10)\n#:kaocha.result{:count 1, :pass 2, :error 0, :fail 0, :pending 1}\n\n;; Now, we change the steps_definitions\n;; We need to disable the glue-cacahe before re-run\nuser=\u003e (reset! lambdaisland.cucumber.jvm/glue-cache nil)\nnil\nuser=\u003e (k/run :features)\n]\nRandomized with --seed 279015433\n\nFAIL in coffeeshop/getting-change (test/features/coffeeshop.feature:13)\nI get $1.00 back\nExpected:\n  100.0\nActual:\n  -100.0 +496.0\n1 tests, 3 assertions, 1 failures.\n#:kaocha.result{:count 1, :pass 2, :error 0, :fail 1, :pending 0}\n```\n## Tags\n\nFollowing standard [Gherkin\nsyntax](https://cucumber.io/docs/cucumber/api/?lang=java#tags), you may add tags\nby prefixing them with `@`. For example, you could add a `@customer-facing` tag\nto the previous `test/features/coffeeshop.feature`.\n\nThis would tag the whole feature with `@customer-facing`:\n\n\n``` feature\n@customer-facing\nFeature: Coffee shop order fulfilment\n```\n\nThis would tag a scenario with `@customer-facing`:\n\n```\n@customer-facing\n  Scenario: Getting change\n```\n\nThen, you can use `--focus-meta` or `--skip-meta` in order to select only tagged\ntests or skip them respectively:\n\n```\nbin/kaocha --focus-meta customer-facing\n```\n\n## Parameter Types\n\nData tables will be converted to a vector of vectors, other types will be passed\non as-is.\n\nTo implement [Custom Parameter\nTypes](https://docs.cucumber.io/cucumber/cucumber-expressions/#custom-parameter-types),\nadd a `:cucumber/parameter-types` to your config.\n\n``` clojure\n#kaocha/v1\n{:tests [{:id :cukes\n          :type :kaocha.type/cucumber\n          :source-paths [\"src\"]\n          :test-paths [\"test/features\" \"test/support\"]\n          :cucumber/glue-paths [\"test/step_definitions\"]\n          :cucumber/parameter-types\n          [#:cucumber.parameter\n           {:name \"color\"\n            :regexp \"red|blue|yellow|green\"\n            :class kaocha.cucumber.extra_types.Color\n            :transformer kaocha.cucumber.extra-types/parse-color}]}]}\n```\n\nFollowing keys are understood\n\n``` clojure\n:cucumber.parameter/name                     ;;=\u003e string?\n:cucumber.parameter/transformer              ;;=\u003e qualified-symbol?\n:cucumber.parameter/regexp                   ;;=\u003e string?\n:cucumber.parameter/class                    ;;=\u003e simple-symbol?\n:cucumber.parameter/suggest?                 ;;=\u003e boolean?\n:cucumber.parameter/prefer-for-regexp-match? ;;=\u003e boolean?\n```\n\n## Relationship with cucumber-jvm-clojure / lein-cucumber\n\nThe existing `cucumber-jvm-clojure` and `lein-cucumber` are based on a very old\nversion of `cucumber-jvm`, and appear to be unmaintained. Because of this\n`kaocha-cucumber` is built directly on top of `cucumber-jvm`. Some of the code\nin `lambdaisland.cucumber.jvm` and `lambdaisland.cucumber.dsl` is adapted from\nthese earlier projects.\n\nIf you are migrating existing code bases then note that the DSL syntax is\ndifferent. Patterns are given as strings, not regular expressions, the first\n\"state\" argument is a new introduction, and certain argument types are coerced\nto Clojure types now.\n\nIf you have a code base of significant size based on these legacy projects then\nplease open a ticket, we might be able to create a separate legacy DSL namespace\nthat's compatible with old tests.\n\n\u003c!-- opencollective --\u003e\n## Lambda Island Open Source\n\n\u003cimg align=\"left\" src=\"https://github.com/lambdaisland/open-source/raw/master/artwork/lighthouse_readme.png\"\u003e\n\n\u0026nbsp;\n\nkaocha-cucumber is part of a growing collection of quality Clojure libraries created and maintained\nby the fine folks at [Gaiwan](https://gaiwan.co).\n\nPay it forward by [becoming a backer on our Open Collective](http://opencollective.com/lambda-island),\nso that we may continue to enjoy a thriving Clojure ecosystem.\n\nYou can find an overview of our projects at [lambdaisland/open-source](https://github.com/lambdaisland/open-source).\n\n\u0026nbsp;\n\n\u0026nbsp;\n\u003c!-- /opencollective --\u003e\n\n\u003c!-- contributing --\u003e\n## Contributing\n\nEveryone has a right to submit patches to kaocha-cucumber, and thus become a contributor.\n\nContributors MUST\n\n- adhere to the [LambdaIsland Clojure Style Guide](https://nextjournal.com/lambdaisland/clojure-style-guide)\n- write patches that solve a problem. Start by stating the problem, then supply a minimal solution. `*`\n- agree to license their contributions as MPL 2.0.\n- not break the contract with downstream consumers. `**`\n- not break the tests.\n\nContributors SHOULD\n\n- update the CHANGELOG and README.\n- add tests for new functionality.\n\nIf you submit a pull request that adheres to these rules, then it will almost\ncertainly be merged immediately. However some things may require more\nconsideration. If you add new dependencies, or significantly increase the API\nsurface, then we need to decide if these changes are in line with the project's\ngoals. In this case you can start by [writing a pitch](https://nextjournal.com/lambdaisland/pitch-template),\nand collecting feedback on it.\n\n`*` This goes for features too, a feature needs to solve a problem. State the problem it solves, then supply a minimal solution.\n\n`**` As long as this project has not seen a public release (i.e. is not on Clojars)\nwe may still consider making breaking changes, if there is consensus that the\nchanges are justified.\n\u003c!-- /contributing --\u003e\n\n\u003c!-- license --\u003e\n## License\n\nCopyright \u0026copy; 2019-2021 Arne Brasseur and Contributors\n\nLicensed under the term of the Eclipse Public License 1.0, see LICENSE.txt.\n\u003c!-- /license --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flambdaisland%2Fkaocha-cucumber","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flambdaisland%2Fkaocha-cucumber","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flambdaisland%2Fkaocha-cucumber/lists"}