{"id":13721256,"url":"https://github.com/trivago/cucable-plugin","last_synced_at":"2025-04-08T04:19:35.919Z","repository":{"id":57729165,"uuid":"93861612","full_name":"trivago/cucable-plugin","owner":"trivago","description":"Maven plugin that simplifies running Cucumber scenarios in parallel.","archived":false,"fork":false,"pushed_at":"2025-03-24T14:35:50.000Z","size":1536,"stargazers_count":115,"open_issues_count":1,"forks_count":42,"subscribers_count":23,"default_branch":"main","last_synced_at":"2025-04-06T22:44:10.497Z","etag":null,"topics":["cucumber-jvm","cucumber-scenarios","gherkin-parser","maven-failsafe","maven-plugin","parallelization","test-automation","test-runner"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trivago.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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}},"created_at":"2017-06-09T13:29:55.000Z","updated_at":"2025-03-24T13:41:18.000Z","dependencies_parsed_at":"2023-12-04T15:24:51.988Z","dependency_job_id":"531185ca-33ce-4966-95cc-8259b54e951a","html_url":"https://github.com/trivago/cucable-plugin","commit_stats":null,"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trivago%2Fcucable-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trivago%2Fcucable-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trivago%2Fcucable-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trivago%2Fcucable-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trivago","download_url":"https://codeload.github.com/trivago/cucable-plugin/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247773734,"owners_count":20993639,"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":["cucumber-jvm","cucumber-scenarios","gherkin-parser","maven-failsafe","maven-plugin","parallelization","test-automation","test-runner"],"created_at":"2024-08-03T01:01:14.630Z","updated_at":"2025-04-08T04:19:35.884Z","avatar_url":"https://github.com/trivago.png","language":"Java","readme":"[![Apache V2 License](http://img.shields.io/badge/license-Apache%20V2-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n[![Maven Central](https://img.shields.io/maven-central/v/com.trivago.rta/cucable-plugin.svg)](https://repo1.maven.org/maven2/com/trivago/rta/cucable-plugin/)\n\n![cucable logo](documentation/img/cucable.png)\n\n_Run Cucumber Scenarios in Parallel with Maven_\n\n![Cucumber compatible](documentation/img/cucumber-compatible-black-64.png)\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [Cucable Maven Plugin](#cucable-maven-plugin)\n  - [Cucable vs Cucumber native parallel runs](#cucable-vs-cucumber-native-parallel-runs)\n  - [JUnit 5](#junit-5)\n  - [Repository Structure](#repository-structure)\n  - [Changelog](#changelog)\n  - [Maven dependency](#maven-dependency)\n- [How it works](#how-it-works)\n  - [Runner template placeholders](#runner-template-placeholders)\n    - [[CUCABLE:RUNNER]](#cucablerunner)\n    - [[CUCABLE:FEATURE]](#cucablefeature)\n    - [Custom template placeholders - [CUCABLE:CUSTOM:xxx]](#custom-template-placeholders---cucablecustomxxx)\n  - [One runner per generated scenario](#one-runner-per-generated-scenario)\n  - [One runner per group of generated scenarios](#one-runner-per-group-of-generated-scenarios)\n  - [No runners](#no-runners)\n- [Typical workflow](#typical-workflow)\n  - [1. Generation of runners and features](#1-generation-of-runners-and-features)\n    - [Parameters](#parameters)\n      - [sourceRunnerTemplateFile](#sourcerunnertemplatefile)\n        - [Using a java file as a runner template](#using-a-java-file-as-a-runner-template)\n        - [Using a text file as a runner template](#using-a-text-file-as-a-runner-template)\n      - [sourceFeatures](#sourcefeatures)\n      - [Combining different feature sources](#combining-different-feature-sources)\n      - [generatedFeatureDirectory](#generatedfeaturedirectory)\n      - [generatedRunnerDirectory](#generatedrunnerdirectory)\n      - [numberOfTestRuns](#numberoftestruns)\n      - [includeScenarioTags](#includescenariotags)\n      - [parallelizationMode](#parallelizationmode)\n      - [logLevel](#loglevel)\n      - [desiredNumberOfRunners](#desirednumberofrunners)\n      - [desiredNumberOfFeaturesPerRunner](#desirednumberoffeaturesperrunner)\n      - [scenarioNames](#scenarionames)\n    - [Generating runners and features inside target directory](#generating-runners-and-features-inside-target-directory)\n    - [Complete Example](#complete-example)\n      - [Source feature file](#source-feature-file)\n      - [Runner template file](#runner-template-file)\n      - [Generated Scenarios](#generated-scenarios)\n      - [Generated runners](#generated-runners)\n  - [2. Running the generated tests with Maven failsafe](#2-running-the-generated-tests-with-maven-failsafe)\n  - [3. Aggregation of a single test report after all test runs](#3-aggregation-of-a-single-test-report-after-all-test-runs)\n- [Example project](#example-project)\n- [Appendix](#appendix)\n  - [Building](#building)\n  - [License](#license)\n  - [Credits](#credits)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n# Cucable Maven Plugin\n\nCucable is a Maven plugin for [Cucumber](https://cucumber.io) scenarios that simplifies fine-grained and efficient\nparallel test runs.\n\nThis plugin does the following:\n\n- Generate single [Cucumber](https://cucumber.io) features containing one single scenario each (scenario outlines are\n  also split up into separate scenarios)\n- Generating [Cucumber](https://cucumber.io) runners\n    - for every generated \"single scenario\" feature file or\n    - for multiple generated \"single scenario\" feature files\n\nThose generated runners and features can then be used\nwith [Maven Failsafe](http://maven.apache.org/surefire/maven-failsafe-plugin/) in order to parallelize test runs.\n\nThis also works for **non-english** feature files!\n\n## Cucable vs Cucumber native parallel runs\n\nCucumber starting with version 5 (using testng or junit 5) can natively run features and scenarios in parallel. Cucable\n__can__ be used but does not __have__ to be.\n\nEven though Cucumber supports basic parallel runs, Cucable has more options that may be beneficial for your use case:\n\n* It supports running single scenarios, complete features or sequences of single scenarios in parallel\n* It supports splitting scenarios and attaching them to a fixed number of runners\n* It supports splitting scenarios and attaching batches of them to a dynamic number of runners\n* You don't need any test framework changes because Cucable runs before the framework invocations\n* You have full control over your runners because of template variables and custom placeholders\n\n## JUnit 5\n\nWhen using the JUnit 5 platform, Cucable can still help parallelize scenarios more fine-grained and with more options\nthan the standard JUnit and Cucumber properties.\n\n## Repository Structure\n\n* [plugin-code](plugin-code) contains the full plugin source code.\n* [example-project](example-project) contains an example Maven project to see the plugin in action.\n\n## Changelog\n\nAll changes are documented in the [full changelog](CHANGELOG.md).\n\n## Maven dependency\n\n```xml\n\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.trivago.rta\u003c/groupId\u003e\n    \u003cartifactId\u003ecucable-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e(check version on top of the page)\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n# How it works\n\n* Cucable will cut up feature file into the smallest possible runnable scenarios\n* Each generated feature file includes a single scenario\n* After this, the runner classes for those generated features are generated based on a provided template file, either\n    * one runner per generated \"single scenario\" feature file or\n    * one runner per group of \"single scenario\" feature files or\n    * no runners at all (not needed if your tests are run as unit tests with JUnit 5 or TestNG)\n\n## Runner template placeholders\n\n__Note:__ If you don't need runner classes to be generated, you can skip this section.\n\n### [CUCABLE:RUNNER]\n\nThe `[CUCABLE:RUNNER]` template placeholder is automatically replaced with the class name of the generated runner class.\n\nIf the generated runner runs only one \"single scenario\" feature, its name will be the same as the generated feature (\ne.g. `Runner_MyFeature_scenario001_run001_IT`).\n\nIn case the runner runs multiple \"single scenario\" features, its name will be auto-generated (e.g.\n`CucableMultiRunner_1da810a2_c4c6_4edb_b078_d81329593950_IT`).\n\n### [CUCABLE:FEATURE]\n\nThe `[CUCABLE:FEATURE]` can be placed in the `feature` option of the `@CucumberOptions` block in your template:\n\n\u003cpre\u003e\n@CucumberOptions(\n  features = {\u003cb\u003e\"target/parallel/features/\u003cb\u003e[CUCABLE:FEATURE]\u003c/b\u003e.feature\"\u003c/b\u003e}\n)\n\u003c/pre\u003e\n\nCucable will automatically detect the string containing the `[CUCABLE:FEATURE]` placeholder and use this to generate one\nline for each feature this runner should trigger.\n\n### Custom template placeholders - [CUCABLE:CUSTOM:xxx]\n\nIn some cases, you may need to set custom values that should be written to your template files.\n\nIn this case, just add a block to your POM file:\n\n```\n\u003ccustomPlaceholders\u003e\n    \u003csomename\u003eAny value\u003c/somename\u003e\n    \u003cfoo\u003ebar\u003c/foo\u003e\n\u003c/customPlaceholders\u003e\n\n```\n\nThese custom placeholders can be used anywhere in your template:\n\n\u003cpre\u003e\nimport cucumber.api.CucumberOptions;\n\n@CucumberOptions(\n        features = {\"target/parallel/features/[CUCABLE:FEATURE].feature\"},\n        plugin = {\"json:target/cucumber-report/\u003cb\u003e[CUCABLE:CUSTOM:foo]\u003c/b\u003e.json\"}\n)\npublic class [CUCABLE:RUNNER] {\n    // \u003cb\u003e[CUCABLE:CUSTOM:somename]\u003c/b\u003e\n}\n\u003c/pre\u003e\n\nIn this case the result would be\n\n\u003cpre\u003e\nimport cucumber.api.CucumberOptions;\n\n@CucumberOptions(\n        features = {\"target/parallel/features/[CUCABLE:FEATURE].feature\"},\n        plugin = {\"json:target/cucumber-report/\u003cb\u003ebar\u003c/b\u003e.json\"}\n)\npublic class [CUCABLE:RUNNER] {\n    // \u003cb\u003eAny value\u003c/b\u003e\n}\n\u003c/pre\u003e\n\n**Note:** The custom placeholder names are case-sensitive!\n\n## One runner per generated scenario\n\nThis is the default mode of Cucable. Having multiple runners that run one \"single scenario\" feature each is best for\nparallelization with [Maven Failsafe](http://maven.apache.org/surefire/maven-failsafe-plugin/).\n\n![Single feature runner generation](documentation/img/cucable_flow_single_runner.png)\n\n## One runner per group of generated scenarios\n\nIf you use the `desiredNumberOfRunners` or `desiredNumberOfFeaturesPerRunner` option, Cucable will automatically switch\nto the multi-feature runner mode.\n\nThis means that it will only generate the specified number of runners (or features per runner) and distribute the\ngenerated features evenly among the runners. This is helpful if a group of scenarios should be executed during each\nforked run of your test framework.\n\n**Note:** If a runner runs only one feature, it automatically has the same name as the feature. Otherwise it will have a\nunique auto-generated name.\n\n![Multi feature runner generation](documentation/img/cucable_flow_multi_runner.png)\n\n## No runners\n\nIf you set `desiredNumberOfRunners` to `0`, this means that Cucable will not generate runner classes at all. In this\ncase, you do not need to set these properties:\n\n* `sourceRunnerTemplateFile` (as you do not need a template file)\n* `generatedRunnerDirectory` (as no runners will be generated)\n\n# Typical workflow\n\n1. Generation of runners and features\n2. Running the generated tests with [Maven Failsafe](http://maven.apache.org/surefire/maven-failsafe-plugin/)\n3. Aggregation of a single test report after all test runs\n\nThe following sections break down the above steps.\n\n## 1. Generation of runners and features\n\n```xml\n\n\u003cplugin\u003e\n    \u003cgroupId\u003ecom.trivago.rta\u003c/groupId\u003e\n    \u003cartifactId\u003ecucable-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e${cucable-plugin.version}\u003c/version\u003e\n    \u003cexecutions\u003e\n        \u003cexecution\u003e\n            \u003cid\u003egenerate-test-resources\u003c/id\u003e\n            \u003cphase\u003egenerate-test-resources\u003c/phase\u003e\n            \u003cgoals\u003e\n                \u003cgoal\u003eparallel\u003c/goal\u003e\n            \u003c/goals\u003e\n        \u003c/execution\u003e\n    \u003c/executions\u003e\n    \u003cconfiguration\u003e\n        \u003c!-- Required properties --\u003e\n        \u003csourceRunnerTemplateFile\u003esrc/test/resources/parallel/cucable.template\u003c/sourceRunnerTemplateFile\u003e\n        \u003csourceFeatures\u003esrc/test/resources/features\u003c/sourceFeatures\u003e\n        \u003cgeneratedFeatureDirectory\u003esrc/test/resources/parallel/features\u003c/generatedFeatureDirectory\u003e\n        \u003cgeneratedRunnerDirectory\u003esrc/test/java/parallel/runners\u003c/generatedRunnerDirectory\u003e\n\n        \u003c!-- Optional properties --\u003e\n        \u003cnumberOfTestRuns\u003e1\u003c/numberOfTestRuns\u003e\n        \u003cincludeScenarioTags\u003e@includeMe and @includeMeAsWell\u003c/includeScenarioTags\u003e\n        \u003clogLevel\u003ecompact\u003c/logLevel\u003e\n\n        \u003cdesiredNumberOfRunners\u003e2\u003c/desiredNumberOfRunners\u003e\n        \u003c!-- or \u003cdesiredNumberOfFeaturesPerRunner\u003e5\u003c/desiredNumberOfRunners\u003e --\u003e\n    \u003c/configuration\u003e\n\u003c/plugin\u003e\n```\n\n### Parameters\n\n#### sourceRunnerTemplateFile\n\n__Note:__ This is only needed, when you want to generate runner classes!\n\nThe specified file will be used to generate runner classes for the generated feature file that can be run\nusing [Maven Failsafe](http://maven.apache.org/surefire/maven-failsafe-plugin/).\n\nThis can be either a text file or a Java class. The difference can be seen below:\n\n##### Using a java file as a runner template\n\nIf you use a java file (e.g. _src/test/java/some/template/CucableJavaTemplate.java_), the **[CUCABLE:FEATURE]**\nplaceholder as well as the **class name** will be substituted for the generated feature file name(s).\nThe **[CUCABLE:RUNNER]** placeholder will be replaced by the runner class name.\n\nAdditionally, the **package declaration** will be stripped.\n\n_Example:_\n\n\u003cpre\u003e\n\u003cb\u003epackage some.template;\u003c/b\u003e\n\nimport cucumber.api.CucumberOptions;\n\n@CucumberOptions(\n        features = {\"target/parallel/features/\u003cb\u003e[CUCABLE:FEATURE]\u003c/b\u003e.feature\"},\n        plugin = {\"json:target/cucumber-report/\u003cb\u003e[CUCABLE:RUNNER]\u003c/b\u003e.json\"}\n)\npublic class CucableJavaTemplate {\n\n}\n\u003c/pre\u003e\n\nwill turn into\n\n\u003cpre\u003e\nimport cucumber.api.CucumberOptions;\n\n@CucumberOptions(\n        features = {\u003cb\u003e\"target/parallel/features/MyFeature_scenario001_run001_IT.feature\"\u003c/b\u003e},\n        plugin = {\"json:target/cucumber-report/\u003cb\u003eMyFeature_scenario001_run001_IT\u003c/b\u003e.json\"}\n)\npublic class \u003cb\u003eMyFeature_scenario001_run001_IT\u003c/b\u003e {\n}\n\n// Generated by Cucable from src/test/java/some/template/CucableJavaTemplate.java\n\u003c/pre\u003e\n\nIn case of a fixed number of runners that contain multiple scenarios (via `desiredNumberOfRunners` property), the runner\nname will be auto-generated:\n\n\u003cpre\u003e\nimport cucumber.api.junit.Cucumber;\nimport cucumber.api.CucumberOptions;\nimport org.junit.runner.RunWith;\n\n@RunWith(Cucumber.class)\n@CucumberOptions(\n    features = {\u003cb\u003e\"target/parallel/features/Bookmarks_scenario001_run001_IT.feature\",\n\"target/parallel/features/Bookmarks_scenario003_run001_IT.feature\"\u003c/b\u003e},\n    plugin = {\n        \"json:target/cucumber-report/\u003cb\u003eCucableMultiRunner_1da810a2_c4c6_4edb_b078_d81329593950_IT\u003c/b\u003e.json\",\n        \"com.trivago.trupi.plugin.TrupiCucumberPlugin\"\n    },\n    glue = {\"com.trivago.trupi.glue\"}\n)\npublic class \u003cb\u003eCucableMultiRunner_1da810a2_c4c6_4edb_b078_d81329593950_IT\u003c/b\u003e {\n}\n\n// Generated by Cucable from src/test/java/some/template/CucableJavaTemplate.java\n\u003c/pre\u003e\n\n##### Using a text file as a runner template\n\nIf you use a text file (e.g. _src/test/resources/cucable.template_), all **[CUCABLE:FEATURE]** placeholder will be\nsubstituted for the generated feature file name(s). The **[CUCABLE:RUNNER]** placeholder will be replaced by the runner\nclass name.\n\n#### sourceFeatures\n\nThis property specifies the location of the features that Cucable should process. It must point to one or more of the\nfollowing:\n\n* the root path of your __existing__ [Cucumber](https://cucumber.io) _.feature_ files, e.g.\n  `src/test/resources/features`\n* the path to a specific __existing__ [Cucumber](https://cucumber.io) _.feature_ file, e.g.\n  `src/test/resources/features/MyFeature.feature`\n* the path to a specific __existing__ [Cucumber](https://cucumber.io) _.feature_ file with optional line numbers of\n  specific scenarios e.g.\n  `src/test/resources/features/MyFeature.feature:12:19`\n* the path to a [Cucumber](https://cucumber.io) text file containing the path to a feature including line number(s) per\n  line (as written by\n  the [Cucumber rerun reporter plugin](https://cucumber.io/docs/cucumber/reporting/?sbsearch=rerun#built-in-reporter-plugins),\n  e.g.\n  ```\n  @src/test/resources/rerun.txt\n  ```\n  __Note:__ The path to a text file has to start with an `@` character!\n\n  The file contents can look like this:\n  ```\n  file:///pathToProject/resources/features/feature1.feature:12\n  file:///pathToProject/resources/features/feature4.feature:6\n  ```\n\n* the root path of your __existing__ [Cucumber](https://cucumber.io) text files (also starting with an `@`), e.g.\n  ```\n  @src/test/resources\n  ```\n\n#### Combining different feature sources\n\nStarting from Cucumber 1.10.0, you can use any combination of sources by separating them with commas, e.g.\n\n```xml\n\n\u003csourceFeatures\u003esrc/test/resources/features, @src/test/rerun.txt\u003c/sourceFeatures\u003e\n```\n\nThis example would use all `.feature` files in `src/test/resources/features` __plus__ all features that are defined in\n`src/test/rerun.txt`!\n\n__Note:__ You need to be careful when selecting multiple sources as the same feature could be generated multiple times\nif it appears in more than one source.\n\n#### generatedFeatureDirectory\n\nThe path where the __generated__ [Cucumber](https://cucumber.io) .feature files should be located (e.g.\n_src/test/resources/parallel_).\n\nAdditionally, a file called `generated-features.properties` will be generated there that shows all generated features\nalong with their reference to the respective source feature.\n\n**Note:** This directory should be located under a valid resource folder to be included as a test source by Maven.\nIf you want to use a directory inside Maven's target\nfolder, [check this example](#generating-runners-and-features-inside-target-directory).\n\n**Caution:** This directory will be wiped prior to the feature file generation!\n\n#### generatedRunnerDirectory\n\n__Note:__ This is only needed, when you want to generate runner classes!\n\nThe path where the __generated__ runner classes should be located (e.g. _src/test/java/parallel/runners_).\n\n**Note:** This directory should be located under a valid source folder to be included as a test source by Maven.\nIf you want to use a directory inside Maven's target\nfolder, [check this example](#generating-runners-and-features-inside-target-directory).\n\n**Caution:** This directory will be wiped prior to the runner file generation!\n\n#### numberOfTestRuns\n\nOptional number of test runs. This can be used if specific scenarios should be run multiple times.\nIf this option is not set, its default value is __1__.\n\nFor each test run, the whole set of features and runners is generated like this:\n\n- MyFeature_scenario001_run001_IT.feature\n- MyFeature_scenario001_run002_IT.feature\n- MyFeature_scenario001_run003_IT.feature\n- etc.\n\n**Note:** Characters other than letters from A to Z, numbers and underscores will be stripped out of the feature file\nname.\n\n#### includeScenarioTags\n\n`includeScenarioTags` can be used to provide\na [Cucumber tag expression](https://docs.cucumber.io/cucumber/api/#tag-expressions) in order to specify which tags\nshould be included or excluded from scenario generation:\n\n__Example:__ include scenarios that are tagged with _@scenario1_:\n\n```xml\n\n\u003cincludeScenarioTags\u003e@scenario1\u003c/includeScenarioTags\u003e\n```\n\n__Example:__ include scenarios that are tagged with _@scenario1_ __or__ _@scenario2_:\n\n```xml\n\n\u003cincludeScenarioTags\u003e@scenario1 or @scenario2\u003c/includeScenarioTags\u003e\n```\n\n__Example:__ include scenarios that are tagged with _@scenario1_ __and__ _@scenario2_:\n\n```xml\n\n\u003cincludeScenarioTags\u003e@scenario1 and @scenario2\u003c/includeScenarioTags\u003e\n```\n\n__Example:__ include scenarios that are __not__ tagged with _@scenario1_:\n\n```xml\n\n\u003cincludeScenarioTags\u003enot @scenario1\u003c/includeScenarioTags\u003e\n```\n\n__Example:__ include scenarios that are __not__ tagged with _@scenario1_ but tagged with _scenario2_ __or__ _scenario3_:\n\n```xml\n\n\u003cincludeScenarioTags\u003enot @scenario1 and (@scenario2 or scenario3)\u003c/includeScenarioTags\u003e\n```\n\n#### parallelizationMode\n\nBy default, Cucable uses the `parallelizationMode = scenarios` meaning that feature files are split into individual\nscenarios that each have a dedicated runner.\n\nSometimes it may be desirable, to parallelize complete features. When setting the `parallelizationMode = features`, only\ncomplete features containing all of their source scenarios are generated so __each runner runs a complete feature__.\n\n```xml\n\n\u003cparallelizationMode\u003efeatures\u003c/parallelizationMode\u003e\n```\n\n__Note:__ For this mode to work, `\u003csourceFeatures\u003e` must specify a directory. Also, `includeScenarioTags` cannot be\nused.\n\n#### logLevel\n\nBy default, Cucable logs all information including\n\n* its own name and version\n* all passed property values\n* a list of processed feature paths\n\nThis can be configured by passing the `logLevel` property:\n\n```\n\u003clogLevel\u003edefault|compact|minimal|off\u003c/logLevel\u003e\n```\n\n* _default_ will log all the mentioned information\n* _compact_ will only log the plugin name, version, properties and one line of summary\n* _minimal_ will only log a summary line\n* _off_ will prevent any logging\n\n#### desiredNumberOfRunners\n\nIf you set this options, all generated features will be distributed to a fixed set of runner classes. This means that\none runner can potentially run multiple features in sequence.\n\nIf this option is not set, its default value is `-1` which basically means \"Generate a dedicated runner for every\ngenerated feature\".\n\n__Note:__ This cannot be used together with `desiredNumberOfFeaturesPerRunner`!\n\n#### desiredNumberOfFeaturesPerRunner\n\nIf you set this option, all generated features will be distributed to a dynamic set of runner classes so that every\nrunner contains a fixed number of generated features. This means that one runner can potentially run multiple features\nin sequence.\n\nIf this option is not set, its default value is `0` which basically means \"Generate a dedicated runner for every\ngenerated feature\".\n\n__Note:__ This cannot be used together with `desiredNumberOfRunners`!\n\n#### scenarioNames\n\nA comma separated list of strings matching a scenario name, either completely or partially. Please see `--name` in\nCucumber command-line options (`java cucumber.api.cli.Main --help` or `mvn test -Dcucumber.options=\"--help`). If you set\nthis option, only scenarios matching the specified names will be loaded into the generated runners. The number of runner\nfiles will default to the number of scenario names and each runner file will contain the scenarios matching 1 name.\nPlease note that this will override `desiredNumberOfRunners`.\nFor example, if the following scenario names are specified:\n\n```xml\n\n\u003cscenarioNames\u003e\n    name1,\n    name2\n\u003c/scenarioNames\u003e\n```\n\n2 runner files will be generated. The first file will contain all the scenarios matching `name1` and the second file\nwill contain all the scenarios matching `name2`.\n\n__Note:__ This *cannot* be used together with `desiredNumberOfFeaturesPerRunner` or `parallelizationMode = features`!\n\n### Generating runners and features inside target directory\n\nIt may be desirable for you to generate the Cucable features and runners in Maven's `target` directory.\nThe advantage of this is that this directory is wiped by the `mvn clean` command and older generated files do not reside\nin your `src` directory.\n\nIn order to achieve this, you can specify subdirectories under target (`${project.build.directory}`) for Cucable, e.g.\n`${project.build.directory}/parallel/runners` and `${project.build.directory}/parallel/features`\n\nAfter this step, use the *build-helper-maven-plugin* in your POM file in order to consider the generated runner classes\ntest sources:\n\n```xml\n\n\u003cplugins\u003e\n    \u003cplugin\u003e\n        \u003cgroupId\u003ecom.trivago.rta\u003c/groupId\u003e\n        \u003cartifactId\u003ecucable-plugin\u003c/artifactId\u003e\n        \u003cversion\u003e${cucable.plugin.version}\u003c/version\u003e\n        \u003cexecutions\u003e\n            \u003cexecution\u003e\n                \u003cid\u003egenerate-test-resources\u003c/id\u003e\n                \u003cphase\u003egenerate-test-resources\u003c/phase\u003e\n                \u003cgoals\u003e\n                    \u003cgoal\u003eparallel\u003c/goal\u003e\n                \u003c/goals\u003e\n            \u003c/execution\u003e\n        \u003c/executions\u003e\n        \u003cconfiguration\u003e\n            \u003csourceRunnerTemplateFile\u003epath_to_template_file\u003c/sourceRunnerTemplateFile\u003e\n            \u003csourceFeatures\u003epath_to_features\u003c/sourceFeatures\u003e\n            \u003cgeneratedFeatureDirectory\u003e${project.build.directory}/parallel/features\u003c/generatedFeatureDirectory\u003e\n            \u003cgeneratedRunnerDirectory\u003e${project.build.directory}/parallel/runners\u003c/generatedRunnerDirectory\u003e\n        \u003c/configuration\u003e\n    \u003c/plugin\u003e\n    \u003cplugin\u003e\n        \u003cgroupId\u003eorg.codehaus.mojo\u003c/groupId\u003e\n        \u003cartifactId\u003ebuild-helper-maven-plugin\u003c/artifactId\u003e\n        \u003cversion\u003e${build.helper.plugin.version}\u003c/version\u003e\n        \u003cexecutions\u003e\n            \u003cexecution\u003e\n                \u003cid\u003eadd-test-source\u003c/id\u003e\n                \u003cphase\u003egenerate-test-sources\u003c/phase\u003e\n                \u003cgoals\u003e\n                    \u003cgoal\u003eadd-test-source\u003c/goal\u003e\n                \u003c/goals\u003e\n                \u003cconfiguration\u003e\n                    \u003csources\u003e\n                        \u003csource\u003e${project.build.directory}/parallel/runners\u003c/source\u003e\n                    \u003c/sources\u003e\n                \u003c/configuration\u003e\n            \u003c/execution\u003e\n        \u003c/executions\u003e\n    \u003c/plugin\u003e\n\u003c/plugins\u003e\n\n```\n\n### Complete Example\n\nBelow, you can see a full example of what Cucable does.\n\n#### Source feature file\n\nThis is our source feature file. It contains a scenario and a scenario outline with two examples.\n\n*MyFeature.feature*\n\n```\nFeature: This is the feature name\n\n    Scenario: First scenario\n        Given I am on the start page\n        And I click the login button\n        Then I see an error message\n\n    Scenario Outline: Second scenario with an amount of \u003camount\u003e\n        Given I am on the start page\n        And I add \u003camount\u003e items\n        And I navigate to the shopping basket\n        Then I see \u003camount\u003e items\n        Examples:\n            | amount |\n            | 12     |\n            | 85     |\n```\n\n#### Runner template file\n\nThis is the runner template file (in this example we use a text file) that is used to generate single scenario runners.\n\n* The placeholder **[CUCABLE:FEATURE]** and its enclosing string will be replaced with the generated feature names by\n  Cucable.\n* The placeholder **[CUCABLE:RUNNER]** will be replaced with the generated runner class name by Cucable.\n\n\u003cpre\u003e\nimport cucumber.api.CucumberOptions;\n\n@CucumberOptions(\n        features = {\"target/parallel/features/\u003cb\u003e[CUCABLE:FEATURE]\u003c/b\u003e.feature\"},\n        plugin = {\"json:target/cucumber-report/\u003cb\u003e[CUCABLE:RUNNER]\u003c/b\u003e.json\"}\n)\npublic class \u003cb\u003e[CUCABLE:RUNNER]\u003c/b\u003e {\n}\n\u003c/pre\u003e\n\n**Note:** The specified _plugin_ generates Cucumber JSON files which are needed for custom aggregated test reports.\n\n#### Generated Scenarios\n\nFor each scenario, a single feature file is created:\n\n*MyFeature_scenario001_run001_IT.feature*\n\n```\nFeature: This is the feature name\n\nScenario: First scenario\nGiven I am on the start page\nAnd I click the login button\nThen I see an error message\n```\n\nNote that for the scenario outlines, each example is converted _to its own scenario and feature file_:\n\n*MyFeature_scenario002_run001_IT.feature*\n\n\u003cpre\u003e\nFeature: This is the feature name\n\nScenario: Second scenario with an amount of \u003cb\u003e12\u003c/b\u003e\nGiven I am on the start page\nAnd I add \u003cb\u003e12\u003c/b\u003e items\nAnd I navigate to the shopping basket\nThen I see \u003cb\u003e12\u003c/b\u003e items\n\u003c/pre\u003e\n\n*MyFeature_scenario003_run001_IT.feature*\n\n\u003cpre\u003e\nFeature: This is the feature name\n\nScenario: Second scenario with an amount of \u003cb\u003e85\u003c/b\u003e\nGiven I am on the start page\nAnd I add \u003cb\u003e85\u003c/b\u003e items\nAnd I navigate to the shopping basket\nThen I see \u003cb\u003e85\u003c/b\u003e items\n\u003c/pre\u003e\n\n#### Generated runners\n\nThe generated runners point to each one of the generated feature files (unless you use the `desiredNumberOfRunners` or\n`desiredNumberOfFeaturesPerRunner` option).\n\nThis is an example for one of the generated runners - note how the placeholders are now replaced with the name of the\nfeature to run:\n\n*Runner_MyFeature_scenario001_run001_IT.java*\n\n\u003cpre\u003e\nimport cucumber.api.CucumberOptions;\n\n@CucumberOptions(\n        features = {\"target/parallel/features/\u003cb\u003eMyFeature_scenario001_run001_IT\u003c/b\u003e.feature\"},\n        plugin = {\"json:target/cucumber-report/\u003cb\u003eMyFeature_scenario001_run001_IT\u003c/b\u003e.json\"}\n)\npublic class \u003cb\u003eMyFeature_scenario001_run001_IT\u003c/b\u003e {\n}\n\u003c/pre\u003e\n\n## 2. Running the generated tests with Maven failsafe\n\nThis will skip the unit tests (if any) and run the generated runner classes\nwith [Maven Failsafe](http://maven.apache.org/surefire/maven-failsafe-plugin/).\nSince all generated runner classes from the step before end with ___IT__, they are automatically considered integration\ntests and run with [Maven Failsafe](http://maven.apache.org/surefire/maven-failsafe-plugin/).\n\n**Note:** If all tests should be run regardless of their result, it is important to set\n```\u003ctestFailureIgnore\u003etrue\u003c/testFailureIgnore\u003e```\nfor [Maven Failsafe](http://maven.apache.org/surefire/maven-failsafe-plugin/) - otherwise the plugin execution will stop\non failing tests.\nHowever, if this is specified, the build will not fail in case of failing tests!\n\nTo circumvent that, it is possible to specify a\ncustom [rule](https://maven.apache.org/enforcer/enforcer-api/writing-a-custom-rule.html)\nfor [Maven enforcer](https://maven.apache.org/enforcer/maven-enforcer-plugin/) that passes or fails the build depending\non custom conditions.\n\n```xml\n\n\u003cplugins\u003e\n    \u003cplugin\u003e\n        \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n        \u003cartifactId\u003emaven-surefire-plugin\u003c/artifactId\u003e\n        \u003cconfiguration\u003e\n            \u003cskipTests\u003etrue\u003c/skipTests\u003e\n        \u003c/configuration\u003e\n    \u003c/plugin\u003e\n    \u003cplugin\u003e\n        \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n        \u003cartifactId\u003emaven-failsafe-plugin\u003c/artifactId\u003e\n        \u003cexecutions\u003e\n            \u003cexecution\u003e\n                \u003cid\u003eRun parallel tests\u003c/id\u003e\n                \u003cphase\u003eintegration-test\u003c/phase\u003e\n                \u003cgoals\u003e\n                    \u003cgoal\u003eintegration-test\u003c/goal\u003e\n                \u003c/goals\u003e\n            \u003c/execution\u003e\n        \u003c/executions\u003e\n        \u003cconfiguration\u003e\n            \u003ctestFailureIgnore\u003etrue\u003c/testFailureIgnore\u003e\n            \u003cforkCount\u003e${maven.fork.count}\u003c/forkCount\u003e\n            \u003creuseForks\u003efalse\u003c/reuseForks\u003e\n            \u003cargLine\u003e-Dfile.encoding=UTF-8\u003c/argLine\u003e\n            \u003cdisableXmlReport\u003etrue\u003c/disableXmlReport\u003e\n        \u003c/configuration\u003e\n    \u003c/plugin\u003e\n\u003c/plugins\u003e\n```\n\n## 3. Aggregation of a single test report after all test runs\n\nWe use the [Cluecumber](https://github.com/trivago/cluecumber-report-plugin) plugin to aggregate all generated __.json__\nreport files into one overall test report.\n\n```xml\n\n\u003cplugins\u003e\n    \u003cplugin\u003e\n        \u003cgroupId\u003ecom.trivago.rta\u003c/groupId\u003e\n        \u003cartifactId\u003ecluecumber-report-plugin\u003c/artifactId\u003e\n        \u003cversion\u003e${cluecumber.report.version}\u003c/version\u003e\n        \u003cexecutions\u003e\n            \u003cexecution\u003e\n                \u003cid\u003ereport\u003c/id\u003e\n                \u003cphase\u003epost-integration-test\u003c/phase\u003e\n                \u003cgoals\u003e\n                    \u003cgoal\u003ereporting\u003c/goal\u003e\n                \u003c/goals\u003e\n            \u003c/execution\u003e\n        \u003c/executions\u003e\n        \u003cconfiguration\u003e\n            \u003csourceJsonReportDirectory\u003e${project.build.directory}/cucumber-report\u003c/sourceJsonReportDirectory\u003e\n            \u003cgeneratedHtmlReportDirectory\u003e${project.build.directory}/test-report\u003c/generatedHtmlReportDirectory\u003e\n        \u003c/configuration\u003e\n    \u003c/plugin\u003e\n\u003c/plugins\u003e\n```\n\n# Example project\n\nYou can test the complete flow and POM configuration by checking out the [Cucable example project](example-project).\n\n# Appendix\n\n## Building\n\nCucable requires Java \u003e= 8 and Maven \u003e= 3.3.9.\nIt is available\nin [Maven central](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.trivago.rta%22%20AND%20a%3A%22cucable-plugin%22).\n\n## License\n\nCopyright 2017 [trivago N.V.](https://www.trivago.de/impressum)\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the\nLicense. You may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"\nAS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific\nlanguage governing permissions and limitations under the License.\n\n## Credits\n\nThis plugin was inspired by\nthe [Cucumber Slices Maven Plugin](https://github.com/DisneyStudios/cucumber-slices-maven-plugin).\n","funding_links":[],"categories":["Tools, Libraries \u0026 Frameworks","Tools"],"sub_categories":["Java"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrivago%2Fcucable-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrivago%2Fcucable-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrivago%2Fcucable-plugin/lists"}