E2E Python solution in DevOps – Part 6: Add test cases to project
In this serie I show you how you can create a PyPi ready solution which is stored on GitHub and has fully automatized build-test-deploy CI/CD pipeline in Azure DevOps. Furthermore you will be able to use it from command line like azure-cli or aws-cli.
Table of content
- Part 1: Basic Python Code
- Part 2: Basic Release diagram
- Part 3: Azure DevOps preparation
- Part 4: Create Azure DevOps pipeline – staging
- Part 5: Create Azure DevOps pipeline – master
- Part 6: Add test cases to project (current)
- Part 7: Expand Python project functionality
In Part 5 more or less we reached our goal. Nevertheless several integrated test cases (unittest) are recommended in a well built code. Therefore Today we add a unittest to our project.
Before we start we need to know some facts about unittests in Python:
- Unittest implementation is not a rocket science, merely we have to follow the best practices
- During unittest the functions are really executing. This means when you test a function in unittest it will call in live not only for testing.
- Prepare your unittest for modular usage.
Then recommended to know the background of unittests:
We use the Python 2.7 related unittest in our project.
1. We create unittest for our Core module. Therefore the simplest thing if we put our unittest next to core module files inside core directory (<project directory>/pypiproject/core). Name if this file in our example is: pypiproject_core_unittest.py
2. Content of the file is very simple.
- unittest package import
- core module import for testing
- TestCase moduile class which contains the required test cases
- TestCase runner function – this is required because we won’t run unittest from __main__.
# Import unittest import unittest # Import core module main file for testing from .pypiproject_core import * # Test case Class class TestCoreModule(unittest.TestCase): currentResult = None # holds last result object passed to run method def setUp(self): pass # teardown for manage test case results def tearDown(self): ok = self.currentResult.wasSuccessful() errors = self.currentResult.errors failures = self.currentResult.failures print ('All tests passed so far!' if ok else \ ' %d errors and %d failures so far' % \ (len(errors), len(failures))) def run(self, result=None): self.currentResult = result # remember result for use in tearDown unittest.TestCase.run(self, result) # call superclass run method # Test Case 01 - Write out text in string format with default value def test_input(self): self.assertEqual(getText("test text"), "test text") # Test Case 02 - Write out text in string and json format def test_output(self): self.assertEqual(getText("test text", "string"), "test text") self.assertEqual(getText("test text", "json"), {"text": "test text"}) # Test runner function def runUnittests(): suite = unittest.TestSuite() # Check test cases in TestCoreModule class for method in dir(TestCoreModule): # Add test collection tests which start with "test" if method.startswith("test"): suite.addTest(TestCoreModule(method)) # Return with execution and result of testcases return unittest.TextTestRunner(verbosity=3).run(suite)
3. How can you run the test cases?
It is pretty easy and simple to automatize
Start a Python shell where our project is installed then execute the following commands:
from pypiproject.core.pypiproject_core_unittest import * testResult = runUnittests()
and the result is awesome:
test_input (pypiproject.core.pypiproject_core_unittest.TestCoreModule) ... All tests passed so far! ok test_output (pypiproject.core.pypiproject_core_unittest.TestCoreModule) ... All tests passed so far! ok ---------------------------------------------------------------------- Ran 2 tests in 0.003s OK
Additionally the testResult variable contains the detailed result of execution.
It was easy and I hope make sense. If you have any further questions feel free to get in touch with your questions.