{"id":28629612,"url":"https://github.com/schmorgurken/schmorgurken","last_synced_at":"2025-06-12T12:10:09.929Z","repository":{"id":62434578,"uuid":"105706523","full_name":"schmorgurken/schmorgurken","owner":"schmorgurken","description":"Clojure Gherkin testing library compatible with Cucumber","archived":false,"fork":false,"pushed_at":"2019-10-14T16:58:20.000Z","size":27,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-10T01:06:37.599Z","etag":null,"topics":["clojure","clojure-library","cucumber","dsl","gherkin","testing","testing-tool"],"latest_commit_sha":null,"homepage":"","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/schmorgurken.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-03T21:41:52.000Z","updated_at":"2025-04-04T17:42:45.000Z","dependencies_parsed_at":"2022-11-01T21:02:28.274Z","dependency_job_id":null,"html_url":"https://github.com/schmorgurken/schmorgurken","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/schmorgurken/schmorgurken","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schmorgurken%2Fschmorgurken","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schmorgurken%2Fschmorgurken/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schmorgurken%2Fschmorgurken/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schmorgurken%2Fschmorgurken/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/schmorgurken","download_url":"https://codeload.github.com/schmorgurken/schmorgurken/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schmorgurken%2Fschmorgurken/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259462559,"owners_count":22861512,"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":["clojure","clojure-library","cucumber","dsl","gherkin","testing","testing-tool"],"created_at":"2025-06-12T12:10:09.336Z","updated_at":"2025-06-12T12:10:09.915Z","avatar_url":"https://github.com/schmorgurken.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# schmorgurken\n\nSchmorgurken is a [Gherkin language](https://en.wikipedia.org/wiki/Cucumber_(software)#Gherkin_.28Language.29)\nbased [Behaviour Driven Development](https://en.wikipedia.org/wiki/Behavior-driven_development) \ntesting tool for Clojure that is broadly compatible with \n[Cucumber](https://github.com/cucumber/cucumber).\n\nTests are written in a plain language format that is accessible to both the developer and user\nand forms a common ground for establishing and validating the behaviour of a system.\n\n## Installation\n\n[![Clojars Project](https://img.shields.io/clojars/v/schmorgurken.svg)](https://clojars.org/schmorgurken)\n\nTo install Schmorgurken, just add the following to your `project.clj` dependencies\n\n```clojure\n[schmorgurken.schmorgurken \"0.1.2\"]\n```\n\n### Requirements\n\nSchmorgurken is built and tested with Clojure 1.10 and JDK 8 although it should work with \nearlier versions.  \n\n### Clojurescript support\n\nCurrently there is no support for Clojurescript although this may be added in a future\nrelease.\n\n\n## Getting started\n\nThis is not intended to be a full tutorial to learn Gherkin, so only the essentials\nare covered here.\n\n### Running \n\nSchmorgurken embraces the standard core Clojure testing library (clojure.test) and hence tests \ncan be run using the standard **lein test** command.\n\n### Features\nA *feature file* contains a single *Feature* element which *must* be the first \nsyntactic element in the feature file.  The keyword *Feature:* may be followed by a \nshort description which can continue over several lines.  The descriptive text is ignored.\n \n```gherkin\nFeature: FX Trading feature\n         Open Position - In order to open a position\n         As a trader\n         I want to send a trade order\n```\n\n### Scenarios\nA *scenario* describes a functional test case. The keyword *Scenario:* may be followed \nby a short description. A feature may have multiple scenarios. Each scenario contains \none or more *steps*.\n\n```gherkin\nScenario: Market Order\n    Given that my position in EURUSD is 0 at 1.34700\n    And the market for EURUSD is at [1.34662;1.34714]\n    When I submit an order to BUY 1000000 EURUSD at MKT\n    Then a trade should be made at 1.34714\n    And my position should show LONG 1000000 EURUSD at 1.34714\n```\n\n### Steps\nSteps are defined by one of the keywords - *Given*, *When*, *Then* or *And*.  \nSchmorgurken considers them all equivalent, but the scenario should use the keywords\nappropriately to describe the setting up (*Given*), running the testing scenario (*When*)\nand the validation (*Then*). \n\n### Connecting the steps to the code\n\nHaving defined a behavioural specification, the feature is connected to the code to be \ntested by a *step definition handler* (sometimes shortened to *\"stepdef\"*).\n\n```clojure\n(ns schmorgurken.full-test\n  (:require [clojure.test :refer :all])\n  (:use (schmorgurken core)))\n```\n\nIn order to create the best readability it is recommended to \"use\" the library\nrather than \"require\" it.\n\nThere are five functions that are used in writing step definition handlers to link the\nfeature file to the code to be tested - *Feature, Given, When, Then,* and *And* which should\ncorrespond to the usage in the feature file.\n\nThe *Feature* function takes the parameters - \n\n* A location from which to load the feature file.  Schmorgurken loads feature files from the classpath and \nmay refer to either one specific file or a directory.  If a directory is specified \nthen all files a loaded recursively from that point.\n* One or more step definitions specified by the functions *Given, When, Then,* or *And*\n\nEach of the step definitions takes a regular expression (regex) to match and the function \nthat should then be called given the match.  Parameters extracted from the match are passed\nto the function, so the arity of the function must match the number of capture groups\nin the regex, plus one extra to pass through the state.\n\n### Regex as glue\nRegular expressions are used to match text elements in the feature file to link to the stepdef handlers\nin the test code.  Parameters in the step definitions can be extracted by match groups in the regex\ndefinition.\n\n### State\n\nEach step handler function *must* have an extra parameter (which is always the first) which\nwill hold the return value from the previous function.  This allows step handler functions to \navoid having to store global state in an atom between each step handler call-back.\n \n### Example\n\nThis example will match the Market Order scenario specified earlier - \n\n```clojure\n(Feature \"features/trade.feature\"\n         (Given #\"^that my position in (.*) is 0 at (.*)$\" \n                (fn [_ currency-pair rate] ... ))\n         \n         (And #\"^the market for (.*) is at \\[(.*);(.*)\\]$\" \n              (fn [return-from-given currency-pair buy sell] ... ))\n         \n         (When #\"^I submit an order to (.*) (.*) (.*) at (.*)$\", \n               (fn [return-from-and dirn qty currency-pair type] ... ))\n         \n         (Then #\"^a trade should be made at (.*)$\", \n               (fn [return-from-when price] ... ))\n         \n         (And #\"^my position should show (.*) (.*) (.*) at (.*)$\", \n              (fn [return-from-then pos-dirn qty currency-pair price] ...)))\n\n```\n\n### Scenario Outlines\nIn order to avoid extensive repetition in the feature file, scenario outlines enable\nspecification of multiple examples using the same scenario steps.\nA table of data defines each of the examples to be tested in the step definitions.  Again, a \n*Scenario Outline:* may have an optional description.\n\nA *Scenario Outline:* is followed by the step definitions and finally by a table of \ndata which indicated by the keyword *Examples:*.\n\n```gherkin\nFeature: Feed planning\n  Scenario Outline: feeding a suckler cow\n    Given the cow weighs \u003cweight\u003e kg\n    When we calculate the feeding requirements\n    Then the energy should be \u003cenergy\u003e MJ\n    And the protein should be \u003cprotein\u003e kg\n    Examples:\n      | weight | energy | protein |\n      | 450    | 26500  | 215     |\n      | 500    | 29500  | 245     |\n      | 575    | 31500  | 255     |\n      | 600    | 37000  | 305     |\n```\n\nThis example is semantically equivalent to -\n\n```gherkin\nFeature: Feed planning\n  Scenario: feeding a suckler cow\n    Given the cow weighs 450 kg\n    When we calculate the feeding requirements\n    Then the energy should be 26500 MJ\n    And the protein should be 215 kg\n\nScenario: feeding a suckler cow\n    Given the cow weighs 500 kg\n    When we calculate the feeding requirements\n    Then the energy should be 29500 MJ\n    And the protein should be 245 kg\n\nScenario: feeding a suckler cow\n    Given the cow weighs 575 kg\n    When we calculate the feeding requirements\n    Then the energy should be 31500 MJ\n    And the protein should be 255 kg\n\nScenario: feeding a suckler cow\n    Given the cow weighs 600 kg\n    When we calculate the feeding requirements\n    Then the energy should be 37000 MJ\n    And the protein should be 305 kg\n```\n\n### Tables\nTables in Schmorgurken are pipe-character delimited.  As the table is parsed, the \nelements are stripped of leading and trailing spaces.\n\nThe first row is the title row and defines the parameter names.\n\nMultiple data rows follow the title row.  Data rows may also contain 'Special' \ncharacters may be escaped with a backslash.  Supported characters are - \n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003eEscape\u003c/th\u003e\u003cth\u003eCharacter\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\\|\u003c/td\u003e\u003ctd\u003ePipe character\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\\n\u003c/td\u003e\u003ctd\u003eNew line\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\\t\u003c/td\u003e\u003ctd\u003eTab\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\\b\u003c/td\u003e\u003ctd\u003eBackspace\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\\r\u003c/td\u003e\u003ctd\u003eReturn\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\\f\u003c/td\u003e\u003ctd\u003eFormfeed\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\\ + space\u003c/td\u003e\u003ctd\u003eforce a space character (useful at the end or start of a field)\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\nAn example of a (deliberately poorly formatted) table is -\n\n```gherkin\n| field1 | field2 |\n|  hello  | fred   |\n| goodbye       | bill    |\n```\n\nThe data will be trimmed of spaces and hence the data will actually be as follows -\n\n```clojure\n'({\"field1\" \"hello\", \"field2\" \"fred\"} \n  {\"field1\" \"goodbye\", \"field2\" \"bill\"})\n```\n\nIf you want to avoid the trimming, then you may escape the spaces with a backslash.\n\n### Backgrounds\nOne or more *Background:* elements may be added to the file.  The syntax and structure \nfollows that of a *Scenario*, but the background is run before each *Scenario:* or \n*Scenario Outline:* in the feature file.\n\nIn this example, the four steps in the background will be run before each of the \nscenarios in the feature file -\n\n```gherkin\nFeature: Multiple site support\n\n  Background:\n    Given a global administrator named \"Greg\"\n    And a blog named \"Greg's anti-tax rants\"\n    And a customer named \"Wilson\"\n    And a blog named \"Expensive Therapy\" owned by \"Wilson\"\n\n  Scenario: Wilson posts to his own blog\n    Given I am logged in as Wilson\n    When I try to post to \"Expensive Therapy\"\n    Then I should see \"Your article was published.\"\n\n  Scenario: Greg posts to a client's blog\n    Given I am logged in as Greg\n    When I try to post to \"Expensive Therapy\"\n    Then I should see \"Your article was published.\"\n```\n\nThis is semantically equivalent to - \n\n```gherkin\nFeature: Multiple site support\n\n  Scenario: Wilson posts to his own blog\n    Given a global administrator named \"Greg\"\n    And a blog named \"Greg's anti-tax rants\"\n    And a customer named \"Wilson\"\n    And a blog named \"Expensive Therapy\" owned by \"Wilson\"\n    Given I am logged in as Wilson\n    When I try to post to \"Expensive Therapy\"\n    Then I should see \"Your article was published.\"\n\n  Scenario: Greg posts to a client's blog\n    Given a global administrator named \"Greg\"\n    And a blog named \"Greg's anti-tax rants\"\n    And a customer named \"Wilson\"\n    And a blog named \"Expensive Therapy\" owned by \"Wilson\"\n    Given I am logged in as Greg\n    When I try to post to \"Expensive Therapy\"\n    Then I should see \"Your article was published.\"\n```\n\n## Multiple line arguments\n\nMultiple line arguments are supported in both *Scenario:* and *Background:* statements,\nbut not in a *Scenario Outline:*.  They come in two flavours - pystrings and tables.  In \neither case the step handler function will have an arity of 2 and the extra information\nit passed in as a single piece of data.\n\n### Pystrings\nPystrings are multiple line pre-formatted strings that conform to the Python Pystring\nsyntax - the text should be delimited by triple quotes (`\"\"\"`) on lines by themselves.\nStrings may be indented and the spaces to the left of the indent will be stripped from\neach line.  All other formatting is preserved.\n\n```gherkin\nScenario: User entering free form text\n  Given the user enters the following text into the web page\n          \"\"\"\n          When the day has a blue sky\n          then I feel much happier\n          \"\"\"\n          ...\n```\n\n### Tables\nSteps may also use the table format to describe data to be passed into the handler.\n\n```gherkin\nScenario: Process a series of trades\n  Given the following trades have been booked during the day\n        | trade id | client | isin        | qty   | consideration |\n        | 1        | CLI1   | UK010910291 | 1000  | GBP1000       |\n        | 2        | CLI2   | US827387238 | 500   | USD2000       |\n        ...\n```\n\nA list of maps representing the table will be passed into the step handler.  In this \ncase the map would be - \n\n````clojure\n    '({\"trade id\" \"1\", \"client\" \"CLI1\", \"isin\" \"UK010910291\", \"qty\" \"1000\", \"consideration\" \"GBP1000\"} \n      {\"trade id\" \"2\", \"client\" \"CLI2\", \"isin\" \"US827387238\", \"qty\" \"500\", \"consideration\" \"USD2000\"})\n````\n\n\n## License\n\nCopyright © Nicholas Riordan.  All rights reserved.\n\nSome small elements of code were taken from clojure.test and modified, and are\nCopyright © Rich Hickey.  All rights reserved.\n\nDistributed under the Eclipse Public License (as per Clojure).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschmorgurken%2Fschmorgurken","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fschmorgurken%2Fschmorgurken","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschmorgurken%2Fschmorgurken/lists"}