GTest

[GTest] (1) Example

i5 2025. 1. 9. 01:51
반응형

 

 

1. Directory Structure

project/
├── src/
│   ├── Car.h
│   └── Car.cpp
├── test/
│   ├── CarTest.cpp
│   └── CMakeLists.txt (or some build script for tests)
├── CMakeLists.txt
└── ...

 

 

2. Source files

Car.h

#ifndef CAR_H
#define CAR_H

#include <string>

class Car {
private:
    std::string make;
    std::string model;
    int year;
    double speed;

public:
    // Constructor
    Car(const std::string& make, const std::string& model, int year);

    // Accessors (Getters)
    std::string getMake() const;
    std::string getModel() const;
    int getYear() const;
    double getSpeed() const;

    // Mutators (Setters/Actions)
    void accelerate(double amount);
    void brake(double amount);
};

#endif // CAR_H

 

Car.cpp

#include "Car.h"

Car::Car(const std::string& make, const std::string& model, int year)
    : make(make), model(model), year(year), speed(0.0) {
}

std::string Car::getMake() const {
    return make;
}

std::string Car::getModel() const {
    return model;
}

int Car::getYear() const {
    return year;
}

double Car::getSpeed() const {
    return speed;
}

void Car::accelerate(double amount) {
    // Only accelerate if amount is positive
    if (amount > 0) {
        speed += amount;
    }
}

void Car::brake(double amount) {
    // Only brake if amount is non-negative
    if (amount >= 0) {
        speed -= amount;
        // Make sure speed doesn't go below 0
        if (speed < 0) {
            speed = 0;
        }
    }
}

 

 

 

 

3. Test codes

Below is a sample test file (CarTest.cpp) that demonstrates how to test Car. It assumes that:

 

CarTest.cpp

#include <gtest/gtest.h>  // Google Test header
#include "Car.h"          // Your Car class header

// Simple test without a test fixture:
TEST(CarTest, ConstructorSetsValues) {
    Car car("Toyota", "Corolla", 2022);

    EXPECT_EQ(car.getMake(), "Toyota");
    EXPECT_EQ(car.getModel(), "Corolla");
    EXPECT_EQ(car.getYear(), 2022);

    // Speed should be initialized to 0
    EXPECT_DOUBLE_EQ(car.getSpeed(), 0.0);
}

// Another test to check accelerate behavior:
TEST(CarTest, AccelerateIncreasesSpeed) {
    Car car("Honda", "Civic", 2023);

    // Start speed
    EXPECT_DOUBLE_EQ(car.getSpeed(), 0.0);

    // Accelerate by 10
    car.accelerate(10.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 10.0);

    // Accelerate by 5 more
    car.accelerate(5.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 15.0);
}

// Another test to check brake behavior:
TEST(CarTest, BrakeDecreasesSpeedButNotBelowZero) {
    Car car("Ford", "Mustang", 2021);

    // Accelerate first so we have a non-zero speed
    car.accelerate(50.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 50.0);

    // Apply the brake
    car.brake(20.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 30.0);

    // Try braking more than the current speed
    car.brake(50.0);
    // Should not go below 0
    EXPECT_DOUBLE_EQ(car.getSpeed(), 0.0);
}

// Test zero or negative values for accelerate/brake
TEST(CarTest, AccelerateBrakeWithInvalidValues) {
    Car car("Tesla", "Model 3", 2022);

    // Speed starts at 0
    EXPECT_DOUBLE_EQ(car.getSpeed(), 0.0);

    // Negative accelerate value (should not change speed)
    car.accelerate(-10.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 0.0);

    // Negative brake value (should not change speed)
    car.brake(-5.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 0.0);
}

 

 

 

4. Test codes (Using Test Fixture)

If you need to set up common objects or data before each test (and clean up after), you can use a test fixture. For example:

#include <gtest/gtest.h>
#include "Car.h"

class CarTestFixture : public ::testing::Test {
protected:
    // This will be called *before* each TEST_F
    void SetUp() override {
        car = new Car("BMW", "i8", 2022);
    }

    // This will be called *after* each TEST_F
    void TearDown() override {
        delete car;
        car = nullptr;
    }

    Car* car;  // Pointer to Car that we can reuse
};

TEST_F(CarTestFixture, InitialValues) {
    EXPECT_EQ(car->getMake(), "BMW");
    EXPECT_EQ(car->getModel(), "i8");
    EXPECT_EQ(car->getYear(), 2022);
    EXPECT_DOUBLE_EQ(car->getSpeed(), 0.0);
}

TEST_F(CarTestFixture, AccelerateTest) {
    car->accelerate(15);
    EXPECT_DOUBLE_EQ(car->getSpeed(), 15.0);
}

 

 

 

Here, SetUp() runs before each test, so each test gets a fresh Car object. TearDown() runs after each test, ensuring no memory leaks if you’re dynamically allocating objects (as shown here). If you prefer, you can also store the Car as a member (not a pointer) and skip the manual allocation/deletion.

 

 

5. Building and Running Tests

CMake Example

Below is a simple CMakeLists.txt snippet in your test directory to build your test executable:

# test/CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(CarTestProject)

# Assuming Google Test is installed
find_package(GTest REQUIRED)

include_directories(${GTEST_INCLUDE_DIRS})
include_directories(../src)  # So we can include Car.h

# Gather test source files
set(TEST_SOURCES
    CarTest.cpp
)

# Create test executable
add_executable(CarTests ${TEST_SOURCES})

# Link with GTest and pthread (if on Linux)
target_link_libraries(CarTests ${GTEST_LIBRARIES} pthread)

# Optionally register a test with CTest
enable_testing()
add_test(NAME CarTests COMMAND CarTests)

 

 

 

 

Important: In a real project, you’d also have a top-level CMake that includes your src/ and test/ subdirectories.

To build and run:

 

cd project
mkdir build && cd build
cmake ..
make
ctest --verbose   # or ./CarTests

 

 

Modified

cmake_minumum_required(VERSION 3.12)

project(CarTestProject)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(GTest REQUIRED)

include_directories(${GTEST_INCLUDE_DIRS})

include_directories(../src)

add_executable(CarTests
    CarTest.cpp
    ../src/Car.cpp
)

target_link_libraries(CarTests
    GTest::gtest
    GTest::gtest_main
    pthread
)

#Optionally register a test with CTest
enable_testing()
add_test(NAME CarTests COMMAND CarTests)
반응형