I had to do something similar. I created simple TestCase subclasses that took a value in their __init__, like this:
class KnownGood(unittest.TestCase):
def __init__(self, input, output):
super(KnownGood, self).__init__()
self.input = input
self.output = output
def runTest(self):
self.assertEqual(function_to_test(self.input), self.output)
I then made a test suite with these values:
def suite():
suite = unittest.TestSuite()
suite.addTests(KnownGood(input, output) for input, output in known_values)
return suite
You can then run it from your main method:
if __name__ == '__main__':
unittest.TextTestRunner().run(suite())
The advantages of this are:
- As you add more values, the number of reported tests increases, which makes you feel like you are doing more.
- Each individual test case can fail individually
- It's conceptually simple, since each input/output value is converted into one TestCase
I had to do something similar. I created simple TestCase subclasses that took a value in their __init__, like this:
class KnownGood(unittest.TestCase):
def __init__(self, input, output):
super(KnownGood, self).__init__()
self.input = input
self.output = output
def runTest(self):
self.assertEqual(function_to_test(self.input), self.output)
I then made a test suite with these values:
def suite():
suite = unittest.TestSuite()
suite.addTests(KnownGood(input, output) for input, output in known_values)
return suite
You can then run it from your main method:
if __name__ == '__main__':
unittest.TextTestRunner().run(suite())
The advantages of this are:
- As you add more values, the number of reported tests increases, which makes you feel like you are doing more.
- Each individual test case can fail individually
- It's conceptually simple, since each input/output value is converted into one TestCase
Not tested:
class TestPreReqs(unittest.TestCase):
...
def create_test (pair):
def do_test_expected(self):
self.assertEqual(under_test(pair[0]), pair[1])
return do_test_expected
for k, pair in enumerate ([(23, 55), (4, 32)]):
test_method = create_test (pair)
test_method.__name__ = 'test_expected_%d' % k
setattr (TestPreReqs, test_method.__name__, test_method)
If you use this often, you could prettify this by using utility functions and/or decorators, I guess. Note that pairs are not an attribute of TestPreReqs object in this example (and so setUp is gone). Rather, they are "hardwired" in a sense to the TestPreReqs class.
I've read the docs here on unittest but I am confused on how should I test multiple test where I have to use only use assertEquals. import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
self.assertEqual('too'.upper(), 'TOO')
self.assertEqual('poo'.upper(), 'POO')
if __name__ == '__main__':
unittest.main()So, If I run this it shows only one test run, I understand why it shows that but how should I organize the test so that I get to know which assertions passed and which failed because it will show the failed ones and i will not have much control over them.
For example my test cases will look something like this,
[{ inputString: 'i like to sleep',
outputDict: {sleepHours: 7, likes: 'sleeping' }
},{...},{...},{...}]python - Creating a test suite from multiple test cases - Stack Overflow
unit testing - Multiple tests per method, new workplace - Python - Software Engineering Stack Exchange
How do I run multiple Python test cases in a loop? - Stack Overflow
How do I run multiple Classes in a single test suite in Python using unit testing? - Stack Overflow
Starting from python 3.4, you can do it like this:
def test_output(self):
for i in range(1,11):
with self.subTest(i=i):
....
self.assertEqual(fn(i),output[i])
https://docs.python.org/3.4/library/unittest.html?highlight=subtest#distinguishing-test-iterations-using-subtests
Using unittest you can show the difference between two sequences all in one test case.
seq1 = range(1, 11)
seq2 = (fn(j) for j in seq1)
assertSequenceEqual(seq1, seq2)
If that's not flexible enough, using unittest, it is possible to generate multiple tests, but it's a bit tricky.
def fn(i): ...
output = ...
class TestSequence(unittest.TestCase):
pass
for i in range(1,11):
testmethodname = 'test_fn_{0}'.format(i)
testmethod = lambda self: self.assertEqual(fn(i), output[i])
setattr(TestSequence, testmethodname, testmethod)
Nose makes the above easier through test generators.
import nose.tools
def test_fn():
for i in range(1, 11):
yield nose.tools.assert_equals, output[i], fn(i)
Similar questions:
- Python unittest: Generate multiple tests programmatically?
- How to generate dynamic (parametrized) unit tests in python?
If you want to run all of the tests from a specific list of test classes, rather than all of the tests from all of the test classes in a module, you can use a TestLoader's loadTestsFromTestCase method to get a TestSuite of tests for each class, and then create a single combined TestSuite from a list containing all of those suites that you can use with run:
import unittest
# Some tests
class TestClassA(unittest.TestCase):
def testOne(self):
# test code
pass
class TestClassB(unittest.TestCase):
def testOne(self):
# test code
pass
class TestClassC(unittest.TestCase):
def testOne(self):
# test code
pass
def run_some_tests():
# Run only the tests in the specified classes
test_classes_to_run = [TestClassA, TestClassC]
loader = unittest.TestLoader()
suites_list = []
for test_class in test_classes_to_run:
suite = loader.loadTestsFromTestCase(test_class)
suites_list.append(suite)
big_suite = unittest.TestSuite(suites_list)
runner = unittest.TextTestRunner()
results = runner.run(big_suite)
# ...
if __name__ == '__main__':
run_some_tests()
I'm a bit unsure at what you're asking here, but if you want to know how to test multiple classes in the same suite, usually you just create multiple testclasses in the same python file and run them together:
import unittest
class TestSomeClass(unittest.TestCase):
def testStuff(self):
# your testcode here
pass
class TestSomeOtherClass(unittest.TestCase):
def testOtherStuff(self):
# testcode of second class here
pass
if __name__ == '__main__':
unittest.main()
And run with for example:
python mytestsuite.py
Better examples can be found in the official documention.
If on the other hand you want to run multiple test files, as detailed in "How to organize python test in a way that I can run all tests in a single command?", then the other answer is probably better.
You can put the asserts in a loop:
def test_fact(self):
tests = [(1,1), (2,2), (3,6), (4,24), (5,120)]
for n,f in tests:
self.assertEqual(fact(n), f)
I'd say your ways of doing it is generally fine (but read on).
You could, as interjay suggested, do a loop (and, incidentally, it only counts as one test because the unittest module counts the number of functions, not the number of asserts). But I assume you won't exhaustively try to test every number, or even all numbers within a very large interval. So looping won't save you much, and, especially in testing, you should aim at being explicit.
Having said that, you should test for a small number of subsequent numbers (say, 1 through 5), and then try to get a feel for where possible corner cases and failures points are. Say, test for 10, 100, 1000 (that is, change order of magnitude), negative numbers, zero etc.
BTW, watch out for your two last tests. The first of them doesn't mean much. fact(5) is different than a LOT of numbers (infinite numbers, actually). Test for the correct case, testing for the incorrect ones isn't productive.
def test_fact_5(self):
self.assertFalse(1==fact(5))
The second one is badly named: "test_fact_6" makes me think you're testing fact(6). You should name it as something like "test_fact_minus_one", or at least "test_fact_negative_number".
def test_fact_6(self):
self.assertRaises(RuntimeError, fact, -1)
Test naming is very important, both when you're debugging errors and when you refer back to the tests as documentation.
The answer is subTest. However, this is only available as of Python 3.4.
There is unittest2, though. It provides a backport of the latest features of unittest in Python 3.4 (including subTest). unittest2 is tested to run on Python 2.6, 2.7, 3.2, 3.3, 3.4 and pypy.
Several libraries will allow you to do this. For example, the py.test example is as follows:
import pytest
@pytest.mark.parametrize("test_input,expected", [
("3+5", 8),
("2+4", 6),
("6*9", 42),
])
def test_eval(test_input, expected):
assert eval(test_input) == expected
This is from the py.test documentation.