From b9198d906a779a024eea2e99d35564b9ecd76a02 Mon Sep 17 00:00:00 2001 From: Guillaume Le Pape Date: Sat, 30 Dec 2023 19:31:48 +0100 Subject: [PATCH] Put in place proper mocking for tests --- .github/workflows/cmake-multi-platform.yml | 21 +++++++++++----- .../include/elevation/action/action_writer.h | 4 ++-- .../include/elevation/action/add_weapon.h | 13 ++++++---- src/action/include/elevation/action/dead.h | 11 +++++---- .../include/elevation/action/use_weapon.h | 13 +++++----- src/utils/include/elevation/utils/pause.h | 4 +++- src/utils/src/pause.cpp | 5 ++-- test/weapon_test.cpp | 24 +++++++++++++++---- 8 files changed, 62 insertions(+), 33 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index bc57a7d..e7d45a9 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -22,7 +22,7 @@ jobs: # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. matrix: os: [ubuntu-latest, windows-latest] - build_type: [Release] + build_type: [Release, Debug] c_compiler: [gcc, clang, cl] include: - os: ubuntu-latest @@ -46,6 +46,8 @@ jobs: fetch-depth: 0 submodules: true + - run: cmake --version + - name: Set reusable strings # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. id: strings @@ -65,14 +67,21 @@ jobs: -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake + -DCMAKE_CXX_FLAGS_DEBUG="-g -fprofile-arcs -ftest-coverage" + -DCMAKE_C_FLAGS_DEBUG="-g -fprofile-arcs -ftest-coverage" -S ${{ github.workspace }} - name: Build # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} - # - name: Test - # working-directory: ${{ steps.strings.outputs.build-output-dir }} - # # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). - # # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - # run: ctest --build-config ${{ matrix.build_type }} + - name: Test + working-directory: ${{ steps.strings.outputs.build-output-dir }} + # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest --build-config ${{ matrix.build_type }} -T Test -T Coverage + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + with: + fail_ci_if_error: true diff --git a/src/action/include/elevation/action/action_writer.h b/src/action/include/elevation/action/action_writer.h index 8bc3656..8f951b5 100644 --- a/src/action/include/elevation/action/action_writer.h +++ b/src/action/include/elevation/action/action_writer.h @@ -21,8 +21,8 @@ void write(T&& statement) { namespace result { template -void write(T&& result) { - utils::pause(); +void write(T&& result, std::istream& in = std::cin) { + utils::pause(in); fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "\n {}", result); } } // namespace result diff --git a/src/action/include/elevation/action/add_weapon.h b/src/action/include/elevation/action/add_weapon.h index f931d38..ef67571 100644 --- a/src/action/include/elevation/action/add_weapon.h +++ b/src/action/include/elevation/action/add_weapon.h @@ -12,12 +12,14 @@ class AddWeapon { std::string result_; entity::Player& player_; weapon::Weapon weapon_; + std::istream& in_; public: - AddWeapon(entity::Player& player, weapon::Weapon&& weapon) + AddWeapon(entity::Player& player, weapon::Weapon&& weapon, std::istream& in) : result_{data::action::resultAddWeapon(weapon.name)}, player_{player}, - weapon_{std::move(weapon)} {} + weapon_{std::move(weapon)}, + in_{in} {} void trigger() { if (weapon_.type != weapon::Type::noWeapon) { @@ -26,15 +28,16 @@ class AddWeapon { player_.weapons().insert(std::move(weapon_)); if (not_in_player_weapons) { - result::write(result_); + result::write(result_, in_); } } } }; namespace add_weapon { -void trigger(entity::Player& player, weapon::Weapon&& weapon) { - AddWeapon add_weapon{player, std::forward(weapon)}; +void trigger(entity::Player& player, weapon::Weapon&& weapon, + std::istream& in = std::cin) { + AddWeapon add_weapon{player, std::forward(weapon), in}; add_weapon.trigger(); } } // namespace add_weapon diff --git a/src/action/include/elevation/action/dead.h b/src/action/include/elevation/action/dead.h index 645e9b7..ed16a4f 100644 --- a/src/action/include/elevation/action/dead.h +++ b/src/action/include/elevation/action/dead.h @@ -9,22 +9,23 @@ class Dead { private: U result_; const entity::Plug& plug_; + std::istream& in_; public: - Dead(const entity::Plug& plug, const U& result) - : result_{result}, plug_{plug} {} + Dead(const entity::Plug& plug, const U& result, std::istream& in) + : result_{result}, plug_{plug}, in_{in} {} void trigger() { if (plug_.healthBar().dead()) { - result::write(result_); + result::write(result_, in_); } } }; namespace dead { template -void trigger(const entity::Plug& plug, const U& result) { - Dead dead{plug, result}; +void trigger(const entity::Plug& plug, const U& result, std::istream& in) { + Dead dead{plug, result, in}; dead.trigger(); } } // namespace dead diff --git a/src/action/include/elevation/action/use_weapon.h b/src/action/include/elevation/action/use_weapon.h index 735cfd2..1de8095 100644 --- a/src/action/include/elevation/action/use_weapon.h +++ b/src/action/include/elevation/action/use_weapon.h @@ -14,11 +14,12 @@ class UseWeapon { entity::Player& player_; entity::Plug& plug_; const std::string& nameWeapon_; + std::istream& in_; public: UseWeapon(entity::Player& player, entity::Plug& plug, - const std::string& nameWeapon) - : player_{player}, plug_{plug}, nameWeapon_{nameWeapon} {} + const std::string& nameWeapon, std::istream& in = std::cin) + : player_{player}, plug_{plug}, nameWeapon_{nameWeapon}, in_{in} {} void trigger() { auto weapon = ranges::find_if(player_.weapons(), [&](const auto& weapon) { @@ -30,9 +31,9 @@ class UseWeapon { auto result = data::weapon::resultUseWeapon(plug_.name(), weapon->nb_damage); - result::write(result); + result::write(result, in_); - action::dead::trigger(plug_, data::action::resultDead(plug_.name())); + action::dead::trigger(plug_, data::action::resultDead(plug_.name()), in_); // if weapon is fireArm and has no ammo, delete it if (weapon->type == weapon::Type::fireArm and weapon->durability <= 0) { @@ -67,8 +68,8 @@ class UseWeapon { namespace use_weapon { void trigger(entity::Player& player, entity::Plug& plug, - const std::string& nameWeapon) { - UseWeapon use_weapon{player, plug, nameWeapon}; + const std::string& nameWeapon, std::istream& in = std::cin) { + UseWeapon use_weapon{player, plug, nameWeapon, in}; use_weapon.trigger(); } } // namespace use_weapon diff --git a/src/utils/include/elevation/utils/pause.h b/src/utils/include/elevation/utils/pause.h index bb1d013..c9ec8bb 100644 --- a/src/utils/include/elevation/utils/pause.h +++ b/src/utils/include/elevation/utils/pause.h @@ -1,5 +1,7 @@ #pragma once +#include + namespace elevation::utils { -void pause(); +void pause(std::istream& in = std::cin); } diff --git a/src/utils/src/pause.cpp b/src/utils/src/pause.cpp index f0fee04..3853c62 100644 --- a/src/utils/src/pause.cpp +++ b/src/utils/src/pause.cpp @@ -1,14 +1,13 @@ #include "elevation/utils/pause.h" #include -#include namespace elevation::utils { std::atomic_bool keep_running{true}; -void pause() { +void pause(std::istream& in) { while (keep_running) { - if (std::cin.get() == 10) { + if (in.get() == 10) { keep_running = false; } } diff --git a/test/weapon_test.cpp b/test/weapon_test.cpp index 6b13309..399eaef 100644 --- a/test/weapon_test.cpp +++ b/test/weapon_test.cpp @@ -1,8 +1,10 @@ #include "elevation/weapon/weapon.h" +#include #include #include +#include #include #include @@ -12,13 +14,19 @@ #include "elevation/entity/player.h" #include "elevation/entity/plug.h" +using ::testing::MockFunction; +using ::testing::Return; + namespace elevation { TEST(weapon_test, UseWeapon) { entity::Player player("Guillaume", 0); - action::add_weapon::trigger(player, weapon::Fist()); + std::istringstream s1{"\u000A\u000A"}; + std::istream s2{s1.rdbuf()}; + + action::add_weapon::trigger(player, weapon::Fist(), s2); - action::add_weapon::trigger(player, weapon::AK47(100)); + action::add_weapon::trigger(player, weapon::AK47(100), s2); EXPECT_EQ(player.pseudo(), "Guillaume"); @@ -35,7 +43,10 @@ TEST(weapon_test, UseWeapon) { TEST(weapon_test, Fist) { entity::Player player("Guillaume", 0, weapon::WeaponInventory{}); - action::add_weapon::trigger(player, weapon::Fist()); + std::istringstream s1{"\u000A"}; + std::istream s2{s1.rdbuf()}; + + action::add_weapon::trigger(player, weapon::Fist(), s2); const auto& fist = *(std::cbegin(player.weapons())); @@ -48,7 +59,10 @@ TEST(weapon_test, Fist) { TEST(weapon_test, AK47) { entity::Player player("Guillaume", 0, weapon::WeaponInventory{}); - action::add_weapon::trigger(player, weapon::AK47(40)); + std::istringstream s1{"\u000A\u000A\u000A"}; + std::istream s2{s1.rdbuf()}; + + action::add_weapon::trigger(player, weapon::AK47(40), s2); const auto& ak47 = *std::find_if( std::cbegin(player.weapons()), std::cend(player.weapons()), @@ -62,7 +76,7 @@ TEST(weapon_test, AK47) { entity::Plug plug("Jean-Michel", 100); - action::use_weapon::trigger(player, plug, data::weapon::nameAK47); + action::use_weapon::trigger(player, plug, data::weapon::nameAK47, s2); EXPECT_EQ(ak47.nb_damage, 150); EXPECT_EQ(ak47.type, weapon::Type::fireArm);