Skip to content

Latest commit

 

History

History
213 lines (175 loc) · 5.24 KB

GSteps.md

File metadata and controls

213 lines (175 loc) · 5.24 KB

GUnit.GSteps - BDD (Given/When/Then - Gherkin) scenarios

  • Gherkin reference

  • Building libgherkin-cpp

    $cd libs/gherkin-cpp && make lib
    $ls libs/gherkin-cpp
      libgherkin-cpp.a
      libgherkin-cpp.so
    
  • Synopsis

    /**
     * @param feature.scenario regex expression matching a feature name
     *        example: "Calc*" - all scenarios from Calc feature
     *        example: "Calc Addition.Add two numbers" - Only 'Add two numbers' scenario from Calc feature
     */
    #define GSTEPS(name) // register steps for a feature.scenario
    
    namespace testing {
      /**
       * Thrown when implementation for given step can't be found
       */
      struct StepIsNotImplemented : std::runtime_error;
    
      /**
       * Thrown when more than one implementation for given step was be found
       */
      struct StepIsAmbiguous : std::runtime_error;
    
      /**
       * Verify whether parameters provided in the step and lambda expression
       * matches at compile-time
       */
      constexpr auto operator""_step();
    
      class convertible {
       public:
        /**
         * Implicit conversion to any type
         * @return converted type
         */
        template <class T> operator T() const;
    
        /**
         * Verifies whether a field was set
         *
         * @return true if field is available, false otherwise
         */
        bool available() const;
      };
    
      class table {
       public:
         /**
          * Multiline data text
          */
         std::string text{};
      };
    
      /**
       * Table parameters from the scenario
       */
      using Table = table<unordered_map<string, convertible>>;
      using Data = Table;
    } // testing
    
    class GSTEPS {
      /**
       * @param pattern step description (support simple regex)
       *        might be followed by _step to verify parameters at compile time
       * @param table optional table parameter, lambda expression will need a Table parameter
       *
       * Lambda expression has to be assigned
       */
      auto Given(auto pattern, auto table = none);
    
      /**
       * Same as Given but it will show file/line from cpp files instead of feature file
       */
      auto $Given(auto pattern, auto table = none);
    
      auto When(auto pattern, auto table = none);
      auto $When(auto pattern, auto table = none);
    
      auto Then(auto pattern, auto table = none);
      auto $Then(auto pattern, auto table = none);
    
      struct Info {
        std::string file{};
        std::string feature{};
        std::string scenario{};
        std::string step{};
      };
    
      /**
       * Returns information about currently being run scenario
       */
      auto& Info() const;
    }
  • Usage

/**
 * @param args default-constructible types to be injected
 */
GSTEPS("*") { // * - any feature
  Given("Step...") = [] { /* action */ };
   When("Step...") = [] { /* action */ };
   Then("Step...") = [] { /* action */ };
}
  • 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 Outline: Add two numbers
    Given I created a calculator with initial value equals 0
    And I have entered <input_1> into the calculator
    And I have entered <input_2> into the calculator
    When I press <button>
    Then the result should be <output> on the screen

  Examples:
    | input_1 | input_2 | button | output |
    | 20      | 30      | add    | 50     |
    | 2       | 5       | add    | 7      |
    | 0       | 40      | add    | 40     |
    | 3       | 222     | add    | 225    |

Steps Implementation

GSTEPS("Calc*") {
  using namespace testing;
  double result{};

  Given("I created a calculator with initial value equals {n}"_step) =
    [&](double n) {
      Calculator calc{n};

      Given("I have entered {n} into the calculator") =
        [&](double n) {
          calc.push(n);
        };

      When("I press add") =
        [&] {
          result = calc.add();
        };

      When("I press divide") =
        [&] {
          result = calc.divide();
        };

      Then("the result should be {expected} on the screen") =
        [&](double expected) {
          EXPECT_EQ(expected, result);
        };
    };
}

Usage

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

GWT and Mocking?

GSTEPS("Calc*") {
  using namespace ::testing;
  testing::GMock<IDisplay> display{DEFER_CALLS(IDisplay, show)};
  CalculatorUI calc{testing::object(display)};

  Given("I created a calculator with initial value equals {n}"_step) =
    [&](double) { /*ignore*/ };

  Given("I have entered {n} into the calculator") =
    [&](double n) {
      calc.push(n);
    };

  When("I press add") =
    [&]{ calc.add(); };

  Given("I press divide") =
    [&]{ calc.divide(); };

  Then("the result should be {expected} on the screen") =
    [&] (double expected) {
      EXPECT_CALL(display, (show)(expected));
    };
}

Note Running specific scenario requires ':' in the test filter (--gtest_filter="feature.scenario")

  • --gtest_filter="Calc Addition.Add two numbers" # calls Calc features test using Addition feature and Add two numbers scenario

  • More examples