Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This tutorial focuses on creating a simple C++ Calculator project using the divide() method function and testing it using the GoogleTest platform, and . This guide shows a complete way to do itthis, starting by writing tests for that function and then moving on to writing the source for the function. The principle of Test Driven Development (TDD) is to write the tests first, and then the function itself. As you write your source code, you should run tests from time to time to check that the code is correct.

Table of Contents
maxLevel3
exclude.*:

Create The Calculator project

...

project preparation:

To present an example of using GoogleTest, we first need to create a project in C++.  In the project directory named Calculator, we will create the C++ source and header files in the appropriate directories. For the tutorial, we create operations.cpp in the src directory, which contains a simple divide function and the operation.h header file. However, C++ is a statically typed language and therefore we need to supply multiple definitions of a division function according to the type of its input arguments. The output of a function should always be floating point, but for the purposes of this tutorial, we predict that the input arguments can be both integers and floating point numbers. Therefore, two definitions have been introduced for each of these types. The header file should look like this:

Code Block
languagecpp
titleoperations.h
linenumberstrue
#ifndef CALCULATOR_OPERATIONS_H
#define CALCULATOR_OPERATIONS_H

#include <stdexcept>

float divide(int numerator, int denominator);
float divide(float numerator, float denominator);

#endif //CALCULATOR_OPERATIONS_H

And the contents of the operation.cpp looks like this:

Code Block
languagecpp
titleoperations.cpp
linenumberstrue
#include "operations.h"

float divide(int numerator, int denominator){
    if(denominator == 0){
        throw std::overflow_error("Divide by zero exception!!! Verify the denominator value!");
    }
    return float(numerator) / float(denominator);
}

float divide(float numerator, float denominator){
    if(abs(denominator) <= 1e-5){
        throw std::overflow_error("Divide by zero exception!!! The denominator value close to zero!");
    }
    return numerator / denominator;
}

The presented function has a mechanism for verifying whether the divisor (denominator) is equal to zero or is close to zero in the case of a floating-point number. In case the condition evaluates to True, an exception is thrown. To implement the exception, include the <stdexcept> library. Under normal circumstances, the output value is computed and returned as floating point in both cases.

tests:

before starting to write codes, it is necessary to prepare its structure. It will need two subdirectories named src and tst - one for the source codes and one for the tests codes. At this point, these folders can be filled with empty files with appropriate names for sources: operation.cpp; operations.h, and for tests: run_tests.cpp; test_operations.cpp. However, each of these files can be created later during development.

tests:

To start writing tests, it is needed to We also need to create a folder for our tests. In this tutorial, this folder is called tst. To start writing tests, we will create run_tests.cpp and test_operations.cpp. We want (if not done previously). In order to force GoogleTest to automatically search for test files automatically, and we do this thanks to the code stored in thethe file run_tests.cpp source file. Typically, this code comes in handy. Typically, a code inside this file will be universal for all kinds of projects:

...

However, the actual test cases are placed in a separate file, the name of which corresponds to the name of the file that stores the code to be tested. It is good practice to name the test file using the name of the source file being tested with the keyword test appended as a prefix or suffix separated by the underscore "_" or the dash "-".  The The goal of this tutorial is to test the divide division function stored in the operations.cpp file. Therefore, although it does not exist at this point, it is predicted that it will be. Therefore, the file with the test code is named test_operations.cpp, and should look like this:

Code Block
languagecpp
titlerun_tests.cpp
linenumberstrue
#include <gtest/gtest.h>
#include "operations.h"

TEST(DivideOperation, PositiveInput) {
    // Integer arguments
    ASSERT_EQ(divide(10, 5), 2);
    ASSERT_FLOAT_EQ(divide(5, 10), 0.5);
    // Floating-point arguments
    ASSERT_FLOAT_EQ(divide(10.0f, 5.0f), 2.0f);
    ASSERT_FLOAT_EQ(divide(5.0f, 10.0f), 0.5f);
}

TEST(DivideOperation, NegitiveInput) {
    // Integer arguments
    ASSERT_EQ(divide(-10, -5), 2);
    ASSERT_FLOAT_EQ(divide(-5, -10), 0.5);
    // Floating-point arguments
    ASSERT_FLOAT_EQ(divide(-10.0f, -5.0f), 2.0f);
    ASSERT_FLOAT_EQ(divide(-5.0f, -10.0f), 0.5f);
}

TEST(DivideOperation, ZerioInput) {
    // Integer arguments
    EXPECT_THROW(divide(10, 0), std::overflow_error);
    // Floating-point arguments
    EXPECT_THROW(divide(10.0f, 0.0f), std::overflow_error);
}

sources:

, we will create the C++ source and header files in the appropriate directories. For the tutorial, we create operations.cpp in the src directory, which contains a simple divide function and the operation.h header file. However, C++ is a statically typed language and therefore we need to supply multiple definitions of a division function according to the type of its input arguments. The output of a function should always be floating point, but for the purposes of this tutorial, we predict that the input arguments can be both integers and floating point numbers. Therefore, two definitions have been introduced for each of these types. The header file should look like this:

Code Block
languagecpp
titleoperations.h
linenumberstrue
#ifndef CALCULATOR_OPERATIONS_H
#define CALCULATOR_OPERATIONS_H

#include <stdexcept>

float divide(int numerator, int denominator);
float divide(float numerator, float denominator);

#endif //CALCULATOR_OPERATIONS_H

And the contents of the operation.cpp looks like this:

Code Block
languagecpp
titleoperations.cpp
linenumberstrue
#include "operations.h"

float divide(int numerator, int denominator){
    if(denominator == 0){
        throw std::overflow_error("Divide by zero exception!!! Verify the denominator value!");
    }
    return float(numerator) / float(denominator);
}

float divide(float numerator, float denominator){
    if(abs(denominator) <= 1e-5){
        throw std::overflow_error("Divide by zero exception!!! The denominator value close to zero!");
    }
    return numerator / denominator;
}

The presented function has a mechanism for verifying whether the divisor (denominator) is equal to zero or is close to zero in the case of a floating-point number. In case the condition evaluates to True, an exception is thrown. To implement the exception, include the <stdexcept> library. Under normal circumstances, the output value is computed and returned as floating point in both cases.

Our project folder should look like this:

...