[GTest] (1) Example
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)