GTest

[GTest] (2) Example

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

 

Below is a more advanced example of two classes, Car and OilBank, that interact with each other. The idea is:

  • Car has an internal oil level that can be increased by “refueling” from an OilBank.
  • OilBank has a total available capacity of oil and can provide oil to a Car upon request.

You’ll find:

  1. Car.h / Car.cpp
  2. OilBank.h / OilBank.cpp
  3. A sample GTest file (e.g., CarAndOilBankTest.cpp) to test their interaction.

Feel free to adjust the logic to suit your needs!

 

1. Car.h

#ifndef CAR_H
#define CAR_H

#include <string>
#include "OilBank.h"

class Car {
private:
    std::string make;
    std::string model;
    int year;
    double speed;
    double oilLevel;      // How many liters of oil are currently in the car
    double maxOilLevel;   // Maximum oil capacity

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

    // Basic getters
    std::string getMake() const;
    std::string getModel() const;
    int getYear() const;
    double getSpeed() const;
    double getOilLevel() const;
    double getMaxOilLevel() const;

    // Actions
    void accelerate(double amount);   // Increase speed, consumes some oil
    void brake(double amount);        // Decrease speed
    bool refuel(OilBank& oilBank, double amount); // Request oil from OilBank
};

#endif // CAR_H

 

 

2. Car.cpp

#include "Car.h"
#include <algorithm>  // for std::max, std::min

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

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;
}

double Car::getOilLevel() const {
    return oilLevel;
}

double Car::getMaxOilLevel() const {
    return maxOilLevel;
}

void Car::accelerate(double amount) {
    if (amount > 0 && oilLevel > 0) {
        speed += amount;

        // Consumes oil based on how much you accelerate, e.g. 1 liter per 10 units speed
        double oilUsed = amount * 0.1;
        oilLevel -= oilUsed;
        if (oilLevel < 0) {
            oilLevel = 0;
        }
    }
}

void Car::brake(double amount) {
    if (amount > 0) {
        speed -= amount;
        if (speed < 0) {
            speed = 0;
        }
    }
}

bool Car::refuel(OilBank& oilBank, double amount) {
    if (amount <= 0) {
        return false;
    }
    
    // Amount of oil needed to fill the tank up to max
    double needed = maxOilLevel - oilLevel;
    if (needed <= 0) {
        // Already at or above max capacity (though we usually don’t let oilLevel exceed max)
        return false;
    }

    // Only request as much as we can actually fit in the car
    double request = (amount > needed) ? needed : amount;

    // Request oil from the bank
    double provided = oilBank.provideOil(request);

    // Increase car’s oilLevel by whatever was provided
    oilLevel += provided;
    return (provided > 0);
}

 

 

 

 

3. OliBank.h

#ifndef OILBANK_H
#define OILBANK_H

#include <string>

class OilBank {
private:
    std::string name;
    double capacity; // Total liters of oil available

public:
    // Constructor
    OilBank(const std::string& name, double capacity);

    // Getters
    std::string getName() const;
    double getCapacity() const;

    // Provide oil to a Car
    // Returns the actual amount of oil provided.
    double provideOil(double requestedAmount);
};

#endif // OILBANK_H

 

 

 

4. OliBank.cpp

#include "OilBank.h"
#include <algorithm> // for std::min

OilBank::OilBank(const std::string& name, double capacity)
    : name(name), capacity(capacity) {
}

std::string OilBank::getName() const {
    return name;
}

double OilBank::getCapacity() const {
    return capacity;
}

double OilBank::provideOil(double requestedAmount) {
    if (requestedAmount <= 0) {
        return 0.0;
    }

    // The actual amount we can provide is limited by our current capacity
    double provided = std::min(capacity, requestedAmount);

    // Deduct from capacity
    capacity -= provided;
    return provided;
}

 

 

 

5. CarAndOilBankTest.cpp (GTest)

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

// 1. Test the OilBank alone
TEST(OilBankTest, ConstructionAndProvideOil) {
    OilBank bank("Global Oil", 100.0);

    EXPECT_EQ(bank.getName(), "Global Oil");
    EXPECT_DOUBLE_EQ(bank.getCapacity(), 100.0);

    // Request 50 liters
    double provided = bank.provideOil(50.0);
    EXPECT_DOUBLE_EQ(provided, 50.0);
    EXPECT_DOUBLE_EQ(bank.getCapacity(), 50.0);

    // Request more than remaining
    provided = bank.provideOil(60.0);
    EXPECT_DOUBLE_EQ(provided, 50.0);  // only 50 left
    EXPECT_DOUBLE_EQ(bank.getCapacity(), 0.0);

    // Bank is now empty
    provided = bank.provideOil(10.0);
    EXPECT_DOUBLE_EQ(provided, 0.0);
    EXPECT_DOUBLE_EQ(bank.getCapacity(), 0.0);
}

// 2. Test Car's basic features
TEST(CarTest, BasicProperties) {
    Car car("Toyota", "Camry", 2022, 60.0);

    EXPECT_EQ(car.getMake(), "Toyota");
    EXPECT_EQ(car.getModel(), "Camry");
    EXPECT_EQ(car.getYear(), 2022);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 0.0);
    EXPECT_DOUBLE_EQ(car.getOilLevel(), 0.0);
    EXPECT_DOUBLE_EQ(car.getMaxOilLevel(), 60.0);
}

TEST(CarTest, AccelerateAndBrake) {
    Car car("Honda", "Civic", 2023, 50.0);

    // No oil => accelerate should not increase speed
    car.accelerate(10.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 0.0);
    EXPECT_DOUBLE_EQ(car.getOilLevel(), 0.0);

    // Let's manually set some oil (for demonstration or we can refuel from an OilBank)
    // For real usage, you'd want to test refuel logic. Here we do a shortcut:
    // Typically you'd keep oil private, so consider adding a 'fillOilForTest' if you want
    // to manipulate it in tests. But let's do the official approach: create an OilBank and refuel.
}

// 3. Test Car refueling from OilBank
TEST(CarAndOilBankInteractionTest, Refuel) {
    Car car("BMW", "i8", 2021, 40.0);
    OilBank bank("Premium Oil", 100.0);

    // Initially, car has 0 oil
    EXPECT_DOUBLE_EQ(car.getOilLevel(), 0.0);

    // Refuel 20 liters
    bool success = car.refuel(bank, 20.0);
    EXPECT_TRUE(success);
    EXPECT_DOUBLE_EQ(car.getOilLevel(), 20.0);
    EXPECT_DOUBLE_EQ(bank.getCapacity(), 80.0); // 100 - 20

    // Try refueling another 30 liters (car only needs 20 more to max at 40)
    success = car.refuel(bank, 30.0);
    EXPECT_TRUE(success);
    // Car's max is 40, so it should now be at 40
    EXPECT_DOUBLE_EQ(car.getOilLevel(), 40.0);
    // The bank provided only 20 (not 30) because the car needed 20
    EXPECT_DOUBLE_EQ(bank.getCapacity(), 60.0);

    // Car is at max oil; requesting more should fail or do nothing
    success = car.refuel(bank, 10.0);
    EXPECT_FALSE(success);
    EXPECT_DOUBLE_EQ(car.getOilLevel(), 40.0);
    EXPECT_DOUBLE_EQ(bank.getCapacity(), 60.0);
}

// 4. Test that accelerating consumes oil
TEST(CarAndOilBankInteractionTest, AccelerateConsumesOil) {
    Car car("Tesla", "Model S", 2024, 50.0);
    OilBank bank("ElectricOil?", 20.0);

    // Refuel 15 liters
    car.refuel(bank, 15.0);
    EXPECT_DOUBLE_EQ(car.getOilLevel(), 15.0);
    EXPECT_DOUBLE_EQ(bank.getCapacity(), 5.0);

    // Accelerate by 10 => speed goes to 10 if there's enough oil
    car.accelerate(10.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 10.0);
    // Consumes 1 liter (10 * 0.1 = 1)
    EXPECT_DOUBLE_EQ(car.getOilLevel(), 14.0);

    // Accelerate by 140 => tries to use 14 liters of oil
    car.accelerate(140.0);
    // Car had 14 liters left => enough to accelerate fully
    // speed => 10 + 140 = 150
    // oil => 14 - (140 * 0.1) = 0
    EXPECT_DOUBLE_EQ(car.getSpeed(), 150.0);
    EXPECT_DOUBLE_EQ(car.getOilLevel(), 0.0);

    // No oil => further acceleration does nothing
    car.accelerate(50.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 150.0);
    EXPECT_DOUBLE_EQ(car.getOilLevel(), 0.0);
}

// 5. Test that braking never goes below 0
TEST(CarTest, BrakeNeverNegative) {
    Car car("Test", "Braker", 2020, 10.0);

    // Force a non-zero speed (ignore oil for now, or imagine we did have some oil)
    // In real tests, you'd want to handle it properly, but let's pretend:
    car.accelerate(10.0);  
    // This won't actually accelerate if there's no oil, so let's do one more trick:
    OilBank dummyBank("Dummy", 100.0);
    car.refuel(dummyBank, 10.0);
    car.accelerate(10.0);

    EXPECT_GT(car.getSpeed(), 0.0);

    // Now test braking
    car.brake(5.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 5.0);

    // Over-brake => speed goes to 0, not negative
    car.brake(999.0);
    EXPECT_DOUBLE_EQ(car.getSpeed(), 0.0);
}
반응형