zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Python Unit Test - 4 pyunit

Python test unit
2023-09-14 09:10:54 时间

pyunit,Python Unit Test Framework
更多的关于TestCase、TestLoader、TestResult的内容,参考 https://docs.python.org/3/library/unittest.html)。
关于python unit架构,参考 https://blog.csdn.net/u012841352/article/details/71511890,Unit Test图示。

1. 基本框架 puthon unit test framework

  • test fixture,测试准备
    测试执行准备。包括相关的清理(cleanup)或 环境/数据初始化。 -- setup,teardown 和 __init__(),每个测试方法执行一次
  • test case,测试用例
    创建测试用例。为了某个特定目的,设计和执行测试数据、测试步骤,验证输出结果是否满足特定响应,断言(assert)。 -- pyunit的所有测试用例方法必须以 “test_“ ”开头
  • test suite,测试套件
    测试套件。为了某种测试目的,将一系列测试用例 或 测试套件组合在一起执行,类似文件夹。-- 调用 unittest.TestCase 创建基本的test case 
  • test runner,测试执行
    测试执行。执行测试用例 或 测试套件,输出测试结果,并对结果的正确性进行判断(assert),以文本 或 图表形式对测试结果进行整理、分析,生成测试报告。-- unittest TestLoader

2. Unit 文件构成

async_case.py
case.py       #测试用例
loader.py     #加载 test case 和 test suite
main.py
mock.py       #使用mock(模拟)对像替代系统的某些部分,并对结果断言
result.py     #测试结果
runner.py     #执行测试并显示测试结果 -- 据此可扩展pyunit测试报告
signals.py
suite.py      #测试套件
util.py

>> 由Unit Test Case构成的pyunit
     
test setup -> test method -> test teardown => call unit test

Import unitttest

# create test case
Class test_class_name(unittest.TestCase):

    #preparation and clean test environment, must be repeated
    Def setUp(self):  #准备测试数据和测试环境,测试用例执行前执行;如果发生错误,其他测试方法均不会执行 
        pass

    # create test method
	Def test_caseName(self):         #测试用例方法,必须以 test_ 开头
		Self.assert…()

    # run after test method run
	Def tearDown(self): #run after setup is success      #清理环境,恢复最初测试状态;测试用例执行完成 或 测试执行失败后执行(只要setup执行成功,teardown一定会执行)
        pass

if __name__ = "__main__":
	unitest.main()         # runner, 测试用例方法执行

>> 由Unit Test Suit构成的pyunit

Import unitttest

# create test case
Class test_class_name(unittest.TestCase):

    #preparation and clean test environment, must be repeated
    Def setUp(self):   
        pass

    # create test method
	Def test_caseName(self): 
		Self.assert…()

    # run after test method run
	Def tearDown(self): #run after setup is success 
        pass

def suite():          #将测试用例组合到一测试套件,完成某种测试验证需求
    suite = unittest.TestSuite()
    suite.addTest(('test_caseName'))
    return suite

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(suite())

>> 代码样例(以下基于此方法进行unit test编写)

import unittest

def pyjiou(n):
    if(n%2 == 0):
        print("ou shu")
        return "ou shu"
    else:
        print("ji shu")
        return "ji shu" 

def py10(n):
    if(n < 10):
        print("less 10")
        return "less 10"
    else:
        print("big 10")
        return "big 10"

3. Python Unit module

 
'''
python unit test module, 2 class with 4 test methods with 7 assert(3 pass, 4 fail)
1. functest class with 3 test methods(6 assert: 3 pass, 3 fail) and setup, teardown
2. ft class with 1 test method(1 assert: 1 fail)
'''
class functest(unittest.TestCase):

    def setUp(self):
        print("test start -- : ")

    def test_jiou(self):
        print("method 1: test_jiou")
        self.assertEqual(pyjiou(4),"ou shu")    #pass
        self.assertEqual(pyjiou(5),"ou shu")    #fail

    def test_py10(self):
        print("method 2: test_py10")
        self.assertEqual(py10(4),"less 10")     #pass
        self.assertEqual(py10(4),"big 10")      #fail

    def test_other(self):
        print("method 3: test_other")
        self.assertEqual('sup'.upper(),'SUP')   #pass
        self.assertTrue('sup'.isupper())        #fail

    def tearDown(self):
        print(" -- test end \n")

class ft(unittest.TestCase):

    def test_data(self):
        print("method 4: test_data")
        self.assertEqual(pyjiou(1),"ou shu")    #fail

4. Runner 测试执行

  • python unit 文件中调用 test method 和 test suite
###call unit test case
if __name__ == "__main__":  
    unittest.main()                             # call unit test

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
###add test metho into test suite
def suite_all():                                # merge test methods into test suite
    suite = unittest.TestSuite()
    suite.addTest(functest('test_jiou'))
    suite.addTest(functest('test_py10'))
    suite.addTest(functest('test_other'))
    return suite

#call unit test suite
if __name__ == "__main__":  
    runner = unittest.TextTestRunner()        # call unit test suite
    runner.run(suite_all())
  •  命令行调用 test method 和 test suite
python -m unittest     #pyunit 基本命令

python -m unittest test_module1 test_module2   #执行多个指定文件中的unit method
python -m unittest test_module.TestClass       #执行指定类中的unit metho
python -m unittest test_module.TestClass.test_method    #执行指定类中的某个特定的test method

python -m unittest -v test_module    #执行指定文件中的unit method,并输出详细测试结果

python -m unittest discover -s project_directory -p "*_test.py"  #执行指定文件夹下(-s)的所有以test结尾的unit method
python -m unittest discover -t project_directory "*_test.py"     #执行指定文件夹的顶层目录(-t)的所有以test结尾的unit method

# discover参数用来在指定目录下检出特定的unit method并执行测试

>> 测试结果
     说明:
     1)test method执行顺序:按class 和 method 名称的ascii排序
     2)Ftest start:F - False,E - Error,. - Pass       
           more:也许你会发现这种标识(F, E, .),输出时有错位

====================== RESTART: D:\Project\python\punit.py =====================
method 4: test_data
ji shu                         
Ftest start -- :               # each method with setup & tear down 
method 1: test_jiou
ou shu                         
ji shu
 -- test end 

Ftest start -- :  
method 3: test_other             
 -- test end 

Ftest start -- :               
method 2: test_py10
less 10
less 10
 -- test end 

F                                       ####### fail method from this 
======================================================================
FAIL: test_data (__main__.ft)              # method 1 
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".\punit.py", line 45, in test_data
    self.assertEqual(pyjiou(1),"ou shu")    #fail
AssertionError: 'ji shu' != 'ou shu'
- ji shu
+ ou shu


======================================================================
FAIL: test_jiou (__main__.functest)          # method 2
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".\punit.py", line 29, in test_jiou
    self.assertEqual(pyjiou(5),"ou shu")    #fail
AssertionError: 'ji shu' != 'ou shu'
- ji shu
+ ou shu


======================================================================
FAIL: test_other (__main__.functest)          # method 3
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".\punit.py", line 37, in test_other
    self.assertTrue('sup'.isupper())        #fail
AssertionError: False is not true

======================================================================
FAIL: test_py10 (__main__.functest)          # method 4
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".\punit.py", line 33, in test_py10
    self.assertEqual(py10(4),"big 10")      #fail
AssertionError: 'less 10' != 'big 10'
- less 10
+ big 10


----------------------------------------------------------------------
Ran 4 tests in 0.065s                       # 4 test method    

FAILED (failures=4)                         # 4 fail

5. 测试断言(test assert)-- 未全部使用

MethodChecks that
assertEqual(a, b)a == b
assertNotEqual(a, b)a != b
assertTrue(x)bool(x) is True
assertFalse(x)bool(x) is False
assertIs(a, b)a is b
assertIsNot(a, b)a is not b
assertIsNone(x)x is None
assertIsNotNone(x)x is not None
assertIn(a, b)a in b
assertNotIn(a, b)a not in b
assertIsInstance(a, b)isinstance(a, b)
assertNotIsInstance(a, b)not isinstance(a, b)
assertRaises(exc, fun, *args, **kwds)fun(*args, **kwds) raises exc
assertRaisesRegex(exc, r, fun, *args, **kwds)fun(*args, **kwds) raises exc and the message matches regex r
assertWarns(warn, fun, *args, **kwds)fun(*args, **kwds) raises warn
assertWarnsRegex(warn, r, fun, *args, **kwds)fun(*args, **kwds) raises warn and the message matches regex r
assertLogs(logger, level)The with block logs on logger with minimum level
assertAlmostEqual(a, b)round(a-b, 7) == 0
assertNotAlmostEqual(a, b)round(a-b, 7) != 0
assertGreater(a, b)a > b
assertGreaterEqual(a, b)a >= b
assertLess(a, b)a < b
assertLessEqual(a, b)a <= b
assertRegex(s, r)r.search(s)
assertNotRegex(s, r)not r.search(s)
assertCountEqual(a, b)a and b have the same elements in the same number, regardless of their order.
assertMultiLineEqual(a, b)strings
assertSequenceEqual(a, b)sequences
assertListEqual(a, b)lists
assertTupleEqual(a, b)tuples
assertSetEqual(a, b)sets or frozensets
assertDictEqual(a, b)dicts