0

I have a class called Helper which contains a method called create_list. The tests I've written for the create_list method include a case where a TypeError is supposed to be raised if any of the values doesn't match the type expected.

The class is below:

class Helper(object):

    def create_list(self, hel_id, hel_name, hel_type, hel_desc):
        if not isinstance(hel_id, int):
            raise TypeError
        elif not isinstance(hel_name, str):
            raise TypeError
        elif not isinstance(hel_type, str):
            raise TypeError
        elif not isinstance(hel_desc, str):
            raise TypeError

and the test which I've written is below:

import unittest

import Helper


class TestHelp(unittest.TestCase):
"""Unit Tests for the Helper class"""

    def setUp(self):
        self.helper = Helper()

    def test_create_list_raise_type_error(self):
        with self.assertRaises(TypeError):
            self.helper.create_list('', 'somename', 'sometype', 'somedescription')
            self.helper.create_list(1, 1, 'sometype', 'somedescription')
            self.helper.create_list(1, 'somename', 1, 'somedescription')
            self.helper.create_list(1, 'somename', 'sometype', 1)

The problem is that the tests pass when the first if isinstance check is added to the Helper class. Commenting out the other checks doesn't make the test fail. How can I write the test (or the code, if that's the issue) such that it only passes when all the conditions are met i.e. a TypeError is raised for each invalid input.

leni1
  • 13
  • 6
  • One way may be to use `AND` operator for all these conditions. – Soumendra Jul 15 '18 at 17:52
  • Possible duplicate of [How do you generate dynamic (parametrized) unit tests in python?](https://stackoverflow.com/questions/32899/how-do-you-generate-dynamic-parametrized-unit-tests-in-python) – awesoon Jul 15 '18 at 17:55
  • @soon I'm not trying to generate dynamic unit tests. I just want to make sure that the test case passes only when all the `isinstance` checks raise a `TypeError` and not only when _one_ `isinstance` check raises a `TypeError`. – leni1 Jul 15 '18 at 19:02
  • @Soumendra using `and` gave me `SyntaxError` issues thus why I chose this approach. – leni1 Jul 15 '18 at 19:13
  • @leni1 It is bad practice when your unit test contains several asserts (except cases when you are checking pipeline of actions - though maybe they are not unit anymore). It is considered bad because it is hard to say what are you checking in the test. The main key in the linked question is not 'dynamic' but 'parametrized'. You can write test with a single line body like `self.helper.create_list(*args)` (inside `self.assertRaises` block) and parametrize the test with required args (e.g. `[[1, 'somename', 'sometype', 1], [1, 'somename', 1, 'somedescription'], ...]`). – awesoon Jul 16 '18 at 04:03
  • @soon thanks for the clarification. Will look into it and try to revise my test accordingly. – leni1 Jul 17 '18 at 16:39

1 Answers1

2

Your example passes because one instantiation raises an Exception. Assert for all of the instantiations like this:

import unittest

class TestHelp(unittest.TestCase):

    def setUp(self):
        self.helper = Helper()

    def test_create_list_raise_type_error(self):
        with self.assertRaises(TypeError):
            self.helper.create_list('', 'somename', 'sometype', 'somedescription')
        with self.assertRaises(TypeError):
            self.helper.create_list(1, 1, 'sometype', 'somedescription')
        with self.assertRaises(TypeError):
            self.helper.create_list(1, 'somename', 1, 'somedescription')
        with self.assertRaises(TypeError):
            self.helper.create_list(1, 'somename', 'sometype', 1)
Josh Abraham
  • 959
  • 1
  • 8
  • 18