4

Unit testing means writing code that verifies individual parts, or units, of an application or library. A unit is the smallest testable part of an application. Unit tests assess code in isolation. In C++ this means writing tests for methods or functions. I am writing a basic calculator program and trying to use CPPUnitTest to test the code in Visual studio 2019.After that I have to build this in Jenkins too. Please don't judge .. I am writing unit Test for the 1st time .. this is my Calculator.cpp

#include <iostream>
#include "Calc.h"
using namespace std;

int main()
{
        Calc obj;
        float a, b;
        cin >> a >> b;
        int menu;
        cout << "Enter what operation you want(1-4);" << endl;
        cout << "1. Addition" << endl;
        cout << "2. Subtraction" << endl;
        cout << "3. Multiplication" << endl;
        cout << "4. Division" << endl;
        cin >> menu;
        switch (menu)
        {
        case 1:obj.add(a, b);
            break;
        case 2:obj.sub(a, b);
            break;
        case 3:obj.multiply(a, b);
            break;
        case 4:
            try
            {
                obj.divide(a, b);
            }
            catch (std::runtime_error& e)
            {
                cout << e.what() << "\n";
            }
            break;
        default:
        {
            cout << "Invalid input" << endl;
        }
    }
}

This is class Calc or "Calc.h" Here I have used std::runtime_error to throw error on division bye zero

#pragma once
#include <stdexcept>
class Calc {

public:
    float add(float a, float b)
    {
        return a + b;
    }
    float sub(float a, float b) {

        return  a - b;
    }

    float multiply(float a, float b) {
        return  a * b;
    }

    float divide(float a, float b) {
        if (b == 0)
        {
            throw std::runtime_error("Division by zero condition!");
        }
        return a / b;
    }

};

I am trying to write unit test using CPPUnitTest for my code. I have written code for add and subtract using assert::AreEqual but for divide by zero condition, I don't know to write the test case. this is my unit test code.

#include "pch.h"
#include "CppUnitTest.h"
#include "../Calculator/Calc.h"
#include <stdexcept>

using namespace std;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace CalculatorTest
{
    TEST_CLASS(CalculatorTest)
    {
    public:
        Calc cal;
        TEST_METHOD(AddTest)
        {
            float k = cal.add(3, 4);
            Assert::AreEqual(7.0f,k);
        }
        TEST_METHOD(SubTest)
        {
            float k = cal.sub(3, 4);
            Assert::AreNotEqual(-2.0f, k);
        }
        TEST_METHOD(DivByZeroTest)
        {
            //what should I write here
        }
    };
}

Please help me to write the test method for this . Somewhere I read CPPUNIT_ASSERT_THROW(cal->divide(12,0), std::runtime_error); but this is not working in my case. How can I make Assert::AreEqual Also suggest which else method I can use to increase my code coverage.

Frodyne
  • 3,547
  • 6
  • 16
  • you can use exception handing methods to catch divide by zero errors. – Manish Kumar Mar 03 '20 at 11:56
  • You'll need to use `__try` and `__except` for [SEH](https://learn.microsoft.com/en-us/cpp/cpp/try-except-statement?view=vs-2019). – Eljay Mar 03 '20 at 12:18
  • What _should_ your calculator do when it gets a zero divisor? Your test should look whether the behavior is as expected. As you've not specified what is expected (required), you obviously can't write a test. – Ruslan Mar 03 '20 at 12:33
  • 1
    @Ruslan It's expected to throw an exception if I read the question correctly. – Ted Lyngmo Mar 03 '20 at 12:40
  • Your question boils down to "How do I write a CPPUnit test that an expected exception is thrown?". Basically, you need to test error handling. The "division by zero" is not an important part of your actual problem (it never happens because your code prevents it!) even though the ways to handle it are an interesting discussion in and of itself. – Ulrich Eckhardt Mar 03 '20 at 13:25

1 Answers1

2

You should not use assert::AreEqual when checking for exceptions. You could wrap your exception throwing code in a lambda and pass it to Assert::ExpectException<std::runtime_error>, which should assert true if the expected exception is thrown:

    TEST_METHOD(DivByZeroTest)
    {
        auto func = [] { return cal.divide(1.f, 0.f); };
        Assert::ExpectException<std::runtime_error>(func);
    }

I expect that this does something like this internally::

bool result = false;
try {
    func();
} catch(const std::runtime_error&) {
    result = true;
} catch(...) {
}
return result;
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108