Detailed testing tools in Python

  • 2021-06-28 09:34:36
  • OfStack

When we write a program, we need tests to verify that the program is wrong or has problems, but writing a lot of tests to make sure every detail of the program is okay doesn't seem cumbersome.In Python, we can use a number of standard modules to help us automate the testing process, such as:

unittest: A common test framework; doctest: A simpler module designed to check documentation, but also ideal for writing unit tests.

Below, the author will briefly introduce the application of these two modules in testing.

doctest

The doctest module searches for code snippets that appear to be in an python interactive session, then attempts to execute and validate the results.Let's take doctest.testmod as an example. The function doctest.testmod reads all the document strings in the module, looks for examples that look like they were picked up from an interactive interpreter, and checks if they reflect reality.

Let's first create the sample code file test_string_lower.py, complete code as follows:


# -*- coding: utf-8 -*-

def string_lower(string):
  '''
   Return 1 Lowercase of strings 
  :param string: type: str
  :return: the lower of input string
  >>> string_lower('AbC')
  'abc'
  >>> string_lower('ABC')
  'abc'
  >>> string_lower('abc')
  'abc'
  '''
  return string.lower()

if __name__ == '__main__':
  import doctest, test_string_lower
  doctest.testmod(test_string_lower)

First the program is described, function string_lower returns the lowercase of the input string. The comment in the function contains 3 test instances, expecting to contain as many test cases as possible, and then imports them in the main function doctest, test_string_lower , then run the testmod function in doctest to test.

Next, we start testing.First, type in the command line python test_string_lower.py , you will find nothing to output after running, but this is a good thing, it indicates that all tests in the program have passed!So what if we want to get more output?You can add the parameter - v when running the script, when the command becomes python test_string_lower.py -v, the output is as follows:


Trying:
  string_lower('AbC')
Expecting:
  'abc'
ok
Trying:
  string_lower('ABC')
Expecting:
  'abc'
ok
Trying:
  string_lower('abc')
Expecting:
  'abc'
ok
1 items had no tests:
  test_string_lower
1 items passed all tests:
  3 tests in test_string_lower.string_lower
3 tests in 2 items.
3 passed and 0 failed.
Test passed

You can see that there are still a lot of things happening behind program testing.Next, we try to find out what went wrong with the program, such as when we accidentally wrote the return of a function as:

return string.upper()

This actually returns the upper case of the input string, but the example we tested returns the lower case of the input string and runs the script (with the parameter -v) with the following output:


Failed example:
  string_lower('abc')
Expected:
  'abc'
Got:
  'ABC'
1 items had no tests:
  test_string_lower
**********************************************************************
1 items had failures:
  3 of  3 in test_string_lower.string_lower
3 tests in 2 items.
0 passed and 3 failed.
***Test Failed*** 3 failures.

At this point, the program test failed, not only capturing bug, but also clearly pointing out where the error occurred.It is not difficult for us to modify this program.

For more detailed instructions on the use of the doctest module, you can refer to the website address: https://docs.python.org/2/lib....

unittest

Similar to the popular Java test framework JUnit, unittest is more flexible and powerful than doctest, enabling you to write large and detailed test sets in a structured way.

Let's start with a simple example, starting with writing my_math.py script, code as follows:


# -*- coding: utf-8 -*-
def product(x, y):
  '''
  :param x: int, float
  :param y: int, float
  :return: x * y
  '''
  return x * y

This function implements the following functions: Enter two numbers x, y, and return the product of the two numbers.Next comes test_my_math.py script, complete code as follows:


import unittest, my_math

class ProductTestcase(unittest.TestCase):

  def setUp(self):
    print('begin test')

  def test_integers(self):
    for x in range(-10, 10):
      for y in range(-10, 10):
        p = my_math.product(x, y)
        self.assertEqual(p, x*y, 'integer multiplication failed')

  def test_floats(self):
    for x in range(-10, 10):
      for y in range(-10, 10):
        x = x/10
        y = y/10
        p = my_math.product(x, y)
        self.assertEqual(p, x * y, 'integer multiplication failed')

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

The function unittest.main is responsible for running tests for you: execute the setUp method before the test method, instantiate all TestCase subclasses, and run all methods whose names begin with test.The assertEqual method checks the conditions specified by the car (equal here) to determine whether the specified test succeeded or failed.

Next, we run the previous tests and the output is as follows:

begin test
.begin test
.
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

You can see that the program runs two tests, each with an output of'begin test'. indicating that the test was successful, and if the test failed, it returned F.

Next, to simulate a test failure, my_The product method in the math function changes to return:

return x + y

Run the test script again, and the output is as follows:

begin test
Fbegin test
F
======================================================================
FAIL: test_floats (__main__.ProductTestcase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_my_math.py", line 20, in test_floats
self.assertEqual(p, x * y, 'integer multiplication failed')
AssertionError: -2.0 != 1.0 : integer multiplication failed

======================================================================
FAIL: test_integers (__main__.ProductTestcase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_my_math.py", line 12, in test_integers
self.assertEqual(p, x*y, 'integer multiplication failed')
AssertionError: -20 != 100 : integer multiplication failed

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=2)

Next, you should be able to quickly fix the bug.

For a more detailed explanation of the unittest module, you can refer to the website address: https://docs.python.org/3/lib....

summary

The above is the test tool in Python introduced to you by this site. I hope it will be helpful to you. If you have any questions, please leave a message for me. This site will reply to you technically!


Related articles: