As Python is a dynamic language, unit testing is not only important for verifying code works as expected, but also needs to cover situations that statically typed languages get for free. So a high level of test coverage is useful to ensure event basic methods are working and even named as expected.
Let’s create a simply Calculator class which we will then write unit tests for (this is saved in a file named calc.py)
class Calculator: def add(self, a, b): return a + b
We can then create a file test_calculator.py and within this we have the following
from unittest import TestCase from calc import Calculator class TestCalculator(TestCase): def test_add(self): c = Calculator() self.assertEqual(5, c.add(3, 2))
As you can see, we need to derive our test class from the TestCase class and test methods should use the naming convention test_ at the start of the test method’s name.
Note: the class name does not require the Test prefix/naming convention.
Using PyCharm we need to create a new configuration, from the Python tests configuration section. Select nosetests and then name the configuration, something like Calculator Tests.
Now we can run the tests. If you find nosetest is not installed you can run the Python Console from PyCharm and run the command
pip install nose
setUp/tearDown
Like most unit testing frameworks, the TestCase class can use a setUp and/or tearDown method for setting up the test case context and cleaning up after each test method is run.
For example
class CalculatorTests(TestCase): def setUp(self): self.c = Calculator() def test_add(self): self.assertEqual(5, self.c.add(3, 2)) def test_subtract(self): self.assertEqual(2, self.c.subtract(7, 5))
setUpClass/tearDownClass
TestCase also includes setUpClass and tearDownClass for setting context for all test methods within a TestCase.
For example, here’s the previous TestCase but using the setUpClass to create the calculator for all test methods
class CalculatorTests(TestCase): @classmethod def setUpClass(cls): cls.c = Calculator() def test_add(self): self.assertEqual(5, self.c.add(3, 2)) def test_subtract(self): self.assertEqual(2, self.c.subtract(7, 5))
Note: the @classmethod is required in this example code or the setUpClass is not treated as a class method as is expected.
References
unittest — Unit testing framework
Creating and running a Python unit test