Python 单元测试 & 文档测试

发布时间:2019-06-24 15:53:34编辑:auto阅读(1401)

    1.1   单元测试

    1.1.1   单元测试编写

    单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。

    编写一个Dict类,这个类的行为和dict一致,但是通过属性来访问。

    >>> d = Dict(a=1, b=2)

    >>> d['a']

    1

    >>> d.a

    1

    class dict编写如下:

    [root@daidai python]# cat mydict.py

    #!/usr/bin/python

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

     

    class Dict(dict):

       def __init__(self, **kw):

           super().__init__(**kw)

       def __getattr__(self, key):

           try:

               return self[key]

           except KeyError:

               raise AttributeError(r"'Dict' has no attribute %s." % key)

       def __setattr__(self, key, value):

           self[key] = value

    编写单元测试:

    [root@daidai python]# cat mydict_test.py

    #!/usr/bin/python

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

     

    import unittest

    from mydict import Dict

    class TestDict(unittest.TestCase):     #测试类从unittest.TestCase继承

       def test_init(self):            #不是test开头的方法不被执行

           d = Dict(a = 1, b = 'test')

           self.assertEqual(d.a, 1)

           self.assertEqual(d.b, 'test')

           self.assertTrue(isinstance(d, dict))

       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):  #通过d['empty']访问不存在的key时,断言会抛出KeyError

               value = d['empty']

       def test_attrerror(self):

           d = Dict()

            with self.assertRaises(AttributeError): #通过d.empty访问不存在的key时,我们期待抛出AttributeError

               value = d.empty

     

    if __name__ == '__main__':

    unittest.main()     #运行单元测试

    1.1.2   运行单元测试

    [root@daidai python]# python mydict_test.py #加上unittest.main()运行语句

    .....

    ----------------------------------------------------------------------

    Ran 5 tests in 0.001s

     

    OK

    [root@daidai python]#

    [root@daidai python]#

    [root@daidai python]# python -m unittest mydict_test  #不用加上unittest.main()运行语句

    .....

    ----------------------------------------------------------------------

    Ran 5 tests in 0.001s

     

    OK

    1.1.3   setUp() & tearDown()

    这两个方法分别在单元测试中每个测试方法的前后被执行。

    [root@daidai python]# cat mydict_test.py

    #!/usr/bin/python

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

     

    import unittest

    from mydict import Dict

    class TestDict(unittest.TestCase):

        def setUp(self):

            print('test begins...')

       def test_init(self):

           d = Dict(a = 1, b = 'test')

           self.assertEqual(d.a, 1)

           self.assertEqual(d.b, 'test')

           self.assertTrue(isinstance(d, dict))

       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):

               value = d['empty']

       def test_attrerror(self):

           d = Dict()

           with self.assertRaises(AttributeError):

               value = d.empty

        def tearDown(self):

            print('test ends...')

     

    #if __name__ == '__main__':

    #   unittest.main()

    [root@daidai python]# pythonmydict_test.py    #发现这样测试没有作用

    [root@daidai python]# python -m unittestmydict_test

    test begins...

    test ends...

    .test begins...

    test ends...

    .test begins...

    test ends...

    .test begins...

    test ends...

    .test begins...

    test ends...

    .

    ----------------------------------------------------------------------

    Ran 5 tests in 0.001s

     

    OK

    1.2   文档测试

    当我们编写注释时,如果写上这样的注释:

     

    def abs(n):

       '''

       Function to get absolute value of number.

     

       Example:

     

       >>> abs(1)

        1

       >>> abs(-1)

        1

       >>> abs(0)

        0

       '''

       return n if n >= 0 else (-n)

    无疑更明确地告诉函数的调用者该函数的期望输入和输出。

     

    并且,Python内置的“文档测试”(doctest)模块可以直接提取注释中的代码并执行测试。

     

    doctest严格按照Python交互式命令行的输入和输出来判断测试结果是否正确。只有测试异常的时候,可以用...表示中间一大段烦人的输出。

     

    让我们用doctest来测试上次编写的Dict类:

     

    # mydict2.py

    class Dict(dict):

       '''

       Simple dict but also support access as x.y style.

     

       >>> d1 = Dict()

       >>> d1['x'] = 100

       >>> d1.x

       100

       >>> d1.y = 200

       >>> d1['y']

       200

       >>> d2 = Dict(a=1, b=2, c='3')

       >>> d2.c

       '3'

       >>> d2['empty']

       Traceback (most recent call last):

           ...

       KeyError: 'empty'

       >>> d2.empty

       Traceback (most recent call last):

           ...

       AttributeError: 'Dict' object has no attribute 'empty'

       '''

       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

     

    if __name__=='__main__':

       import doctest

       doctest.testmod()

    运行python3 mydict2.py

     

    $ python3 mydict2.py

    什么输出也没有。这说明我们编写的doctest运行都是正确的。如果程序有问题,比如把__getattr__()方法注释掉,再运行就会报错:

     

    $ python3 mydict2.py

    **********************************************************************

    File "/Users/michael/Github/learn-python3/samples/debug/mydict2.py",line 10, in __main__.Dict

    Failed example:

       d1.x

    Exception raised:

       Traceback (most recent call last):

         ...

       AttributeError: 'Dict' object has no attribute 'x'

    **********************************************************************

    File"/Users/michael/Github/learn-python3/samples/debug/mydict2.py", line16, in __main__.Dict

    Failed example:

       d2.c

    Exception raised:

       Traceback (most recent call last):

         ...

       AttributeError: 'Dict' object has no attribute 'c'

    **********************************************************************

    1 items had failures:

       2of   9 in __main__.Dict

    ***Test Failed*** 2 failures.

    注意到最后3行代码。当模块正常导入时,doctest不会被执行。只有在命令行直接运行时,才执行doctest。所以,不必担心doctest会在非测试环境下执行。


关键字