15.6 自动化集成和性能测试

    我们可以使用unittest包对那些不是单独的类定义进行测试。如之前所介绍的,可以使用unittest来对一个由多个集成的组件组成的单元进行自动化测试,仅当软件中每个隔离的组件都已经通过了单元测试时,才进行这样的集成测试。当一个组件没有通过单元测试时,去调试一个失败的集成测试是没有意义的。

    性能测试可以在多个集成的层面上被完成。对于大应用来说,对整个系统进行性能测试不会带来太多好处。有一种传统的观点是,一个程序中10%的代码占了整个执行时间的90%。因此,我们不必要对整个系统进行优化,我们只需要对造成性能瓶颈的部分进行评测。

    在一些情况下,我们有一个用于搜索的数据结构。移除这个搜索会带来显著的性能提升。正如我们在第5章“可调用对象和上下文的使用”中实现记忆化可以带来显著的性能提升,因为避免了重复计算。

    为了执行正确的性能测试,需要遵照以下3个步骤。

    • 通过结合使用设计审查与代码分析来找出可能对应用造成性能问题的部分。Python标准库中有两个分析模块。除非有复杂的需求,cProfile才会对应用需要关注的部分进行查找。
    • 使用unittest创建一个自动化测试场景来展示任何实际中的性能问题。使用timeit或time.perf _ counter()来收集性能数据。
    • 对选择的测试用例代码进行优化,直到性能满意为止。

    目的是为了尽可能多的自动化,并避免为了带来性能的提升对代码进行模糊意义的修改。大多数情况下,对核心数据结构或算法(或两者)进行修改会导致大规模的重构。自动化测试会使得大规模重构更实际。

    一个尴尬的情形是性能测试中缺少一个具体的合格与否的标准。在没有对“足够快”下定义时,让程序更快些可能是必要的。当有评测性能的标准时,事情总会容易一些,性能测试可以用来衡量结果是否正确的同时运行时间能否接受。

    可以使用以下代码进行性能测试。

    import unittest
    import timeit
    class Test_Performance( unittest.TestCase ):
      def test_simpleCalc_shouldbe_fastEnough( self ):
         t= timeit.timeit(
         stmt="""RateTimeDistance( rate=1, time=2 )""",
         setup="""from p1_c03 import RateTimeDistance"""
         )
         print( "Run time", t )
         self.assertLess( t, 10, "run time {0} >= 10".format(t) )

    以上代码使用了unittest来完成自动化性能测试。因为timeit模块对指定语句执行了1000000次,这样可以使得测试结果更准确。

    在之前的例子中,每个RTD结构的执行时间需要小于1/100000秒,执行1000000次应该小于10秒。