A summary of the use of UnitTest framework for Python unit testing __python

Source: Internet
Author: User
Tags prepare python script

One, what is unit test

Unit tests are tests that are used to test the correctness of a module, a function, or a class.

For example, for the function abs (), we can write the test cases as:

(1) Enter positive numbers, such as 1, 1.2, 0.99, and expect the return value to be the same as the input

(2) Enter complex numbers, such as-1,-1.2,-0.99, expecting the return value to be the opposite of the input

(3) input 0, expect to return 0

(4) Input non-numeric type, such as none, [], {}, expecting to throw TypeError

Putting these test cases into a test module is a complete unit test

Second,unittest working principle

The core four parts of UnitTest are: testcase,testsuite,testrunner,testfixture

(1) An example of a testcase is a test case. A test case is a complete test process that includes the setup of the preparation environment before the test, the execution of the test code (run), and the restoration of the environment after the test (teardown). The nature of the Meta Test (unit test) is right here, a test case is a complete test cell, by running the test unit, you can verify a problem.

(2) While multiple test cases are assembled, they are testsuite, and testsuite can also be nested testsuite.

(3) Testloader is used to load testcase into the testsuite.

(4) Texttestrunner is to execute the test case, where run (test) executes the run (Result) method in Testsuite/testcase

(5) The results of the test will be saved to the Texttestresult instance, including how many test cases have been run, how much has been accomplished, and how much has failed.

In summary, the whole process is the first to write a good testcase, and then by Testloader loaded testcase to Testsuite, and then run Texttestrunner by Testsuite, the results of the operation saved in the Texttestresult , the whole process is integrated into the Unittest.main module.

three, two examples below to see how unittest test a simple function

(1) Write a dict class that behaves like a dict, but can be accessed by attributes such as

>>> d = Dict (A=1, b=2)
>>> d[' A ']
1
>>> d.a
1

The mydict.py code is as follows:

Class Dict (Dict):
    def __init__ (self, **kw):
        super (Dict, self). __init__ (**kw)
 
    def __getattr__ (self, key):
        try: Return
            Self[key]
        except Keyerror:
            raise Attributeerror (r "' Dict ' object has no attribute '%s '"% Key)
 
    def __setattr__ (self, Key, value):
        Self[key] = value
 


The file mydict_test.py code for the test is as follows:

Import unittest from
mydict import Dict
 
 
class Testdict (unittest. TestCase):
    def test_init (self):
        d = Dict (a=1, b= ' test ')
        self.assertequal (D.A, 1)  # to determine if D.A equals 1
        Self.assertequal (d.b, ' test ')  # to determine if the d.b equals test
        self.asserttrue (isinstance (d, Dict))  # to determine if D is a dict type
 
    def test_key (self):
        d = Dict ()
        d[' key ' = ' value '
        self.assertequal (d.key, ' value ')
 
    def test _attr (self):
        d = Dict ()
        D.key = ' value '
        self.asserttrue (' key ' in D)
        self.assertequal (d[' key '), ' Value ')
 
    def test_keyerror (self):
        d = Dict ()
        with Self.assertraises (keyerror):  # through d[' empty '] When accessing a key that does not exist, the assertion throws Keyerror
            value = d[' empty '
 
    def test_attrerror (self):
        d = Dict ()
        with Self.assertraises (Attributeerror):  # When accessing nonexistent key via D.empty, we expect to throw attributeerror
            value = D.empty
 
 
if __ name__ = = ' __main__ ':
    unittest.main ()


Just run mydict_test.py as a normal Python script.

Output:

.....
----------------------------------------------------------------------
Ran 5 tests in 0.000s
 
OK


(2) to measure a simple subtraction interface

The mathfunc.py file code is as follows:

def add (A, B): return
    A + b
 
def minus (A, b): Return
    a-b
 
def multi (A, B): Return
    A * b
 
def divide (A, B): return
    B

The test_mathfunc.py file code is as follows:

Import unittest from
mathfunc Import *
 
 
class Testmathfunc (unittest. TestCase):
 
    def test_add (self):
        self.assertequal (3, Add (1, 2))
        self.assertnotequal (3, Add (2, 2))
 
    def Test_minus (self):
        self.assertequal (1, minus (3, 2))
 
    def test_multi (self):
        self.assertequal (6, multi (3, 2 )
 
    def test_divide (self):
        self.assertequal (2, Divide (6, 3))
        self.assertequal (2.5, Divide (5, 2))
 
if __name__ = = ' __main__ ':
	unittest.main ()

Output:

. F..
======================================================================
fail:test_divide (__main__. testdict)
----------------------------------------------------------------------
Traceback (most recent Call last):
  File "d:/pythonworkspace/test_mathfunc.py", line, in Test_divide
    self.assertequal (2.5, divide ( 5, 2))
assertionerror:2.5!= 2
 
----------------------------------------------------------------------
Ran 4 tests in 0.000s
 
FAILED (Failures=1)

You can see that you ran 4 tests, failed 1, and gave the reason for failure, 2.5!=2, which means our divide method is problematic.

A few notes on the output:

1, in the first line gives the identification of the results of each use case execution, success is., failure is F, error is E, skip is S. As you can see from the above, the execution of the test has nothing to do with the order of the methods, the Divide method is written in the 4th, but it is executed at the 2nd.

2, each test method starts with test, otherwise cannot be unittest recognized

3, in Uniitest.main () with the verbosity parameter can control the output error report of the level of detail, the default is 1, if set to 0, do not output the execution result of each use case, that is, no 1th row in the above result, if set to 2, then output detailed execution results, as follows:

Test_add (__main__. Testmathfunc) ... ok
test_divide (__main__). Testmathfunc) ... FAIL
Test_minus (__main__. Testmathfunc) ... ok
test_multi (__main__). Testmathfunc) ... ok
 
======================================================================
fail:test_ Divide (__main__. Testmathfunc)
----------------------------------------------------------------------
traceback (most Recent call last):
  File "d:/pythonworkspace/test_mathfunc.py", line, in Test_divide
    self.assertequal (2.5, Divide (5, 2))
assertionerror:2.5!= 2
 
------------------------------------------------------------------ ----
Ran 4 tests in 0.000s
 
FAILED (Failures=1)


Four, Organization Testsuite

The test cases above are not executed sequentially, and testsuite is used if you want the use cases to be executed in the order you set them. The case we add to the testsuite is executed in the order in which they were added.

Now we have only one test file, and if we have multiple test files, we can organize them with testsuite.

To continue with the example of the second subtraction above, now create a new file, test_suite.py, the following code:

# coding=utf-8
import unittest from
test_mathfunc import testmathfunc
 
if __name__ = ' __main__ ':
    Suite = UnitTest. TestSuite ()
 
    tests = [Testmathfunc ("Test_add"), Testmathfunc ("Test_minus"), Testmathfunc ("Test_divide")]
    Suite.addtests (Tests)
 
    runner = UnitTest. Texttestrunner (verbosity=2)
    Runner.run (Suite)

The results of the implementation are as follows:

Test_add (Test_mathfunc. Testmathfunc) ... ok
test_minus (test_mathfunc). Testmathfunc) ... ok
test_divide (test_mathfunc). Testmathfunc) ... FAIL
 
======================================================================
fail:test_divide (test_ Mathfunc. Testmathfunc)
----------------------------------------------------------------------
traceback (most Recent call last):
  File "D:\pythonWorkspace\HTMLTest\test_mathfunc.py", line, in Test_divide
    Self.assertequal (2.5, Divide (5, 2))
assertionerror:2.5!= 2
 
---------------------------------------------- ------------------------
Ran 3 tests in 0.000s
 
FAILED (Failures=1)

Five, output the results to a file

Now our test results can only be exported to the console, and now we want to output the results to the file for subsequent viewing.

Make a little change to the test_suite.py code as follows:

# coding=utf-8
 
import unittest from
test_mathfunc import testmathfunc
 
if __name__ = ' __main__ ':
    Suite = UnitTest. TestSuite ()
 
    tests = [Testmathfunc ("Test_add"), Testmathfunc ("Test_minus"), Testmathfunc ("Test_divide")]
    Suite.addtests (Tests)
 
    with open (' UnittestTextReport.txt ', ' a ') as  f:
        runner = UnitTest. Texttestrunner (Stream=f, verbosity=2)
        Runner.run (Suite)
 

Running the file, you will find that the directory generates ' UnittestTextReport.txt, and all the execution reports are exported to this file.

the setup and teardown of test fixture

When you encounter the situation where you want to start a database, you only want to connect to the database at the beginning and close the connection at the end. Then you can use the setup and teardown functions.

Class Testdict (UnitTest. TestCase):
 
    def setUp (self):
        print ' Setup ... '
 
    def teardown (self):
        print ' teardown ... '


The two methods are executed before each test method executes and after execution, and setup is used to prepare the environment for the test, teardown to clean up the environment for subsequent tests.

If you want to prepare an environment before all case execution and then clean up the environment after all case execution is finished, we can use SetupClass () and Teardownclass () with the following code format:

Class Testmathfunc (UnitTest. TestCase):
    @classmethod
    def setupclass (CLS):
        print "SetUp"
 
    @classmethod
    def teardownclass (CLS ):
        print "teardown"


Seven, Skip a case

UnitTest offers several ways to skip case

(1)Skip decoration device

The code is as follows

# coding=utf-8
import unittest from
mathfunc Import *
 
class Testmathfunc (unittest. TestCase): ...
 
    @unittest. Skip ("I don ' t want to run this case.")
    def test_minus (self):
        self.assertequal (1, minus (3, 2))


Output:

Test_add (Test_mathfunc. Testmathfunc) ... ok
test_minus (test_mathfunc). Testmathfunc) ... skipped "I don ' t want to run this case."
Test_divide (Test_mathfunc. Testmathfunc) ... FAIL
 
======================================================================
fail:test_divide (test_ Mathfunc. Testmathfunc)
----------------------------------------------------------------------
traceback (most Recent call last):
  File "D:\pythonWorkspace\HTMLTest\test_mathfunc.py", line, in Test_divide
    Self.assertequal (2.5, Divide (5, 2))
assertionerror:2.5!= 2
 
---------------------------------------------- ------------------------
Ran 3 tests in 0.000s
 
FAILED (Failures=1, skipped=1)

There are three skip adorners

Unittest,skip (reason): Skip unconditionally

UNITTEST.SKIPIF (condition, reason): skipping when condition is true

Unittest.skipunless (condition, reason): skipping when condition is false


(2) testcase.skiptest () method

Class Testmathfunc (UnitTest. TestCase): ...
def test_minus (self):
        self.skiptest (' Don't run this. ')
        Self.assertequal (1, minus (3, 2))


Output:

Test_add (Test_mathfunc. Testmathfunc) ... ok
test_minus (test_mathfunc). Testmathfunc) ... skipped ' don't run this. '
Test_divide (Test_mathfunc. Testmathfunc) ... FAIL
 
======================================================================
fail:test_divide (test_ Mathfunc. Testmathfunc)
----------------------------------------------------------------------
traceback (most Recent call last):
  File "D:\pythonWorkspace\HTMLTest\test_mathfunc.py", line, in Test_divide
    Self.assertequal (2.5, Divide (5, 2))
assertionerror:2.5!= 2
 
---------------------------------------------- ------------------------
Ran 3 tests in 0.000s
 
FAILED (Failures=1, skipped=1)


Eight, use Htmltestrunner to output beautiful HTML reports

TXT format Text execution report too shabby, here we learn to generate HTML reports with the help of Htmltestrunner. First you need to download htmltestrunner.py, and put it in the current directory, or in the Python directory in the LIB, you can import the run.

Download Address: http://tungwaiyip.info/software/HTMLTestRunner.html

Modify the test_suite.py code as follows:

# coding=utf-8
 
import unittest from
test_mathfunc import testmathfunc from
htmltestrunner Import Htmltestrunner
 
 
If __name__ = = ' __main__ ':
    suite = UnitTest. TestSuite ()
 
    tests = [Testmathfunc ("Test_add"), Testmathfunc ("Test_minus"), Testmathfunc ("Test_divide")]
    Suite.addtests (Tests)
 
    with open (' htmlreport.html ', ' W ') as F:
        runner = Htmltestrunner (stream=f,
                                title = ' Mathfunc Test ",
                                description= ' generated by Htmltestrunner. ',
                                verbosity=2
                                )
        Runner.run ( Suite


After execution, the console output is as follows:

Ok Test_add (Test_mathfunc. Testmathfunc)
F  test_divide (test_mathfunc. Testmathfunc) Time
 
elapsed:0:00:00.001000

Generated HTML:

IX, Summary

1. UnitTest is a Python self-contained unit test framework that we can use as a framework for implementing use-case organizations for our automated test framework.

2, UnitTest process: Write good testcase, then by Testloader load TestCase to Testsuite, and then run Texttestrunner by Testsuite, The result of the run is saved in Texttestresult, and when we execute it through the command line or Unittest.main (), main will invoke run in Texttestrunner to execute, Or we can execute the use case directly through Texttestrunner.

3, a class inherits UnitTest. TestCase is a testcase in which the method that begins with test is loaded as a real testcase at load time.

4, the verbosity parameter can control the output of the execution result, 0 is the simple report, 1 is the general report, 2 is the detailed report.

5, you can add case or suite to the suite through Addtest and addtests, you can use the Testloader loadtestsfrom__ () method.

6. Use SetUp (), teardown (), SetupClass (), and Teardownclass () to lay out the environment before the use case is performed, and to clean up the environment after use case execution

7, we can skip a case through the skip,skipif,skipunless adorner, or use the Testcase.skiptest method.

8, the parameter adds stream, can output the report to the file: can use Texttestrunner output TXT report, and can use Htmltestrunner output HTML report.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.