What Is Unit Testing In Python.

Saurabhmirgane
8 min readOct 11, 2020

--

As we were working with insideaiml project, which was required to check the quality of the codes, been used in project also to verify, whether the project we are going to release is going to be benefited one or not?

The conversation is not yet been over guys, like you all, even I was confuse how to simplify this issue, then finally got to know the solution out of it which “Unit testing in python” which has got the very good concept of solving this type of issues working with any project.

Lets clear a lot more interesting things, in this content covering importance of unit testing in python, and its uses in python programming language.

‘pyunit’ is the python language which is the version of Junit which was introduced by “Kent Beck and Erich Gamma”, each has their own standard unit testing for their respective language

The unit test modules, provides the different classes which makes it easy to support the better qualities for set of test. Which also supports setup and shutdown code for test aggregation of test?

Unit test supports test automation, sharing of setup and shutdown code for tests, aggregation of tests into collections, and independence of the tests from the reporting framework.

What is unit testing in python?

For working with python, we need some software to determine/examine whether they are fit for us or not, in order to pretend such things, we use unit testing in python, which has got its own software to measure the things which are useful or non useful things in python programming language, it also verifies, the quality of code and gives us the final output.. The frame work which is used in unit testing is called unit test. which is already in build in python, but they require separate files to code also they have their own different naming conventions.

You could either write the name of the unit test file, as the name of the code/unit + test, separated by an underscore, or test + name of the code/unit separated by an underscore.

The unit test framework follows Xunit style where, A unit can be categorized into different modules they are:

  • An entire module,
  • An individual function,

Let’s understand more additional functions about unit test, which also supports the command line options, which are as follows:-

b — Buffer

Buffer helps in detecting the errors during test running, the output which is receives is been discarded on test fail or error and these are added to the failure messages

C — Catch

c- Stands for catch here, which functions for the current test to end test which gives results for all the reports.

f — Failfast

It stops the complete test, on the very first test.

k--

This is mostly used for methods & classes, that is used to define the patterns or substrings, this method can be used infinite times we use to test any case which matched the provided pattern.

The fnmatch.fnmatchcase(): is used against test name which contains, the pattern with wildcard character(*), & the patterns which are finalized for test method are imported by test loader.

the simplest way to write unit test, is start with small testable unit and then match this unit with the other units which can build up a comprehensive unit test for our created applications.

Let’s understand with the coding part.

import unittest
class SimpleTest(unittest.TestCase):
# Returns True or False.
def test(self):
self.assertTrue(True)

This is the basic test code using unit test framework, which is having a single test. This test() method will fail if TRUE is ever FALSE.

There are few important concepts to achieve unit test, they are as follows:

Test fixture :

It is used when we want to test one or more test,& also for any kind of clean up associate actions, for example creating temporary or proxy databases, directories, or starting a server process.

Test case:-

This is the smallest way of unit testing which checks specific set of inputs. Which also provides a base class, test case which is used for creating a new test case

Test suite:-

It’s a combination of test case or test suites which are used together or individually according to the requirement of the test.

Test runner:-

This component is organized to which provides the outcome of the user which is used mostly for graphical interface, a textual interface, or return a special value for the user.

Organizing test code:- The test are the basic basement for the unit testing, these are also

Used for checking the correctness of testing, in order to create our own unit testing we require testcase or use of “FunctionTestCase”

The testing code of a “TestCase ”instance should be entirely self contained, such that it can be run either in isolation or in arbitrary combination with any number of other test cases.

Lets understand this with coding part in, python.

import unittest
class DefaultappSizeTestCase(unittest.TestCase):
def test_default_app_size(self):
app1 = app1('The app')
self.assertEqual(app1.size(), (50, 50))

Important note:-

we use assert*() method to test something also which was provided by test case base class, but if it fails then there would be an explanatory message raise and this detection would be done with the help of unit testing, other than these everything would be considered as errors.

Setup()is the important testing framework which will automatically code itself for every single test we run, even though in any kind of situation though we have N number of test to work with :

Lets continue with above same example,

import unittest
class appTestCase(unittest.TestCase):
def setUp(self):
self.app = app('The widget')
def test_default_app_size(self):
self.assertEqual(self.app.size(), (50,50),
'incorrect default size')
def test_app_resize(self):
self.app.resize(100,150)
self.assertEqual(self.app.size(), (100,150),
'wrong size after resize')

IMPORTANT NOTE:- The order in which the various tests, will be run is determined by sorting the test method, names with respect to the built-in ordering for strings.

Also we can use teardown() method tidies up after the test method has been run, in order to avoid the errors which wasn’t been performed by setup()method..

Import unittest
class appTestCase(unittest.TestCase):
def setUp(self):
self.app = app ('The widget')
def tearDown(self):
self.app.dispose()

Explanation :-Teardown() method will run in any provided conditions, also where the setup() condition fails to execute the method.

Setup()& tearDown() These two functions, can be called only once during the test case.

Suite():

This is the method, which will allow us to modify or customize the UnitTest,

Let’s use the below code to execute with,

def suite():
suite = unittest.TestSuite()
suite.addTest(appTestCase('test_default_app_size'))
suite.addTest(appTestCase('test_app_resize'))
return suite
if __name__ == '__main__':
runner = unittest.TextTestRunner()
runner.run(suite())

Conclusion about organized TestCode:

You can place the definitions of test cases, and test suites in the same modules as the code. They are to test (such as app.py), but there are several advantages to placing the test code in a separate module, such as test_app.py:

The test module can be easily separated, and run standalone from the command line. it also can be refactored easily, & it doesn’t make any reason to test the code if its a good test.

Test code, should be modified much less frequently than the code it tests.

The simplest TestCase subclass, will simply override the runTest() method in order to perform specific testing code.

Re-using old test code:

Why one requires re-using of old test code?

It so happens, that user wants to convert every old test function, without converting testcase in such cases we can use the existing test code.

For this reason, UnitTest provides a Function Testcase class. This subclass of TestCase can be used to wrap an existing test function. Set-up and tear-down functions can also be provided.

Given the following test function:

def testinsideaiml():

something = makeinsideaiml()

assert insideaiml.name is not None

Note

Even though FunctionTestCase can be used to quickly convert an existing test base over to a UnitTest-based system, this approach is not recommended. Taking the time to set up, proper TestCase subclasses will make future test refactoring's infinitely easier.

Classes and functions

Class UnitTest.TestCase([methodName])

Instances of the TestCase class represent, the smallest testable units in the UnitTest universe. This class is intended to be used as a base class, with specific tests being implemented by concrete subclasses. This class implements the interface needed by the test runner to allow it to drive the test, and methods that the test code can use to check for and report various kinds of failure.

The UnitTest module provides a rich set of tools for constructing and running tests. This section demonstrates that a small subset of the tools suffice to meet the needs of most users.

Here is a short script to test three string methods:

import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
def test_isupper(self):
self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())
def test_split(self):
s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
# check that s.split fails when the separator is not a string
with self.assertRaises(TypeError):
s.split(2)
if __name__ == '__main__':
unittest.main()

A testcase is created by sub classing UnitTest.caseThe three individual tests are defined with methods whose names start with the letters test. This naming convention informs the test runner about which methods represent tests.x

Test Case Objects

Each Test Case instance represents a single test, but each concrete subclass may be used to define multiple tests — the concrete class represents a single test fixture. The fixture is created and cleaned up for each test case.

Test Case instances provide three groups of methods: one group used to run the test, another used by the test implementation to check conditions and report failures, and some inquiry methods allowing information about the test itself to be gathered.

Methods in the first group are:

  1. SetUp()
  2. Tear down()
  3. Run()
  4. Debug()

Test Suite Objects

TestSuite objects behave much like TestCase objects, except they do not actually implement a test. Instead, they are used to aggregate tests into groups that should be run together. Some additional methods are available to add tests to TestSuite instances:

def suite():
suite = unittest.TestSuite()
suite.addTest(appTestCase('test_default_app_size'))
suite.addTest(appTestCase('test_app_resize'))
return suite
if __name__ == '__main__':
runner = unittest.TextTestRunner()
runner.run(suite())

Therefore:-

  1. Add a TestCase or TestSuite to the set of tests that make up the suite.
  2. Add all the tests from a sequence of TestCase and TestSuite instances to this test suite.
  3. The run() method is also slightly different:

Run(result)

Run the tests associated with this suite, collecting the result into the test result object passed as result. Note that unlike TestCase.run(), TestSuite.run() requires the result object to be passed in.

In the typical usage of a TestSuite object, the run() method is invoked by a Test Runner rather than by the end-user test harness.

Since that unit testing is one of the most important concept from data science course, similarly its important to gain knowledge about related information like,

https://saurabhmirgane007.medium.com/what-are-r-squared-and-adjusted-r-squared-dbfc0961b864

Think creative be positive.

Happy Learning.

--

--