{"id":20716301,"url":"https://github.com/fslev/cucumber-jutils","last_synced_at":"2025-07-17T08:38:08.142Z","repository":{"id":48971249,"uuid":"517063428","full_name":"fslev/cucumber-jutils","owner":"fslev","description":"An extension for Cucumber for Java with scenario variables and assertion support","archived":false,"fork":false,"pushed_at":"2025-04-02T19:30:48.000Z","size":1564,"stargazers_count":6,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-23T13:23:36.458Z","etag":null,"topics":["assertion","cucumber","diff","java","match","scenario","spel","variables"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fslev.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-07-23T13:20:06.000Z","updated_at":"2025-03-31T14:10:05.000Z","dependencies_parsed_at":"2023-12-23T15:42:55.834Z","dependency_job_id":"f0536100-c109-4dff-9cc7-6405788ea980","html_url":"https://github.com/fslev/cucumber-jutils","commit_stats":null,"previous_names":[],"tags_count":230,"template":false,"template_full_name":null,"purl":"pkg:github/fslev/cucumber-jutils","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fslev%2Fcucumber-jutils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fslev%2Fcucumber-jutils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fslev%2Fcucumber-jutils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fslev%2Fcucumber-jutils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fslev","download_url":"https://codeload.github.com/fslev/cucumber-jutils/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fslev%2Fcucumber-jutils/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259578202,"owners_count":22879213,"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":["assertion","cucumber","diff","java","match","scenario","spel","variables"],"created_at":"2024-11-17T03:05:25.193Z","updated_at":"2025-06-13T04:06:14.684Z","avatar_url":"https://github.com/fslev.png","language":"Java","readme":"# Cucumber JUtils \u003csup\u003e[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://vshymanskyy.github.io/StandWithUkraine)\u003c/sup\u003e\n\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.fslev/cucumber-jutils.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22io.github.fslev%22%20AND%20a:%22cucumber-jutils%22)\n![Java CI with Maven](https://github.com/fslev/cucumber-jutils/actions/workflows/maven.yml/badge.svg?branch=main)\n[![Coverage Status](https://coveralls.io/repos/github/fslev/cucumber-jutils/badge.svg?branch=main)](https://coveralls.io/github/fslev/cucumber-jutils?branch=main)\n\n\n# Summary\nAn extension to [Cucumber for Java](https://github.com/cucumber/cucumber-jvm) based on [Cucumber Guice](https://github.com/cucumber/cucumber-jvm/tree/main/cucumber-guice), with scenario variables support, assertion support and some pre-defined utility steps.  \n\n\nIt augments your Cucumber based test framework with some powerful features, such as:\n* [Scenario scoped variables](#scenario-vars)\n* [Assertion support](#assertion-support)  \n* [SpEL support](#spel-support)\n* [Predefined common steps](#predefined-steps)   \n* [Utility classes](#utility-classes)           \n\n#### Maven Central\n```\n\u003cdependency\u003e\n  \u003cgroupId\u003eio.github.fslev\u003c/groupId\u003e\n  \u003cartifactId\u003ecucumber-jutils\u003c/artifactId\u003e\n  \u003cversion\u003e${latest.version}\u003c/version\u003e\n\u003c/dependency\u003e\n\nGradle: compile(\"io.github.fslev:cucumber-jutils:${latest.version}\")\n```  \n\n### Required dependencies\n[Cucumber-JUtils](https://github.com/fslev/cucumber-jutils) requires the following dependencies inside your project:  \n```\n\u003cdependency\u003e\n   \u003cgroupId\u003eio.cucumber\u003c/groupId\u003e\n   \u003cartifactId\u003ecucumber-java\u003c/artifactId\u003e\n   \u003cversion\u003e${cucumber.version}\u003c/version\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n   \u003cgroupId\u003eio.cucumber\u003c/groupId\u003e\n   \u003cartifactId\u003ecucumber-guice\u003c/artifactId\u003e\n   \u003cversion\u003e${cucumber.version}\u003c/version\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n   \u003cgroupId\u003ecom.google.inject\u003c/groupId\u003e\n   \u003cartifactId\u003eguice\u003c/artifactId\u003e\n   \u003cversion\u003e${guice.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n# Configuration\nIn order to integrate **cucumber-jutils** within your test project you must configure the following **glue** package inside your IDE Cucumber plugin or / and inside the code:\n```\ncom.cucumber.utils\n```  \n# Tutorial\nFollow the [Cucumber JUtils Tutorial](https://github.com/fslev/cucumber-jutils-tutorial) for a better picture on how this library should be used.\n\n# \u003ca name=\"scenario-vars\"\u003e\u003c/a\u003e 1. Scenario scoped variables\nScenario variables can be set and read inside __Gherkin__ syntax, __Java__ code and __resource__ files.  \nThese variables are scenario scoped. Meaning, they live as long as the scenario is running and they cannot be accessed from another scenario.  \n\n\n## 1.1 Gherkin\nScenario variables are read using `#[` and `]` delimiters.  \n__Important note:__ If you want to use scenario variables inside your step arguments, your step definition has to use [anonymous parameter types](https://github.com/cucumber/cucumber-expressions#readme).  \n\nVariables can be set using different pre-defined steps:  \n\n#### `* var \u003cname\u003e=\"\u003cvalue\u003e\"`\nExample:\n```Gherkin\nScenario: Test scenario variables\n  * var animal=\"rabbit\"\n  * var location=\"forest\"\n  * [util] Match some rabbit with some #[animal]\n  * [util] Match forest with #[location]\n```\nAs you can see bellow, the matching step is defined with anonymous parameter types:  \n```javascript\n@Then(\"[util] Match {} with {}\")\npublic void match(Object expected, Object actual) {\n```\n\n#### `* var \u003cvarName\u003e=\u003cdocString\u003e`\nDefines a variable with value from [doc string](https://cucumber.io/docs/gherkin/reference/):  \n```gherkin\nScenario: Test scenario variable set from doc string\n  * var animal=\n    \"\"\"\n    rabbit\n    \"\"\"\n  * [util] Match some rabbit with some #[animal]\n```\n\n#### `* var \u003cvarName\u003e from file \"\u003cpath/to/file\u003e\"`\nDefines a variable with value from file content:    \n\u003e File: features/readme/vars/madagascar.crt\n\u003e \u003e macac\n\n```gherkin\nScenario: Test scenario variable set from file\n  * var animal from file \"features/readme/vars/madagascar.crt\"\n  * [util] Match macac with #[animal]\n```\n\n#### `* load vars from file \"path/to/file\"`\nLoads the properties from a file, as scenario variables: `.properties`, `.yaml`, `.yml`.  \nExample:\n\u003e File: features/readme/vars/config.properties\n\u003e \u003e animal = lioness  \n\u003e \u003e location = Africa\n\n```gherkin\nScenario: Test scenario variables set from properties file\n  * load vars from file \"features/readme/vars/config.properties\"\n  * [util] Match lioness with #[animal]\n  * [util] Match Africa with #[location]\n```\n\n#### `* load vars from dir \"\u003cpath/to/directory\u003e\"`\nIt reads recursively the entire directory tree structure and each file becomes a scenario variable:  \n_file name, without extension -\u003e `variable name`_  \n_file content -\u003e `variable value`_  \n\nSupported file types: `.txt`, `.text`, `.json`, `.xml`, `.html`, `.csv`  \nProperties inside files: `.properties`, `.yaml`, `.yml` are also parsed as scenario variables.  \n\nExample:  \n\u003eDirectory: placeholders/properties/drinks\n\u003e\u003eFile: whisky.txt\n\u003e\u003e\u003eJohnny Walker\n\n\u003e\u003eFile: drink.yaml\n\u003e\u003e\u003e beer: Bergenbier  \n\u003e\u003e\u003e beers:  \n\u003e\u003e\u003e ``-`` Ursus  \n\u003e\u003e\u003e ``-`` Heineken   \n\n```gherkin\nScenario: Test scenario variables set from directory\n  * load vars from dir \"placeholders/properties/drinks\"\n  * [util] Match Johnny Walker with #[whisky]\n  * [util] Match Bergenbier with #[beer]\n  * [util] Match [\"Ursus\", \"Heineken\"] with #[beers]\n```\n\n\n#### `* var \u003cvarName\u003e from table`\nDefines a variable with value from [data table](https://github.com/cucumber/cucumber-jvm/tree/main/datatable):\n```gherkin\nScenario: Test scenario variable set from table\n  * var animals from table\n    | feline  | marsupial       |\n    | lioness | kangaroo        |\n    | cougar  | tasmanian devil |\n  * [util] Match [{\"feline\":\"lioness\", \"marsupial\":\"kangaroo\"}, {\"feline\":\"cougar\", \"marsupial\":\"tasmanian devil\"}] with #[animals]\n```\n\n## 1.2 Java\nScenario variables can also be set and used directly inside Java code, by injecting the `ScenarioVars.class`.  \nVariables defined inside Gherkin files can be used from Java code and vice versa.  \n\n#### 1.2.1 ScenarioVars `.put()`, `.putAll()`, `.get()` and `.getAsString()`\n__Set variables inside a step and use them from another step__\n```javascript\npublic class ScenarioVarsReadmeSteps {\n\n    @Inject\n    private ScenarioVars scenarioVars;\n\n    @Given(\"Some random step which sets some variables\")\n    public void setVariables() {\n        scenarioVars.put(\"animal\", \"Cheetah\");\n        Map\u003cString, Object\u003e vars = new HashMap\u003c\u003e();\n        vars.put(\"figure\", \"triangle\");\n        vars.put(\"number\", 10);\n        scenarioVars.putAll(vars);\n    }\n}\n```\n```javascript\npublic class ScenarioVarsAnotherReadmeSteps {\n\n    @Inject\n    private ScenarioVars scenarioVars;\n\n    @Given(\"Some random step which reads the variables\")\n    public void readVariables() {\n        assertEquals(\"Cheetah\", scenarioVars.getAsString(\"animal\"));\n        assertEquals(\"triangle\", scenarioVars.getAsString(\"figure\"));\n        assertEquals(10, scenarioVars.get(\"number\"));\n    }\n}\n```\n__Set and use variables from both Gherkin and Java:__\n```Gherkin\nScenario: Use scenario variables from Java and Gherkin\n  * Some random step which sets some variables\n  * [util] Match Cheetah with #[animal]\n  * var planet=\"Mars\"\n  * Some random step which reads variables set inside Gherkin\n```\n```javascript\n@Inject\nprivate ScenarioVars scenarioVars;\n\n@Given(\"Some random step which reads variables set inside Gherkin\")\npublic void readVariablesSetViaGherkin() {\n    assertEquals(\"Mars\", scenarioVars.getAsString(\"planet\"));\n}\n```\n\n#### 1.2.2 ScenarioVarsUtils `.loadScenarioVarsFromFile()` and `.loadScenarioVarsFromDir()`\nSimilar to the Gherkin steps, scenario variables can also be set from files:  \n\n```javascript\n@Inject\nprivate ScenarioVars scenarioVars;\n\n@Given(\"Read scenario variables from file\")\npublic void setVariablesFromFile() {\n    ScenarioVarsUtils.loadScenarioVarsFromFile(\"features/readme/vars/config.properties\", scenarioVars);\n    ScenarioVarsUtils.loadScenarioVarsFromDir(\"placeholders/properties/drinks\", scenarioVars);\n    assertEquals(\"Africa\", scenarioVars.get(\"location\"));\n    assertEquals(\"Johnny Walker\", scenarioVars.get(\"whisky\"));\n}\n```\n\n## 1.3 Resources \nYou may parse resource files for scenario variables, delimited by `#[` and `]`.\n### `ScenarioVarsUtils.parse()`\n\u003e File path: features/readme/scene/some_text.txt\n\u003e\u003e The #[animal] lives in #[location]\n```gherkin\nScenario: Parse files for scenario variables\n  * var animal=\"wolf\"\n  * var location=\"forest\"\n  * Parse file for scenario variables\n```\n```javascript\n@Inject\nprivate ScenarioVars scenarioVars;\n    \n@Given(\"Parse file for scenario variables\")\npublic void parseFileForScenarioVars() {\n    assertEquals(\"The wolf lives in forest\", ScenarioVarsUtils.parse(\"features/readme/scene/some_text.txt\", scenarioVars));\n}\n```\n\n## 1.4 Path variables\nFor JSON type variables you may access certain values by using Jackson paths `/`:\n```gherkin\n* var x=\n  \"\"\"json\n    {\"book\":{\n        \"details\":{\"title\":\"Moby Dick\"}\n      }\n    }\n  \"\"\"\n* [util] Match #[x/book/details/title] with Moby Dick\n```\n\nPlay with the [Readme examples](https://github.com/fslev/cucumber-jutils/tree/main/src/test/resources/features/readme) for getting a better insight on how scenario variables work.  \n\n# \u003ca name=\"assertion-support\"\u003e\u003c/a\u003e 2. Assertion support\n[Cucumber-JUtils](https://github.com/fslev/cucumber-jutils) already ships with [**JTest-Utils**](https://github.com/fslev/jtest-utils) that has some powerful assertions in terms of Objects matching.   \n\n\n# \u003ca name=\"spel-support\"\u003e\u003c/a\u003e 3. SpEL support\nYou may use [SpEL](https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/core.html#expressions) expressions inside Gherkin or resource files, delimited by `#{` and `}`:\n### 3.1 Gherkin\n```Gherkin\nFeature: SpEL\n\n  Scenario: Use SpEL inside Gherkin\n    * var number=\"5\"\n    * var isOddNumber=\"#{ #[number] % 2 != 0 }\"\n    * [util] Match true with #[isOddNumber]\n```\n\n### 3.2 Resource\n[SpEL](https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/core.html#expressions) expressions used inside files:  \n\u003e File path: features/readme/scene/some_text_with_spel.txt\n\u003e\u003e \"Is #[number] odd: #{ #[number] % 2 !=0 }\" \n\n\n```gherkin\nScenario: Use SpEL inside files\n  * var content from file \"features/readme/scene/some_text_with_spel.txt\"\n  * var number=\"5\"\n  * [util] Match \"Is 5 odd: true\" with #[content]\n```\n\n__Note:__ `ScenarioVarsUtils.parse()` not only parses for scenario variables, but also for SpEL expressions:  \n```javascript\n@Inject\nprivate ScenarioVars scenarioVars;\n    \n@Given(\"Parse file for SpEL\")\npublic void parseFileForSpEL() {\n    assertEquals(\"\\\"Is 5 odd: true\\\"\", ScenarioVarsUtils.parse(\"features/readme/scene/some_text_with_spel.txt\", scenarioVars));\n}\n```\n```gherkin\nScenario: Parse files for SpEL\n  * var number=\"5\"\n  * Parse file for SpEL\n```\nPlay with the [Readme examples](https://github.com/fslev/cucumber-jutils/tree/main/src/test/resources/features/readme) for getting a better insight on how SpEL expressions are used.  \n\n\n# \u003ca name=\"predefined-steps\"\u003e\u003c/a\u003e 4. Predefined common steps\n\n### 4.1 Matching\n```Gherkin\n  # throws and AssertionError \n  * [util] Match true with false\n```\n### 4.2 Date time\n```Gherkin\n  * [time-util] Check period from 2019-02-03 23:58:12+0200 to 2019-02-04 01:59:10+0300 is 1 HOURS using date time pattern yyyy-MM-dd HH:mm:ssZ\n\n  * var currentMillis=\"#[now]\"\n  * [time-util] date var currentDate=from millis #[currentMillis] PLUS 0 YEARS with format pattern=yyyy-MM-dd\n  * [time-util] date var futureDateYears=from millis #[currentMillis] PLUS 15 YEARS with format pattern=yyyy-MM-dd\n  * [time-util] Check period from #[currentDate] to #[futureDateYears] is 15 YEARS using date pattern yyyy-MM-dd\n```\n\n### 4.3 Sleep\n```gherkin\n  * [util] Wait 10.471s\n  * [util] Wait 2.5m\n```\n\n# \u003ca name=\"utility-classes\"\u003e\u003c/a\u003e 5. Utility classes\n- `ScenarioVars` - it stores all scenario variables. Access it via injection: `com.google.inject.Inject`\n- `ScenarioVarsUtils` - it sets scenario variables and parses files for both scenario variables and SpEL expressions\n- `ScenarioVarsParser` - it parses a String for scenario variables and SpEL expressions\n- `ScenarioUtils` - fast access to the underlying Cucumber `Scenario.class` and used for writing:\n```javascript\n@Inject\nprivate ScenarioUtils scenarioUtils;\n\n@Given(\"write {}=\\\"{}\\\"\")\npublic void writeSomething(String name, Object value) {\n    scenarioUtils.log(\"var {} = {}\", name, value);\n    scenarioUtils.log(\"Scenario: {}\", scenarioUtils.getScenario().getName());\n}\n```\n\n# Tutorial\nFollow the [Cucumber JUtils Tutorial](https://github.com/fslev/cucumber-jutils-tutorial) for a better picture on how this library should be used.\n\n# Website\nhttps://fslev.github.io/cucumber-jutils/\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffslev%2Fcucumber-jutils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffslev%2Fcucumber-jutils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffslev%2Fcucumber-jutils/lists"}