Search

12 June, 2019

Python unittest and exceptions: Writing custom exceptions, and catching them.


Generally in unit test, we match the responses with an expected value . But there are cases , where calling a method or passing an incorrect value (or type of value) may raise an exception . This exception might me a custom exception . Or the message or error code might me specific to the situation. So how to write test for the same.

1. Calling a method with incorrect type , raises an exception.


class MyTest(unittest.TestCase):
    def test_exception(self):
         with self.assertRaises(xmlrpclib.Fault) as cm:
            self.Proxy.setParameter('name', 1234)
            self.fail('Expected exception of type xmlrpc.Fault')




In the above example test,
  • The tests purpose is to expect a particular type of exception "xmlrpclib.Fault". 
  • We are trying to set the param "name" with a value 1234 which is incorrect.
  • We expect an error to be raised when we call the setParameter method with this argument.
  • If no exception is raised, then we must fail the test. 

Lets create some of our own methods that can raise exceptions if you do something it does not like.
Then lets add a test for the same.

Here you will learn :

  • How to create custom exception
  • How to set custom properties to our exception class.
  • How to use the exception in our methods to raise correct errors.
  • How to write tests that verify if correct exception has been raised.



import unittest

class DeviceException(Exception):
    def __init__(self, msg, code):
        self.msg = msg
        self.code = code
    def __str__(self):
        return repr("Error {}: {}".format(self.code, self.msg))

class MyDevice(object):
    def __init__(self):
        self.name = 'DefaultName'
        
    def setParameter(self, param, value):
        if isinstance(value, str):
            setattr(self, param , value)
        else:
            raise DeviceException('Incorrect type of argument passed. Name expects a string', 100001)

    def getParameter(self, param):
        return getattr(self, param)

class TestMyDevice(unittest.TestCase):
    
    def setUp(self):
        self.dev1 = MyDevice()

    def tearDown(self):
        del self.dev1
        
    def test_name(self):
        """ Test for valid input for name parameter """
        
        self.dev1.setParameter('name', 'MyDevice')
        name = self.dev1.getParameter('name')
        self.assertEqual(name, 'MyDevice')

    def test_invalid_name(self):
        """ Test to check if error is raised if invalid type of input is provided """
        
        self.assertRaises(DeviceException, self.dev1.setParameter, 'name', 1234)

    def test_exception_message(self):
        """ Test to check if correct exception message and code is raised when incorrect value is passed """
        
        with self.assertRaises(DeviceException) as cm:
            self.dev1.setParameter('name', 1234)
        self.assertEqual(cm.exception.msg, 'Incorrect type of argument passed. Name expects a string', 'mismatch in expected error message')
        self.assertEqual(cm.exception.code, 100001, 'mismatch in expected error code')
            
        
if __name__ == '__main__':
    unittest.main()



No comments:

Post a Comment