Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiate Python unittest.TestCase with arguments

I would like to iterate over a list of items, and run an assertion on each of them. One example might be checking whether each number in a list is odd.

TestCase:

class TestOdd(unittest.TestCase):
    def runTest(self):
        """Assert that the item is odd"""
        self.assertTrue( NUMBER %2==1, "Number should be odd")

Test suite:

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTest(TestOdd())
    # I would like to have:
    # suite.addTest(TestOdd(1))
    # suite.addTest(TestOdd(2))
    # suite.addTest(TestOdd(3))
    # ...
    unittest.main()

How can I instantiate a TestOdd object with an argument - for example, the number to be tested?

Update: According to a blog post from 2011 (posted as answer), there is no built-in mechanism for parametrized tests. I will be happy to accept any cleaner solutions.

like image 254
Adam Matan Avatar asked Jun 23 '13 11:06

Adam Matan


2 Answers

According to "Python unit testing: parametrized test cases", published in Eli Bendersky's blog:

Python’s standard unittest library is great and I use it all the time. One thing missing from it, however, is a simple way of running parametrized test cases. In other words, you can’t easily pass arguments into a unittest.TestCase from outside.

Eli's solution is inheriting unittest.TestCase into ParametrizedTestCase. I'm not sure about copyright issues, so I won't copy-paste the code here.

If there is any better solution, I will be happy to accept it.

like image 152
Adam Matan Avatar answered Oct 14 '22 05:10

Adam Matan


Same can be achieved using class attributes.

class TestOdd1(unittest.TestCase):
    NUMBER=1
    def runTest(self):
        """Assert that the item is odd"""
        self.assertTrue( self.NUMBER % 2 == 1, "Number should be odd")

class TestOdd2(TestOdd1):
    NUMBER=2

if __name__ == '__main__':
    unittest.main()

The unittesting will discover them automatically, so no need to create a suite.

If you want to avoid using a TestCase for base class, you can use multiple inheritance:

from unittest import TestCase, main

class TestOdd:
    def runTest(self):
        """Assert that the item is odd"""
        self.assertTrue( self.NUMBER % 2 == 1, "Number should be odd")

class TestOdd1(TestOdd, TestCase):
    NUMBER=1
class TestOdd2(TestOdd, TestCase):
    NUMBER=2

if __name__ == '__main__':
    main()
like image 26
Marko Kohtala Avatar answered Oct 14 '22 04:10

Marko Kohtala