Python 性能比较和做函数级单元测试的方法

这是从python的docs文档中摘录出来的两小节,以后再写python代码肯定会经常用到,下面总结部分都是自己写的。

性能度量

有些用户对了解解决同一问题的不同方法之间的性能差异很感兴趣。Python 提供了一个度量工具,为这些问题提供了直接答案。

例如,使用元组封装和拆封来交换元素看起来要比使用传统的方法要诱人的多。 timeit 证明了后者更快一些:

>>> from timeit import Timer
>>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
0.57535828626024577
>>> Timer('a,b = b,a', 'a=1; b=2').timeit()
0.54962537085770791

相对于 timeit 的细粒度,profile 和 pstats 模块提供了针对更大代码块的时间度量工具。

总结: 对于行级别代码,用timer比较性能是可以的,但是对于模块级别的,还是得用profile

质量控制

开发高质量软件的方法之一是为每一个函数开发测试代码,并且在开发过程中经常进行测试。

doctest 模块提供了一个工具,扫描模块并根据程序中内嵌的文档字符串执行测试。测试构造如同简单的将它的输出结果剪切并粘贴到文档字符串中。通过用户提供的例子,它发展了文档,允许 doctest 模块确认代码的结果是否与文档一致:

def average(values):
    """Computes the arithmetic mean of a list of numbers. >>> print(average([20, 30, 70])) 40.0 """
    return sum(values, 0.0) / len(values)

import doctest
doctest.testmod()   # automatically validate the embedded tests

总结:这是非常好的一个写函数级别单元测试用例的方法,有这个功能,如果测试用例写得好,可能再也不用担心修改引入新的问题了,这个测试用例没跑过,程序根本run不起来。只能说当初想到这办法的人挺牛的。

我把文档字符串中的测试用例改成了 print(average([10, 30, 70]))。run的时候报下面的错误。

**********************************************************************
File "F:/Forwork/pythonprj/sendmail", line 4, in __main__.average
Failed example:
 print(average([10, 30, 70]))
Expected:
 40.0
Got:
 36.6666666667
**********************************************************************
1 items had failures:
   1 of   1 in __main__.average
***Test Failed*** 1 failures.

unittest 模块不像 doctest 模块那么容易使用,不过它可以在一个独立的文件里提供一个更全面的测试集:

import unittest

class TestStatisticalFunctions(unittest.TestCase):

    def test_average(self):
        self.assertEqual(average([20, 30, 70]), 40.0)
        self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
        self.assertRaises(ZeroDivisionError, average, [])
        self.assertRaises(TypeError, average, 20, 30, 70)

unittest.main() # Calling from the command line invokes all tests

总结:个人认为,doctest 那种方法用来做函数级别的单元测试非常好,unittest用来做模块、特性级别的功能测试更加合适。

你可能感兴趣的:(python)