trillion
trillion

Reputation: 1401

Raise ValueError not getting through unit test

I am trying the unitest to raise the value error when the value is negative using the code below.

A raise error is added : number should be greater than 0 But when I run the code below:

from functools import reduce
import math
import unittest

def calculate_factorial(number):
    if number < 0:
        print('about to throw value error')
        raise ValueError('number should be greater than 0')
    elif type(number) != int:
        raise  TypeError('number should be an integer type')
    else:
        data = []
        for i in range(number):
            data.append(number - i)
            print(data)
        results = reduce((lambda x, y: x * y), data, 1)
        return results

class TestCalc(unittest.TestCase):
    def test_factorial(self):
        print('Function is starting to check for values')
        print()
        result = calculate_factorial(n)
        print('results are:',result)
        print()
        self.assertEqual(result,math.factorial(n))
        
        
    def test_n(self):
        print('The value of n taken by the class function is:',n)
        

run = True
while run:
    n = int(input('Enter an integer value: '))
    if n != -9999:
        unittest.main(argv=[''], verbosity=2, exit=False)
    else:
        run = False

I am getting the error as following. I can see below that my raise value is getting passed through but somehow the test class is not considering it.

test_factorial (__main__.TestCalc) ... ERROR
test_n (__main__.TestCalc) ... ok

======================================================================
ERROR: test_factorial (__main__.TestCalc)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython-input-3-d89c3d44c70d>", line 5, in test_factorial
    result = calculate_factorial(n)
  File "<ipython-input-2-2ad930b1e911>", line 5, in calculate_factorial
    raise ValueError('number should be greater than 0')
ValueError: number should be greater than 0

----------------------------------------------------------------------
Ran 2 tests in 0.010s

FAILED (errors=1)

Upvotes: 0

Views: 1929

Answers (1)

Sven Eberth
Sven Eberth

Reputation: 3116

As already mentioned in my comments, your test fails because the raised ValueError is not expected here. You can extend you test with an if to handle positive and non-positive values differently.

class TestCalc(unittest.TestCase):
    def test_factorial(self):
        print('Function is starting to check for values')
        print()
        if n < 0:
            with self.assertRaises(ValueError) as context:
                calculate_factorial(n)
            self.assertEqual('number should be greater than 0', str(context.exception))
        else:
            result = calculate_factorial(n)
            print('results are:', result)
            print()
            self.assertEqual(result, math.factorial(n))

    def test_n(self):
        print('The value of n taken by the class function is:', n)

However, it could be better to have different tests for different value ranges/kinds with fixed values like this:

class TestCalcFixedValues(unittest.TestCase):
    def test_factorial_positive(self):
        self.assertEqual(calculate_factorial(42), math.factorial(42))

    def test_factorial_negative(self):
        with self.assertRaises(ValueError) as context:
            calculate_factorial(-42)
        self.assertEqual('number should be greater than 0', str(context.exception))

    def test_factorial_NaN(self):
        with self.assertRaises(TypeError) as context:
            calculate_factorial("NaN")
        self.assertEqual('number should be an integer type', str(context.exception))

(then you will see, that calculate_factorial has a bug ;))

Upvotes: 2

Related Questions