Google Tests

This commit is contained in:
cdemeyer-teachx
2025-08-14 10:19:03 +09:00
parent e2cb19b92f
commit 1c1e7f8d51
19 changed files with 500 additions and 2 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Pokemon Battle Engine
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,14 @@
@PACKAGE_INIT@
# Pokemon Battle Simulator CMake Configuration
set(PokemonSim_VERSION "@PROJECT_VERSION@")
# Set up import targets
include("${CMAKE_CURRENT_LIST_DIR}/PokemonSimTargets.cmake")
# Set up variables for consumers
set(PokemonSim_LIBRARIES PokemonSim::pokemon_battle_sim)
set(PokemonSim_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
# Check required components
check_required_components(PokemonSim)

View File

@@ -0,0 +1,22 @@
# Compiler warnings configuration
function(set_project_warnings)
option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" ON)
if(MSVC)
add_compile_options(
/W4
/permissive-
$<$<BOOL:${WARNINGS_AS_ERRORS}>:/WX>
)
else()
add_compile_options(
-Wall
-Wextra
-Wpedantic
-Wshadow
-Wconversion
-Wsign-conversion
$<$<BOOL:${WARNINGS_AS_ERRORS}>:-Werror>
)
endif()
endfunction()

View File

@@ -0,0 +1,20 @@
# Static analysis tools configuration
function(enable_static_analysis)
# Find clang-tidy
find_program(CLANG_TIDY_EXE NAMES clang-tidy)
if(CLANG_TIDY_EXE)
set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_EXE} PARENT_SCOPE)
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
else()
message(STATUS "clang-tidy not found")
endif()
# Find cppcheck
find_program(CPPCHECK_EXE NAMES cppcheck)
if(CPPCHECK_EXE)
set(CMAKE_CXX_CPPCHECK ${CPPCHECK_EXE} PARENT_SCOPE)
message(STATUS "cppcheck found: ${CPPCHECK_EXE}")
else()
message(STATUS "cppcheck not found")
endif()
endfunction()

View File

@@ -0,0 +1,5 @@
# DEB packaging configuration
set(CPACK_DEB_COMPONENT_INSTALL ON)
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Pokemon Sim Team")
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")

View File

@@ -0,0 +1,4 @@
# RPM packaging configuration
set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_RPM_PACKAGE_GROUP "Games")
set(CPACK_RPM_PACKAGE_LICENSE "MIT")

26
examples/CMakeLists.txt Normal file
View File

@@ -0,0 +1,26 @@
# Examples CMakeLists.txt
# Collect all example source files
file(GLOB_RECURSE EXAMPLE_SOURCES "*.cpp" "*.cc" "*.cxx")
# Create example executables
foreach(EXAMPLE_SOURCE ${EXAMPLE_SOURCES})
get_filename_component(EXAMPLE_NAME ${EXAMPLE_SOURCE} NAME_WE)
add_executable(${EXAMPLE_NAME} ${EXAMPLE_SOURCE})
# Link with our library
target_link_libraries(${EXAMPLE_NAME}
PRIVATE
PokemonSim::pokemon_battle_sim
)
# Include directories
target_include_directories(${EXAMPLE_NAME}
PRIVATE
${CMAKE_SOURCE_DIR}/include
)
endforeach()
# Example of adding examples manually:
# add_executable(battle_example battle_example.cpp)
# target_link_libraries(battle_example PRIVATE PokemonSim::pokemon_battle_sim)

View File

@@ -0,0 +1,37 @@
// Pokemon Battle Engine Header
// This is a placeholder header for the Pokemon Battle Engine library
#ifndef POKEMON_BATTLE_SIM_H
#define POKEMON_BATTLE_SIM_H
#include <string>
namespace PokemonSim {
// Forward declarations
class Pokemon;
// Pokemon class
class Pokemon {
public:
Pokemon(const std::string& name, int health = 100);
~Pokemon() = default;
// Getters
std::string getName() const;
int getHealth() const;
// Setters
void setHealth(int health);
private:
std::string name_;
int health_;
};
// Battle simulation function
bool simulateBattle(Pokemon& pokemon1, Pokemon& pokemon2);
} // namespace PokemonSim
#endif // POKEMON_BATTLE_SIM_H

41
src/CMakeLists.txt Normal file
View File

@@ -0,0 +1,41 @@
# Source files CMakeLists.txt
# Collect all source files
file(GLOB_RECURSE SOURCES "*.cpp" "*.cc" "*.cxx")
file(GLOB_RECURSE HEADERS "*.h" "*.hpp" "*.hxx")
# Create the main library
add_library(pokemon_battle_sim ${SOURCES} ${HEADERS})
# Set library properties
set_target_properties(pokemon_battle_sim PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
)
# Include directories
target_include_directories(pokemon_battle_sim
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# Link dependencies
target_link_libraries(pokemon_battle_sim
PRIVATE
Threads::Threads
)
# Create an alias for consistency
add_library(PokemonSim::pokemon_battle_sim ALIAS pokemon_battle_sim)
# Export the target
install(TARGETS pokemon_battle_sim
EXPORT PokemonSimTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

44
src/placeholder.cpp Normal file
View File

@@ -0,0 +1,44 @@
// Placeholder source file for Pokemon Battle Engine
// This file is temporary and will be replaced with actual implementation
#include "pokemon_battle_sim.h"
#include <string>
#include <iostream>
namespace PokemonSim {
// Pokemon class method implementations
Pokemon::Pokemon(const std::string& name, int health)
: name_(name), health_(health) {}
std::string Pokemon::getName() const {
return name_;
}
int Pokemon::getHealth() const {
return health_;
}
void Pokemon::setHealth(int health) {
health_ = health;
}
// Placeholder battle function
bool simulateBattle(Pokemon& pokemon1, Pokemon& pokemon2) {
// Simple battle simulation for testing
while (pokemon1.getHealth() > 0 && pokemon2.getHealth() > 0) {
// Pokemon 1 attacks Pokemon 2
int damage = 10; // Fixed damage for now
pokemon2.setHealth(pokemon2.getHealth() - damage);
if (pokemon2.getHealth() <= 0) {
return true; // Pokemon 1 wins
}
// Pokemon 2 attacks Pokemon 1
pokemon1.setHealth(pokemon1.getHealth() - damage);
}
return false; // Pokemon 2 wins or tie
}
} // namespace PokemonSim

8
test_all.sh Executable file
View File

@@ -0,0 +1,8 @@
# Configure the project
cmake -B build -S .
# Build the project (includes tests)
cmake --build build
# Run all tests
cmake --build build --target test

75
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,75 @@
# Tests CMakeLists.txt
include(FetchContent)
# Download and configure Google Test
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/v1.14.0.zip
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)
# Prevent overriding the parent project's compiler/linker on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Make Google Test available
FetchContent_MakeAvailable(googletest)
# Include Google Test modules
include(GoogleTest)
# Create test executable for unit tests
add_executable(unit_tests
unit/main.cpp
)
# Link with Google Test and our library
target_link_libraries(unit_tests
PRIVATE
GTest::gtest_main
GTest::gmock_main
PokemonSim::pokemon_battle_sim
)
# Set up test discovery
gtest_discover_tests(unit_tests
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
PROPERTIES
LABELS "unit"
)
# Create test executable for integration tests
add_executable(integration_tests
integration/main.cpp
)
# Link with Google Test and our library
target_link_libraries(integration_tests
PRIVATE
GTest::gtest_main
GTest::gmock_main
PokemonSim::pokemon_battle_sim
)
# Set up test discovery
gtest_discover_tests(integration_tests
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
PROPERTIES
LABELS "integration"
)
# Include directories for tests
target_include_directories(unit_tests
PRIVATE
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/src
)
target_include_directories(integration_tests
PRIVATE
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/src
)
# Add test subdirectories
add_subdirectory(unit)
add_subdirectory(integration)

View File

@@ -38,10 +38,49 @@ tests/
## Testing Framework
- **Google Test (gtest)**: Primary testing framework
- **Google Mock (gmock)**: For mocking dependencies
- **Google Test (gtest)**: Primary testing framework - automatically downloaded via FetchContent
- **Google Mock (gmock)**: For mocking dependencies - included with Google Test
- **Test Coverage**: Aim for >90% code coverage
- **Continuous Integration**: Tests run on every commit
- **Version**: Google Test v1.14.0
## Running Tests
### Build and Run
```bash
# Configure and build
cmake -B build -S .
cmake --build build
# Run all tests
cmake --build build --target test
# Run specific test types
cd build && ctest -L unit # Unit tests only
cd build && ctest -L integration # Integration tests only
# Run with verbose output
cd build && ctest -V
```
### Test Structure (Now Implemented)
```
tests/
├── unit/ # Unit tests for individual components
│ ├── main.cpp # Unit test entry point
│ ├── CMakeLists.txt # Unit test build config
│ └── core/ # Core system tests
│ ├── CMakeLists.txt
│ └── test_example.cpp # Example test (ready to run)
├── integration/ # Integration tests
│ ├── main.cpp # Integration test entry point
│ └── CMakeLists.txt # Integration test build config
├── fixtures/ # Test data and fixtures
├── helpers/ # Test helper utilities
└── CMakeLists.txt # Main test build configuration
```
## Test Categories

View File

@@ -0,0 +1,18 @@
# Integration tests CMakeLists.txt
# Collect all test source files
file(GLOB_RECURSE INTEGRATION_TEST_SOURCES "*.cpp" "*.cc" "*.cxx")
# Remove main.cpp from the sources list if it exists
list(REMOVE_ITEM INTEGRATION_TEST_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp")
# Add integration test sources to the integration_tests executable
if(INTEGRATION_TEST_SOURCES)
target_sources(integration_tests PRIVATE ${INTEGRATION_TEST_SOURCES})
endif()
# Example of how to add specific test files:
# target_sources(integration_tests PRIVATE
# test_battle_integration.cpp
# test_full_game_flow.cpp
# )

View File

@@ -0,0 +1,11 @@
#include <gtest/gtest.h>
// Main test runner for integration tests
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
// Set up any global test configuration here
// Integration tests might need different setup than unit tests
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,9 @@
# Unit tests CMakeLists.txt
# Add unit test subdirectories
add_subdirectory(core)
# You can add more unit test subdirectories here as needed:
# add_subdirectory(math)
# add_subdirectory(utils)
# add_subdirectory(battle)

View File

@@ -0,0 +1,18 @@
# Core unit tests CMakeLists.txt
# Collect all test source files
file(GLOB_RECURSE CORE_TEST_SOURCES "*.cpp" "*.cc" "*.cxx")
# Remove main.cpp from the sources list if it exists
list(REMOVE_ITEM CORE_TEST_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp")
# Add core test sources to the unit_tests executable
if(CORE_TEST_SOURCES)
target_sources(unit_tests PRIVATE ${CORE_TEST_SOURCES})
endif()
# Example of how to add specific test files:
# target_sources(unit_tests PRIVATE
# test_example.cpp
# test_another_example.cpp
# )

View File

@@ -0,0 +1,75 @@
#include <gtest/gtest.h>
// Example test case demonstrating Google Test usage
class ExampleTest : public ::testing::Test {
protected:
void SetUp() override {
// Set up test fixtures here
}
void TearDown() override {
// Clean up test fixtures here
}
};
// Basic assertion test
TEST_F(ExampleTest, BasicAssertions) {
// Basic equality assertions
EXPECT_EQ(2 + 2, 4);
EXPECT_NE(2 + 2, 5);
// Boolean assertions
EXPECT_TRUE(true);
EXPECT_FALSE(false);
// String assertions
EXPECT_STREQ("hello", "hello");
EXPECT_STRNE("hello", "world");
}
// Test with parameters
TEST(ParameterizedTest, Addition) {
EXPECT_EQ(1 + 1, 2);
EXPECT_EQ(10 + 5, 15);
EXPECT_EQ(-1 + 1, 0);
}
// Test that demonstrates failure (using TEST_F to match the fixture)
TEST_F(ExampleTest, ThisWillFail) {
// This test will fail to demonstrate the failure output
// EXPECT_EQ(2 + 2, 5); // Uncomment this line to see a failing test
}
// Example of how you might test a Pokemon battle simulator component
// This demonstrates testing the placeholder implementation we created
#include "pokemon_battle_sim.h"
TEST(PokemonTest, PokemonCreation) {
PokemonSim::Pokemon pikachu("Pikachu", 100);
// Test basic properties
EXPECT_EQ(pikachu.getName(), "Pikachu");
EXPECT_EQ(pikachu.getHealth(), 100);
}
TEST(PokemonTest, PokemonHealthModification) {
PokemonSim::Pokemon charizard("Charizard", 150);
EXPECT_EQ(charizard.getHealth(), 150);
charizard.setHealth(100);
EXPECT_EQ(charizard.getHealth(), 100);
}
TEST(PokemonTest, BattleSimulation) {
PokemonSim::Pokemon pokemon1("Pokemon1", 50);
PokemonSim::Pokemon pokemon2("Pokemon2", 30);
// Pokemon1 should win because it has more health
bool result = PokemonSim::simulateBattle(pokemon1, pokemon2);
EXPECT_TRUE(result); // Pokemon1 wins
// Both Pokemon should have taken damage
EXPECT_LT(pokemon1.getHealth(), 50);
EXPECT_LE(pokemon2.getHealth(), 0);
}

11
tests/unit/main.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include <gtest/gtest.h>
// Main test runner for unit tests
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
// Set up any global test configuration here
// For example, you can set test filters, output format, etc.
return RUN_ALL_TESTS();
}