├── .clang-format ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── format.yml │ ├── linux-build.yml │ ├── qt5.yml │ ├── run-all.yml │ └── windows-build.yml ├── .gitignore ├── CHANGELOG.md ├── CMakeLists.txt ├── CONTRIBUTING.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── cmake └── modules │ ├── FindAsio.cmake │ ├── FindTCLAP.cmake │ ├── FindValgrind.cmake │ └── GitVersion.cmake ├── examples ├── CMakeLists.txt ├── Calc │ ├── CMakeLists.txt │ ├── README.txt │ ├── features │ │ ├── addition.feature │ │ ├── division.feature │ │ └── step_definitions │ │ │ ├── BoostCalculatorSteps.cpp │ │ │ ├── CalculatorSteps.cpp │ │ │ ├── FuncArgsCalculatorSteps.cpp │ │ │ ├── GTestCalculatorSteps.cpp │ │ │ ├── QtTestCalculatorSteps.cpp │ │ │ └── cucumber.wire │ └── src │ │ ├── Calculator.cpp │ │ └── Calculator.hpp ├── CalcQt │ ├── CMakeLists.txt │ ├── README.txt │ ├── features │ │ ├── addition.feature │ │ ├── behavior.feature │ │ ├── initialization.feature │ │ ├── step_definitions │ │ │ ├── BoostCalculatorQtSteps.cpp │ │ │ ├── CalculatorQtSteps.cpp │ │ │ ├── GTestCalculatorQtSteps.cpp │ │ │ ├── QtTestCalculatorQtSteps.cpp │ │ │ └── cucumber.wire │ │ └── subtraction.feature │ └── src │ │ ├── CalcQt.cpp │ │ ├── Calculator.cpp │ │ ├── Calculator.hpp │ │ ├── CalculatorWidget.cpp │ │ └── CalculatorWidget.hpp └── FeatureShowcase │ ├── CMakeLists.txt │ ├── README.txt │ └── features │ ├── step_definitions │ ├── TableSteps.cpp │ ├── TagSteps.cpp │ └── cucumber.wire │ ├── table.feature │ └── tag.feature ├── include └── cucumber-cpp │ ├── autodetect.hpp │ ├── defs.hpp │ ├── generic.hpp │ └── internal │ ├── ContextManager.hpp │ ├── CukeCommands.hpp │ ├── CukeEngine.hpp │ ├── CukeEngineImpl.hpp │ ├── Macros.hpp │ ├── RegistrationMacros.hpp │ ├── Scenario.hpp │ ├── Table.hpp │ ├── connectors │ └── wire │ │ ├── ProtocolHandler.hpp │ │ ├── WireProtocol.hpp │ │ ├── WireProtocolCommands.hpp │ │ └── WireServer.hpp │ ├── defs.hpp │ ├── drivers │ ├── BoostDriver.hpp │ ├── DriverSelector.hpp │ ├── GTestDriver.hpp │ ├── GenericDriver.hpp │ └── QtTestDriver.hpp │ ├── hook │ ├── HookMacros.hpp │ ├── HookRegistrar.hpp │ └── Tag.hpp │ ├── step │ ├── StepMacros.hpp │ └── StepManager.hpp │ └── utils │ ├── IndexSequence.hpp │ └── Regex.hpp ├── run-linux.sh ├── run-windows.ps1 ├── src ├── CMakeLists.txt ├── ContextManager.cpp ├── CukeCommands.cpp ├── CukeEngine.cpp ├── CukeEngineImpl.cpp ├── HookRegistrar.cpp ├── Regex.cpp ├── Scenario.cpp ├── StepManager.cpp ├── Table.cpp ├── Tag.cpp ├── connectors │ └── wire │ │ ├── WireProtocol.cpp │ │ ├── WireProtocolCommands.cpp │ │ └── WireServer.cpp ├── drivers │ ├── BoostDriver.cpp │ ├── GTestDriver.cpp │ ├── GenericDriver.cpp │ └── QtTestDriver.cpp └── main.cpp └── tests ├── CMakeLists.txt ├── integration ├── ContextHandlingTest.cpp ├── HookRegistrationTest.cpp ├── StepRegistrationTest.cpp ├── TaggedHookRegistrationTest.cpp ├── WireProtocolTest.cpp ├── WireServerTest.cpp └── drivers │ ├── BoostDriverTest.cpp │ ├── GTestDriverTest.cpp │ ├── GenericDriverTest.cpp │ └── QtTestDriverTest.cpp ├── unit ├── BasicStepTest.cpp ├── ContextManagerTest.cpp ├── CukeCommandsTest.cpp ├── RegexTest.cpp ├── StepCallChainTest.cpp ├── StepManagerTest.cpp ├── TableTest.cpp └── TagTest.cpp └── utils ├── ContextManagerTestDouble.hpp ├── CukeCommandsFixture.hpp ├── DriverTestRunner.hpp ├── HookRegistrationFixture.hpp └── StepManagerTestDouble.hpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | AccessModifierOffset: -4 4 | AlignAfterOpenBracket: BlockIndent 5 | AlignEscapedNewlinesLeft: true 6 | AllowShortEnumsOnASingleLine: false 7 | AllowShortFunctionsOnASingleLine: None 8 | AlwaysBreakTemplateDeclarations: true 9 | BinPackArguments: false 10 | BinPackParameters: false 11 | BreakBeforeBinaryOperators: All 12 | BreakBeforeBraces: Attach 13 | BreakConstructorInitializers: AfterColon 14 | ColumnLimit: 100 15 | FixNamespaceComments: true 16 | IncludeCategories: 17 | # The autodetect header should always be included last 18 | - Regex: '^$' 19 | Priority: 3 20 | - Regex: '^["<]cucumber-cpp/' 21 | Priority: 1 22 | - Regex: '.*' 23 | Priority: 2 24 | IndentPPDirectives: BeforeHash 25 | IndentWidth: 4 26 | NamespaceIndentation: None 27 | PackConstructorInitializers: Never 28 | PenaltyBreakString: 1000 29 | PenaltyExcessCharacter: 10000 30 | PenaltyReturnTypeOnItsOwnLine: 1000 31 | PointerAlignment: Left 32 | ShortNamespaceLines: 200 33 | SortIncludes: false 34 | SpaceAfterTemplateKeyword: false 35 | SpaceBeforeAssignmentOperators: true 36 | SpaceBeforeParens: ControlStatements 37 | Standard: Cpp11 38 | ... 39 | 40 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Summary 8 | 9 | 10 | 11 | ## Expected Behavior 12 | 13 | 14 | 15 | 16 | 17 | ## Current Behavior 18 | 19 | 20 | 21 | 22 | 23 | ~~~ 24 | ~~~ 25 | 26 | ## Possible Solution 27 | 28 | 29 | 30 | 31 | ## Steps to Reproduce (for bugs) 32 | 33 | 34 | 35 | 1. 36 | 2. 37 | 3. 38 | 4. 39 | 40 | ## Context & Motivation 41 | 42 | 43 | 44 | 45 | ## Your Environment 46 | 47 | 48 | * Version used: 49 | * Operating System and version: 50 | * Link to your project: 51 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Summary 4 | 5 | 6 | 7 | ## Details 8 | 9 | 10 | 11 | ## Motivation and Context 12 | 13 | 14 | 15 | 16 | ## How Has This Been Tested? 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ## Types of changes 25 | 26 | 27 | - [ ] Bug fix (non-breaking change which fixes an issue). 28 | - [ ] New feature (non-breaking change which adds functionality). 29 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected). 30 | 31 | ## Checklist: 32 | 33 | 34 | 35 | - [ ] It is my own work, its copyright is implicitly assigned to the project and no substantial part of it has been copied from other sources (including [Stack Overflow](https://stackoverflow.com/)). In rare occasions this is acceptable, like in CMake modules where the original copyright information should be kept. 36 | - [ ] I'm using the same code standards as the existing code (indentation, spacing, variable naming, ...). 37 | - [ ] I've added tests for my code. 38 | - [ ] I have verified whether my change requires changes to the documentation 39 | - [ ] My change either requires no documentation change or I've updated the documentation accordingly. 40 | - [ ] My branch has been rebased to main, keeping only relevant commits. 41 | -------------------------------------------------------------------------------- /.github/workflows/format.yml: -------------------------------------------------------------------------------- 1 | name: check format 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | push: 8 | branches: 9 | - main 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | build: 17 | runs-on: ubuntu-22.04 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | 22 | - name: setup environment 23 | run: | 24 | sudo apt-get install --no-install-recommends \ 25 | clang-format-15 26 | 27 | - name: check code format 28 | run: | 29 | clang-format-15 --style=file --Werror --dry-run --verbose `find . -type d \( -name '3rdparty' \) -prune -o -regex '.*\.\(cpp\|hpp\)' -print` 30 | -------------------------------------------------------------------------------- /.github/workflows/linux-build.yml: -------------------------------------------------------------------------------- 1 | name: Linux build 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | push: 8 | branches: 9 | - main 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} 13 | cancel-in-progress: true 14 | 15 | 16 | jobs: 17 | build: 18 | strategy: 19 | matrix: 20 | cpp-compiler: 21 | - g++ 22 | - clang++-15 23 | cpp-standard: 24 | - 17 25 | - 20 26 | 27 | runs-on: ubuntu-22.04 28 | 29 | steps: 30 | - uses: actions/checkout@v2 31 | 32 | - name: setup environment 33 | run: | 34 | sudo apt-get install --no-install-recommends \ 35 | clang-15 \ 36 | cmake \ 37 | g++ \ 38 | git \ 39 | libasio-dev \ 40 | libboost-test-dev \ 41 | libgl1-mesa-dev \ 42 | libtclap-dev \ 43 | ninja-build \ 44 | nlohmann-json3-dev \ 45 | qt6-base-dev 46 | 47 | - name: install gtest 48 | run: | 49 | git clone https://github.com/google/googletest.git 50 | cd googletest 51 | mkdir build 52 | cd build 53 | cmake \ 54 | .. 55 | cmake --build . --parallel 56 | sudo cmake --install . 57 | 58 | - name: build 59 | run: | 60 | export CXXFLAGS=-Werror 61 | cmake -E make_directory build 62 | cmake -E chdir build cmake \ 63 | -DCMAKE_CXX_COMPILER=${{ matrix.cpp-compiler }} \ 64 | -DCMAKE_CXX_STANDARD=${{ matrix.cpp-standard }} \ 65 | -G Ninja \ 66 | -DCUKE_ENABLE_BOOST_TEST=on \ 67 | -DCUKE_ENABLE_GTEST=on \ 68 | -DCUKE_ENABLE_QT_6=on \ 69 | -DCUKE_ENABLE_EXAMPLES=on \ 70 | -DCUKE_TESTS_UNIT=on \ 71 | .. 72 | cmake --build build --parallel --verbose 73 | 74 | - name: unit tests 75 | run: | 76 | cmake --build build --target test 77 | -------------------------------------------------------------------------------- /.github/workflows/qt5.yml: -------------------------------------------------------------------------------- 1 | name: build and test with Qt5 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | push: 8 | branches: 9 | - main 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | build: 17 | runs-on: ubuntu-22.04 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | 22 | - name: setup environment 23 | run: | 24 | sudo apt-get install --no-install-recommends \ 25 | cmake \ 26 | g++ \ 27 | git \ 28 | libasio-dev \ 29 | libboost-test-dev \ 30 | libtclap-dev \ 31 | ninja-build \ 32 | nlohmann-json3-dev \ 33 | qtbase5-dev \ 34 | ruby \ 35 | ruby-dev 36 | 37 | - name: install ruby tools 38 | run: | 39 | sudo gem install bundler 40 | sudo bundle install 41 | 42 | - name: install gtest 43 | run: | 44 | git clone https://github.com/google/googletest.git 45 | cd googletest 46 | mkdir build 47 | cd build 48 | cmake ../ 49 | cmake --build . --parallel 50 | sudo cmake --install . 51 | 52 | - name: build 53 | run: | 54 | export CXXFLAGS=-Werror 55 | cmake -E make_directory build 56 | cmake -E chdir build cmake \ 57 | -G Ninja \ 58 | -DCUKE_ENABLE_BOOST_TEST=on \ 59 | -DCUKE_ENABLE_GTEST=on \ 60 | -DCUKE_ENABLE_QT_5=on \ 61 | -DCUKE_ENABLE_EXAMPLES=on \ 62 | -DCUKE_TESTS_UNIT=on \ 63 | .. 64 | cmake --build build --parallel --verbose 65 | 66 | - name: unit tests 67 | run: | 68 | cmake --build build --target test 69 | 70 | - name: QtCalc examples 71 | run: | 72 | for TEST in \ 73 | build/examples/CalcQt/GTestCalculatorQtSteps \ 74 | build/examples/CalcQt/QtTestCalculatorQtSteps \ 75 | build/examples/CalcQt/BoostCalculatorQtSteps \ 76 | ; do 77 | "${TEST}" 2> /dev/null & 78 | sleep 1 79 | (cd examples/CalcQt; cucumber) 80 | wait % 81 | done 82 | -------------------------------------------------------------------------------- /.github/workflows/run-all.yml: -------------------------------------------------------------------------------- 1 | name: run all 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | push: 8 | branches: 9 | - main 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | build-linux: 17 | runs-on: ubuntu-22.04 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | - name: update package index 23 | run: sudo apt-get -y update 24 | 25 | - name: setup environment 26 | run: | 27 | sudo apt-get install --no-install-recommends \ 28 | cmake \ 29 | g++ \ 30 | gcovr \ 31 | git \ 32 | libasio-dev \ 33 | libboost-test-dev \ 34 | libgl1-mesa-dev \ 35 | libtclap-dev \ 36 | ninja-build \ 37 | nlohmann-json3-dev \ 38 | qt6-base-dev \ 39 | ruby \ 40 | ruby-dev 41 | 42 | - name: install ruby tools 43 | run: | 44 | sudo gem install bundler 45 | sudo bundle install 46 | 47 | - name: install gtest 48 | run: | 49 | git clone https://github.com/google/googletest.git 50 | cd googletest 51 | mkdir build 52 | cd build 53 | cmake ../ 54 | cmake --build . --parallel 55 | sudo cmake --install . 56 | 57 | - name: build and run 58 | run: | 59 | export CXXFLAGS=-Werror 60 | ./run-linux.sh 61 | 62 | - name: code coverage summary report 63 | uses: irongut/CodeCoverageSummary@v1.3.0 64 | with: 65 | filename: coverage/cobertura.xml 66 | indicators: false 67 | hide_complexity: true 68 | format: markdown 69 | output: file 70 | 71 | - name: publish code coverage summary 72 | run: | 73 | echo '# Code Coverage Report' >> $GITHUB_STEP_SUMMARY 74 | cat code-coverage-results.md >> $GITHUB_STEP_SUMMARY 75 | -------------------------------------------------------------------------------- /.github/workflows/windows-build.yml: -------------------------------------------------------------------------------- 1 | name: Windows build 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | push: 8 | branches: 9 | - main 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | build: 17 | strategy: 18 | matrix: 19 | cpp-standard: 20 | - 17 21 | - 20 22 | # You can find specific tool versions for Windows builds in the Runner specification: 23 | # https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md 24 | # In particular, this build uses: 25 | # cmake: 3.27.9 26 | # VSCode: 2022 Enterprise Edition (corresponding C++ version: https://blog.knatten.org/2022/08/26/microsoft-c-versions-explained/) 27 | # Ruby: 3.0.6p216 28 | # boost: 1.82.0 29 | runs-on: windows-2022 30 | env: 31 | BOOST_VERSION: 1.82.0 32 | NLOHMANN_CLONE_DIR: nlohmann 33 | NLOHMANN_TAG: v3.11.3 34 | ASIO_CLONE_DIR: asio 35 | ASIO_TAG: asio-1-29-0 36 | TCLAP_CLONE_DIR: tclap 37 | TCLAP_TAG: v1.2.5 38 | 39 | steps: 40 | - uses: actions/checkout@v4 41 | 42 | - name: install ruby tools 43 | run: | 44 | gem install bundler 45 | bundle install 46 | 47 | # - name: Install Google Test 48 | # uses: MarkusJx/googletest-installer@v1.1 49 | 50 | - name: Restore cached boost dependencies 51 | id: cache-boost-deps 52 | uses: actions/cache@v3 53 | with: 54 | path: | 55 | boost_1_82_0 56 | key: ${{ runner.os }}-boost-1820 57 | 58 | - name: install boost 59 | if: steps.cache-boost-deps.outputs.cache-hit != 'true' 60 | run: | 61 | $boost_version_str = ${Env:BOOST_VERSION}.Replace(".","_") 62 | $ProgressPreference = 'SilentlyContinue' 63 | Invoke-WebRequest -Uri https://boostorg.jfrog.io/artifactory/main/release/${Env:BOOST_VERSION}/source/boost_${boost_version_str}.zip -OutFile boost_${boost_version_str}.zip 64 | 7z x boost_${boost_version_str}.zip 65 | cd boost_${boost_version_str} 66 | cmd /C bootstrap 67 | ./b2.exe --build-type=complete toolset=msvc --with-regex --with-program_options --with-system --with-test 68 | 69 | - name: Get and build nlohmann-json 70 | run: | 71 | Start-Process "git" -ArgumentList "clone https://github.com/nlohmann/json.git $Env:NLOHMANN_CLONE_DIR --depth 1 --branch $Env:NLOHMANN_TAG" -PassThru -NoNewWindow -Wait 72 | cd $Env:NLOHMANN_CLONE_DIR 73 | cmake -B build -S . 74 | cd .. 75 | 76 | - name: Get ASIO 77 | run: Start-Process "git" -ArgumentList "clone https://github.com/chriskohlhoff/asio.git $Env:ASIO_CLONE_DIR --depth 1 --branch $Env:ASIO_TAG" -PassThru -NoNewWindow -Wait 78 | 79 | - name: Get TCLAP 80 | run: Start-Process "git" -ArgumentList "clone https://github.com/mirror/tclap.git $Env:TCLAP_CLONE_DIR --depth 1 --branch $Env:TCLAP_TAG" -PassThru -NoNewWindow -Wait 81 | 82 | - name: build and run 83 | run: | 84 | $current_script_dir = Get-Location | Select-Object -Expand "Path" 85 | $Env:nlohmann_json_DIR = "${current_script_dir}/$Env:NLOHMANN_CLONE_DIR/build" 86 | $Env:Asio_ROOT = "${current_script_dir}/$Env:ASIO_CLONE_DIR/asio" 87 | $Env:TCLAP_ROOT = "${current_script_dir}/$Env:TCLAP_CLONE_DIR" 88 | $Env:cpp_standard = ${{ matrix.cpp-standard }} 89 | ./run-windows.ps1 90 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Bundler 2 | /Gemfile.lock 3 | 4 | # rvm 5 | /.ruby-version 6 | /.ruby-gemset 7 | 8 | # Build artifacts 9 | /build/ 10 | /coverage/ 11 | /.local/ 12 | 13 | # vim swap files 14 | *.swp 15 | 16 | # CLion 17 | /.idea 18 | /cmake-build-*/ 19 | 20 | # Qt Creator 21 | /CMakeLists.txt.user 22 | 23 | # build folder 24 | build 25 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## About to create a new Github Issue? 2 | 3 | We appreciate that. But before you do, please learn our basic rules: 4 | 5 | * Do you have a feature request? Then don't expect it to be implemented unless you or someone else sends a [pull request](https://help.github.com/articles/using-pull-requests). 6 | * Reporting a bug? We need to know what compiler, operating system and architecture (32 or 64 bit) you are using, including versions of all libraries. Bugs with [pull requests](https://help.github.com/articles/using-pull-requests) get fixed quicker. Some bugs may never be fixed. 7 | * You have to tell us how to reproduce a bug. Bonus point for a [pull request](https://help.github.com/articles/using-pull-requests) with a failing test that reproduces the bug. 8 | * Want to paste some code or output? Put \`\`\` on a line above and below your code/output. See [GFM](https://help.github.com/articles/github-flavored-markdown)'s *Fenced Code Blocks* for details. 9 | * We love [pull requests](https://help.github.com/articles/using-pull-requests), but if you don't have a test to go with it we probably won't merge it. 10 | 11 | ## Contributing 12 | 13 | Before you can contribute, you have to be able to build the source and run tests. 14 | 15 | ### The Github Process 16 | 17 | The process for using git/github is similar to the [Github-Flow](http://scottchacon.com/2011/08/31/github-flow.html) 18 | 19 | * **Anything** in the main branch is good enough to release 20 | * Working on nontrivial features 21 | + Create a descriptively named branch off of main 22 | + Commit to that branch locally and regularly 23 | + Push your work to the same named branch on the server 24 | + Regularly rebase this branch from main to keep it up to date 25 | * Open a pull request 26 | + When you need feedback or help 27 | + You think the branch is ready for merging (you can use the [hub](https://github.com/defunkt/hub#git-pull-request) command-line tool) 28 | * For any nontrivial change, even if you have the rights to merge the pull request yourself, wait before someone else has reviewed and agreed on the change 29 | 30 | Here is an [Example](https://github.com/cucumber/bool/pull/12) of this process in action 31 | 32 | #### Tips for good commits 33 | 34 | 1. Read up on [Github Flavored Markdown](https://help.github.com/articles/github-flavored-markdown) 35 | + Especially links and syntax highlighting. GFM can be used in tickets as well as commit messages (e.g. put "#4" somewhere in a commit message to link ticket 4 to that commit 36 | 2. Close tickets with commits if you can 37 | + Add "Closes #5, #9" somewhere in the commit message to both link and close. See [Issues 2.0 the Next Generation](https://github.com/blog/831-issues-2-0-the-next-generation) for details. 38 | + Use [this script](https://gist.github.com/aslakhellesoy/4754009) to compile and view GFM locally 39 | 3. Subscribe to ticket feeds so you stay in the loop and get a chance to provide feedback on tickets 40 | 4. The code standard is the existing code 41 | + Use the same indentation, spacing, line ending, ASCII for source code, UTF-8 everywhere else 42 | 5. Use git diff (or git diff --cached if you have staged) before every commit 43 | + This helps you avoid committing changes you didn't mean to 44 | 45 | ## Maintainers' guide 46 | 47 | ### Merge a PR 48 | 49 | - Verify that: 50 | - All checks have passed 51 | - At least one maintainer has approved any non-trivial change, and a 52 | discussion has occurred for any breaking change 53 | - The branch does not need rebasing or squashing of commits 54 | - To merge: 55 | - Follow the command line instructions on GitHub 56 | - If it is either a new feature or a bugfix, specify the `--no-commit` 57 | flag when merging and add a line to `CHANGELOG.md` following the 58 | current convention. Add this file to the changes to be committed and 59 | commit the merge. 60 | - Commit message should follow the current convention: 61 | `Merge #42 'Description of the change usually from the PR description'` 62 | 63 | ### Do a release 64 | 65 | - Release commit (e.g. [fdf8a5c](https://github.com/cucumber/cucumber-cpp/commit/fdf8a5c4ef4c51dfa7ea82077f706414a4c6322d)): 66 | - Change `CHANGELOG.md` renaming the "In Git" section with the release number and date 67 | - Commit with message `Update changelog for the X.Y.Z release` 68 | - Create an annotated tag for this commit named `vX.Y.Z` 69 | - New development branch commit (e.g. [da60995](https://github.com/cucumber/cucumber-cpp/commit/da609956fcd42046e5182c6226acd7e53dd7754e)): 70 | - Add new "In Git" section to `CHANGELOG.md` 71 | - Commit with message `Preparing history file for next development release` 72 | - Push commits and tags to main 73 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | group :test do 4 | gem 'cucumber', "=7.1.0" 5 | gem 'cucumber-wire', "=6.2.1" 6 | end 7 | 8 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010 Paolo Ambrosio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cucumber-CPP 2 | 3 | ## Overview 4 | 5 | Cucumber-Cpp allows Cucumber to support step definitions written in C++. 6 | 7 | * [Cucumber-Cpp Website](https://github.com/cucumber/cucumber-cpp) 8 | * [Cucumber-Cpp Documentation](https://github.com/cucumber/cucumber-cpp/wiki/) 9 | * [Cucumber Website](https://cucumber.io/) 10 | * [Get in touch](https://cucumber.io/docs/community/get-in-touch/) 11 | 12 | If you need to ask a question, post on the [Cucumber discussion group](https://github.com/orgs/cucumber/discussions). 13 | 14 | If you want to contribute code to the project, guidelines are in [CONTRIBUTING.md](CONTRIBUTING.md). 15 | 16 | ## Dependencies 17 | 18 | It relies on a few executables: 19 | 20 | * [cmake](https://cmake.org/download/) 3.16 or later. 21 | Required to setup environment and build software 22 | 23 | It relies on a few libraries: 24 | 25 | * [Asio](https://think-async.com/Asio/) 1.18.1 or later. 26 | * [Boost.Test](https://www.boost.org/) 1.70. Optional for the Boost Test driver. 27 | * [GTest](https://github.com/google/googletest) 1.11.0 or later. Optional for the GTest driver. 28 | * [GMock](https://github.com/google/googletest) 1.11.0 or later. Optional for the internal test suite. 29 | * [nlohmann-json](https://github.com/nlohmann/json) 3.10.5 or later. 30 | * [Qt6 or Qt5](https://qt-project.org/). Optional for the CalcQt example and QtTest driver. 31 | * [TCLAP](https://tclap.sourceforge.net/) 1.2.5 or later. 32 | 33 | It might work with earlier versions of the libraries, but it was not tested with them. 34 | See the [CI scripts](.github/workflows/run-all.yml) for details about dependency installation. 35 | 36 | Cucumber-Cpp uses the wire protocol at the moment, so you will need 37 | Cucumber-Ruby installed and available on the path. It is also needed 38 | to run the functional test suite. 39 | 40 | Please mind that Cucumber-Cpp is not compatible with Cucumber-Ruby 3.x 41 | due to a [bug in its wire protocol](https://github.com/cucumber/cucumber-ruby/issues/1183) 42 | implementation. 43 | 44 | To install the Ruby prerequisites: 45 | 46 | ``` 47 | gem install bundler // For windows: gem install bundle 48 | bundle install 49 | ``` 50 | 51 | ### Windows vs. Linux 52 | 53 | To get an inspiration on how to set up the dependencies on your specific system (Windows or Linux), you may want to have a look at the 54 | workflow files [for Windows](.github/workflows/windows-build.yml) and [for Linux](.github/workflows/linux-build.yml). 55 | 56 | 57 | ## Build 58 | 59 | Building Cucumber-Cpp with tests and samples: 60 | 61 | ``` 62 | # Create build directory 63 | cmake -E make_directory build 64 | 65 | # Generate Makefiles 66 | cmake -E chdir build cmake \ 67 | -DCUKE_ENABLE_BOOST_TEST=on \ 68 | -DCUKE_ENABLE_GTEST=on \ 69 | -DCUKE_ENABLE_QT_6=on \ 70 | -DCUKE_TESTS_UNIT=on \ 71 | -DCUKE_ENABLE_EXAMPLES=on \ 72 | .. 73 | 74 | # Build cucumber-cpp 75 | cmake --build build 76 | 77 | # Run unit tests 78 | cmake --build build --target test 79 | 80 | # Run install 81 | cmake --install build 82 | ``` 83 | 84 | Running the Calc example on Unix: 85 | 86 | ``` 87 | build/examples/Calc/BoostCalculatorSteps >/dev/null & 88 | (cd examples/Calc; cucumber) 89 | ``` 90 | 91 | Running the Calc example on Windows (NMake): 92 | 93 | ``` 94 | start build\examples\Calc\BoostCalculatorSteps.exe 95 | cucumber examples\Calc 96 | ``` 97 | 98 | ## The way it works 99 | (This is a great explanation by [paoloambrosio](https://github.com/paoloambrosio) copied from [stackoverflow](https://stackoverflow.com/questions/50760865/cucumber-cpp-required-software-for-running-example)) 100 | 101 | The way Cucumber-CPP currently works is by having Cucumber-Ruby connecting to a TCP port where the C++ implementation is listening. When the wire protocol is defined in the cucumber.wire file, with host and port where your C++ wire protocol server is listening, Cucumber-Ruby will try and run them with Cucumber-CPP. 102 | 103 | C++ is a compiled language, so step definitions must be compiled first. The examples provided use CMake, as described in the README. Cucumber-CPP needs to be linked to the step definitions and to everything that they use (usually the application under test), creating an executable file that will listen to the wire protocol port (defaults to localhost:3902) for Cucumber-Ruby to connect to (and exiting when it disconnects). 104 | 105 | ``` 106 | +------------------------------------------+ 107 | | | 108 | +----------+ | +----------+ +----------+ +----------+ | 109 | | | | | | | | | | | 110 | | Cucumber | | | Cucumber | | C++ Step | | Your | | 111 | | Ruby |--------->| CPP Wire |--| Defs |--| CPP App | | 112 | | | | | Server | | | | | | 113 | | | | | | | | | | | 114 | +----------+ | +----------+ +----------+ +----------+ | 115 | | | 116 | +------------------------------------------+ 117 | ``` 118 | 119 | ## Getting started 120 | 121 | Here is a basic example on how to get started with *cucumber-cpp*. First you need to create the basic feature structure: 122 | 123 | ``` 124 | cucumber --init 125 | ``` 126 | 127 | Then create a *cucumber.wire* file in the *features/step_definitions* folder with the following content: 128 | 129 | ``` 130 | host: localhost 131 | port: 3902 132 | ``` 133 | 134 | Create your first feature (an example is available [here](examples/Calc/features/addition.feature)). 135 | 136 | Then create your step definition runner (an example is available [here](examples/Calc/features/step_definitions/BoostCalculatorSteps.cpp)). In order to compile the step definition runner, make sure to add [cucumber include directory](include/cucumber-cpp) to the include path and link with *libcucumber-cpp.a* and additional testing libraries (boost unit test). 137 | 138 | Run the step definition runner in the background and then cucumber, like in the Calc example in the previous section. The step definition runner should exit after the feature is run and cucumber exits. 139 | -------------------------------------------------------------------------------- /cmake/modules/FindAsio.cmake: -------------------------------------------------------------------------------- 1 | find_path(ASIO_INCLUDE_DIR asio.hpp) 2 | 3 | if (ASIO_INCLUDE_DIR) 4 | set(ASIO_FOUND TRUE) 5 | else () 6 | set(ASIO_FOUND FALSE) 7 | endif () 8 | 9 | include(FindPackageHandleStandardArgs) 10 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(Asio REQUIRED_VARS ASIO_INCLUDE_DIR) 11 | -------------------------------------------------------------------------------- /cmake/modules/FindTCLAP.cmake: -------------------------------------------------------------------------------- 1 | find_path(TCLAP_INCLUDE_DIR tclap/CmdLine.h) 2 | 3 | if (TCLAP_INCLUDE_DIR) 4 | set(TCLAP_FOUND TRUE) 5 | else () 6 | set(TCLAP_FOUND FALSE) 7 | endif () 8 | 9 | include(FindPackageHandleStandardArgs) 10 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(TCLAP REQUIRED_VARS TCLAP_INCLUDE_DIR) 11 | -------------------------------------------------------------------------------- /cmake/modules/FindValgrind.cmake: -------------------------------------------------------------------------------- 1 | #.rst: 2 | # FindValgrind 3 | # ------- 4 | # 5 | # The module defines the following variables: 6 | # 7 | # ``VALGRIND_EXECUTABLE`` 8 | # Path to Valgrind command-line client. 9 | # ``Valgrind_FOUND`` 10 | # True if the Valgrind command-line client was found. 11 | # ``VALGRIND_VERSION_STRING`` 12 | # The version of Valgrind found. 13 | # 14 | # Example usage: 15 | # 16 | # .. code-block:: cmake 17 | # 18 | # find_package(Valgrind) 19 | # if(Valgrind_FOUND) 20 | # message("Valgrind found: ${VALGRIND_EXECUTABLE}") 21 | # endif() 22 | 23 | #============================================================================= 24 | # Copyright (c) 2017 Giel van Schijndel 25 | # 26 | # CMake - Cross Platform Makefile Generator 27 | # All rights reserved. 28 | # 29 | # Redistribution and use in source and binary forms, with or without 30 | # modification, are permitted provided that the following conditions 31 | # are met: 32 | # 33 | # * Redistributions of source code must retain the above copyright 34 | # notice, this list of conditions and the following disclaimer. 35 | # 36 | # * Redistributions in binary form must reproduce the above copyright 37 | # notice, this list of conditions and the following disclaimer in the 38 | # documentation and/or other materials provided with the distribution. 39 | # 40 | # * Neither the names of Kitware, Inc., the Insight Software Consortium, 41 | # nor the names of their contributors may be used to endorse or promote 42 | # products derived from this software without specific prior written 43 | # permission. 44 | # 45 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 46 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 47 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 48 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 49 | # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 51 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 55 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 | # 57 | # ------------------------------------------------------------------------------ 58 | # 59 | # The above copyright and license notice applies to distributions of 60 | # CMake in source and binary form. Some source files contain additional 61 | # notices of original copyright by their contributors; see each source 62 | # for details. Third-party software packages supplied with CMake under 63 | # compatible licenses provide their own copyright notices documented in 64 | # corresponding subdirectories. 65 | # 66 | # ------------------------------------------------------------------------------ 67 | # 68 | # CMake was initially developed by Kitware with the following sponsorship: 69 | # 70 | # * National Library of Medicine at the National Institutes of Health 71 | # as part of the Insight Segmentation and Registration Toolkit (ITK). 72 | # 73 | # * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel 74 | # Visualization Initiative. 75 | # 76 | # * National Alliance for Medical Image Computing (NAMIC) is funded by the 77 | # National Institutes of Health through the NIH Roadmap for Medical Research, 78 | # Grant U54 EB005149. 79 | # 80 | # * Kitware, Inc. 81 | #============================================================================= 82 | 83 | find_program(VALGRIND_EXECUTABLE 84 | NAMES valgrind 85 | DOC "Valgrind command line executable" 86 | ) 87 | mark_as_advanced(VALGRIND_EXECUTABLE) 88 | 89 | if(VALGRIND_EXECUTABLE) 90 | execute_process(COMMAND ${VALGRIND_EXECUTABLE} --version 91 | OUTPUT_VARIABLE VALGRIND_VERSION_STRING 92 | ERROR_QUIET 93 | OUTPUT_STRIP_TRAILING_WHITESPACE) 94 | if (VALGRIND_VERSION_STRING MATCHES "^valgrind-[0-9]") 95 | string(REPLACE "valgrind-" "" VALGRIND_VERSION_STRING "${VALGRIND_VERSION_STRING}") 96 | endif() 97 | endif() 98 | 99 | include(FindPackageHandleStandardArgs) 100 | find_package_handle_standard_args(Valgrind 101 | REQUIRED_VARS VALGRIND_EXECUTABLE 102 | VERSION_VAR VALGRIND_VERSION_STRING) 103 | -------------------------------------------------------------------------------- /cmake/modules/GitVersion.cmake: -------------------------------------------------------------------------------- 1 | function(git_get_version VERSION_VARIABLE) 2 | find_program(GIT_EXECUTABLE git) 3 | 4 | if(NOT GIT_EXECUTABLE) 5 | message(FATAL_ERROR "Git not found. Please install Git and make sure it is in your system's PATH.") 6 | endif() 7 | 8 | execute_process( 9 | COMMAND ${GIT_EXECUTABLE} describe --always --dirty 10 | OUTPUT_VARIABLE VERSION_STRING 11 | OUTPUT_STRIP_TRAILING_WHITESPACE 12 | WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" 13 | ERROR_VARIABLE GIT_DESCRIBE_ERROR 14 | RESULT_VARIABLE GIT_DESCRIBE_RESULT 15 | ) 16 | 17 | if(NOT GIT_DESCRIBE_RESULT EQUAL 0) 18 | message(FATAL_ERROR "Error running 'git describe': ${GIT_DESCRIBE_ERROR}") 19 | endif() 20 | 21 | string(LENGTH "${VERSION_STRING}" VERSION_STRING_LENGTH) 22 | string(SUBSTRING "${VERSION_STRING}" 0 1 FIRST_CHARACTER) 23 | 24 | if("${FIRST_CHARACTER}" STREQUAL "v") 25 | string(SUBSTRING "${VERSION_STRING}" 1 ${VERSION_STRING_LENGTH} VERSION_STRING) 26 | endif() 27 | 28 | set(${VERSION_VARIABLE} ${VERSION_STRING} PARENT_SCOPE) 29 | endfunction() 30 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(Calc) 2 | add_subdirectory(CalcQt) 3 | add_subdirectory(FeatureShowcase) 4 | -------------------------------------------------------------------------------- /examples/Calc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(Calc) 2 | 3 | add_library(Calc STATIC src/Calculator.cpp) 4 | target_include_directories(Calc INTERFACE src) 5 | 6 | if(TARGET GTest::gtest) 7 | add_executable(GTestCalculatorSteps features/step_definitions/GTestCalculatorSteps.cpp) 8 | target_link_libraries(GTestCalculatorSteps PRIVATE Calc cucumber-cpp GTest::gtest) 9 | 10 | add_executable(FuncArgsCalculatorSteps features/step_definitions/FuncArgsCalculatorSteps.cpp) 11 | target_link_libraries(FuncArgsCalculatorSteps PRIVATE Calc cucumber-cpp GTest::gtest) 12 | endif() 13 | 14 | if(TARGET Boost::unit_test_framework) 15 | add_executable(BoostCalculatorSteps features/step_definitions/BoostCalculatorSteps.cpp) 16 | target_link_libraries(BoostCalculatorSteps PRIVATE Calc cucumber-cpp Boost::unit_test_framework) 17 | endif() 18 | 19 | if(TARGET Qt::Test) 20 | add_executable(QtTestCalculatorSteps features/step_definitions/QtTestCalculatorSteps.cpp) 21 | target_link_libraries(QtTestCalculatorSteps Calc Qt::Test cucumber-cpp) 22 | endif() 23 | -------------------------------------------------------------------------------- /examples/Calc/README.txt: -------------------------------------------------------------------------------- 1 | This was inspired by Cuke4Nuke Calc sample 2 | 3 | -------------------------------------------------------------------------------- /examples/Calc/features/addition.feature: -------------------------------------------------------------------------------- 1 | # language: en 2 | Feature: Addition 3 | In order to avoid silly mistakes 4 | As a math idiot 5 | I want to be told the sum of two numbers 6 | 7 | Scenario Outline: Add two numbers 8 | Given I have entered into the calculator 9 | And I have entered into the calculator 10 | When I press