Skip to content

GUnit - Google.Test/Google.Mock/Cucumber on steroids

Notifications You must be signed in to change notification settings

cpp-testing/GUnit

Repository files navigation

Boost LicenceVersionBuildBuildCoverallsGithub Issues


Testing

"If you liked it then you should have put a test on it", Beyonce rule

GUnit

Google.Test/Google.Mock/Cucumber on steroids

  • Improve your productivity with GUnit, a library which extends/simplifies Google.Test/Google.Mock and adds support for Gherkin (Behaviour Driven Development) to it.

Motivation Examples

No more base classes, labels as identifiers and special assertions - GUnit.GTest / GUnit.GTest-Lite

 Google.Test | GUnit.GTest -----------------------------------------------+----------------------------------------- #include<gtest/gtest.h> | #include <GUnit.h> | structCalcTest : testing::Test{| GTEST("Calc Test"){voidSetUp() override{| Calc calc{}; calc = std::make_unique<Calc>(); | } | // SetUp | voidTearDown() override{} | SHOULD("return sum of 2 numbers"){| EXPECT(5 == calc->add(4, 1)); std::unique_ptr<Calc> calc; | } }; | | SHOULD("throw if division by 0"){TEST_F(CalcTest, ShouldReturnSumOf2Numbers){| EXPECT_ANY_THROW(calc->div(42, 0)); EXPECT_EQ(5, calc->add(4, 1)); | } } | | // TearDownTEST_F(CalcTest, ShouldThrowIfDivisionBy0){| } EXPECT_ANY_THROW(calc->div(42, 0)); | } |

Output

[----------] 2 tests from CalcTest | [----------] 1 tests from Calc Test [ RUN ] CalcTest.ShouldReturnSumOf2Numbers| [ RUN ] Calc Test [ OK ] CalcTest.ShouldReturnSumOf2Numbers| [ SHOULD ] return sum of 2 numbers [ RUN ] CalcTest.ShouldThrowIfDivisionBy0 | [ SHOULD ] throw if division by 0 [ OK ] CalcTest.ShouldThrowIfDivisionBy0 | [ OK ] Calc Test (0 ms) [----------] 2 tests from CalcTest (1 ms total)| [----------] 1 tests from Example

No more hand written mocks - GUnit.GMock

structinterface{virtual~interface() = default; virtualintget() const = 0; virtualvoidfoo(int) = 0; virtualvoidbar(int, const std::string&) = 0};
 Google.Test | GUnit.GMock -----------------------------------------------+-------------------------------------- #include<gmock/gmock.h> | #include <GUnit.h> | structmock_interface : interface{| MOCK_CONST_METHOD0(get, int(int)); | MOCK_METHOD1(foo, void(int)); | MOCK_METHOD2(bar, void(int, const string&)); | }; | | intmain(){| intmain(){StrictMock<mock_interface> mock{}; | StrictGMock<interface> mock{}; EXPECT_CALL(mock, foo(42)); | EXPECT_CALL(mock, (foo)(42)); | interface& i = mock; | interface& i = mock.object(); i.foo(42); | i.foo(42)} | }

Simplified creation and injection of SUT (System Under Test) and mocks - GUnit.GMake

classcoffee_maker{public:coffee_maker(iheater&, ipump&, igrinder&); ... };
 Google.Test | GUnit.GMake ----------------------------------------+-------------------------------------------------- #include<gtest/gtest.h> | #include <GUnit.h> #include<gmock/gmock.h> | | TEST(CalcTest, ShouldMakeCoffee){| GTEST("Calc Test"){StrictMock<mock_heater> heater{}; | auto [sut, mocks] = StrictMock<mock_pump> pump{}; | make<coffee_maker, StrictGMock>(); StrictMock<mock_grinder> grinder{}; | coffee_maker sut{heater,pump,grinder};| EXPECT_CALL(mocks.mock<iheater>(), (on)()); | EXPECT_CALL(mocks.mock<ipump>(), (pump)()); EXPECT_CALL(heater, on()); | EXPECT_CALL(mocks.mock<igrinder>(), (grind)()); EXPECT_CALL(pump, pump()); | EXPECT_CALL(mocks.mock<iheater>(), (off)()); EXPECT_CALL(grinder, grind()); | EXPECT_CALL(heater, off()); | sut->brew(); | } sut->brew(); | }

Support for - Gherkin style - BDD (Behaviour Driven Development) scenarios - GUnit.GSteps

Feature specification

Test/Features/Calc/addition.feature 
Feature: Calc Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers Scenario: Add two numbersGiven I created a calculator with value 0 And I have entered 20 into the calculator And I have entered 30 into the calculator When I press add Then The result should be 50

Steps Implementation

Test/Features/Calc/Steps/CalcSteps.cpp 
#include<GUnit.h>GSTEPS("Calc*"){// "Calc Addition.Add two numbers"auto result = 0; Given("I created a calculator with value{n}") = [&](int n){Calculator calc{n}; Given("I have entered{n} into the calculator") = [&](int n){calc.push(n)}; When("I press add") = [&]{result = calc.add()}; Then("The result should be{expected}") = [&](int expected){EXPECT_EQ(expected, result)}}}

Usage

SCENARIO="Test/Features/Calc/addition.feature" \ ./test --gtest_filter="Calc Addition.Add two numbers"

Output

[==========] Running 1 test from 1 test case. [----------] Global test environment set-up. [----------] 1 tests from Calc Addition [ RUN ] Calc Addition.Add two numbers [ Given ] I have created a calculator with value 0 # CalcSteps.cpp:10 [ Given ] I have entered 20 into the calculator # CalcSteps.cpp:12 [ Given ] I have entered 30 into the calculator # CalcSteps.cpp:14 [ When ] I press add # CalcSteps.cpp:16 [ Then ] the result should be 50 on the screen # CalcSteps.cpp:19 [----------] Global test environment tear-down [==========] 1 test from 1 testcase ran. (7 ms total) [ PASSED ] 1 tests.

Overview

  • GUnit.GTest - Google.Test with strings and more friendly macros
    • Test cases with string as names
    • No more SetUp/TearDown (SHOULD clauses)
    • One (GTEST) macro for all types of tests
    • 100% Compatible with tests using GTest
  • GUnit.GTest-Lite - lightweight, limited, no-macro way of defining simple tests
  • GUnit.GMock - Google.Mock without hand written mocks
    • No more hand written mocks!
    • Support for more than 10 parameters
    • Quicker compilation times
    • Support for unique_ptr without any tricks
    • Support for overloaded operators
    • Support for mocking classes with constructors
    • 100% Compatible with Google Mocks
  • GUnit.GMake - Makes creation of System Under Test (SUT) and Mocks easier
    • No need to instantiate SUT (System Under Test) and mocks
      • Automatic mocks injection
  • GUnit.GSteps - Behaviour Driven Development
    • Support for - Gherkin style - BDD tests
  • GUnit.GAssert - Google.Test assertions without postfixes
    • Simple/consised interface - EXPECT(true); EXPECT(.0 > 2.0); ASSERT(11 != 42), ...
    • No more EXPECT_EQ/EXPECT_GT/...
    • No more confusing error messages depending on expected, given parameters
    • No more bugs due to using the wrong EXPECT for floating point numbers (EXPECT_DOUBLE_EQ) and/or strings
    • No more implicit conversions between types!

Quick Start

Quick Start (CMake)

  • Add to your CMakeLists.txt the following lines:
    include(FetchContent) FetchContent_Declare( gunit GIT_REPOSITORY https://github.com/cpp-testing/GUnit.git GIT_TAG master ) FETCHCONTENT_MAKEAVAILABLE(gunit) 
  • Write some tests...
  • Compile and Run

When using the installation method as described here you may fully skip this step.

  • gherkin support using CMake
    • gherkin-cpp using add_subdirectory
      # using add_subdirectory from the top-level CMakeLists.txt file: add_subdirectory(gunit)
      # src/CMakeLists.txt contains either this: add_executable(myprogram) target_link_libraries(myprogram gunit) ... # or you could have also been more explicit, then you would write this: target_link_libraries(myprogram gtest gtest_main)
    • gherkin-cpp using a ExternalProject_Add(gunit ...) Note: This sections needs updates, when writing the gherkin-cpp CMake integration I used add_subdirectory:
      • Add include paths
        • -I GUnit_install_dir/include
      • Link with libgherkin-cpp.{a, so} Note: I wasn't able to nest the fmem/gherkin into libghekin-cpp, so two more libs to add: fmem/gherkin!
        • -L gherkin-cpp
        • -L fmem
        • -L gherkin
      • Write some feature tests...
      • Compile and Run!

  • To run GUnit tests/benchmarks
    $mkdir build &&cd build && cmake .. $make&& ctest

Requirements

Tested compilers

User Guide

Acknowledgements

About

GUnit - Google.Test/Google.Mock/Cucumber on steroids

Topics

Resources

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 19