• 自底向上的单元测试&&程序设计思想


    自底向上的单元测试

    • 方法
      • 先对最底层基本单元进行测试,模拟调用该单元的单元做驱动模块。然后再对上面一层进行测试,用下面已被测试过的单元做桩模块。依此类推,直到测试完所有单元。
    • 优点
      • 在集成测试前提供系统早期的集成途径。不需要开发桩模块。
    • 缺点
      • 随着测试的进行,测试过程越来越复杂。
    • 总结
      • 比较合理的单元测试策略,但测试周期较长。

    自底向上实现与单元测试

    自顶向下设计设计是创建层次化的模块结构的过程,而从实现的角度看,我们又是采取了相反的过程,即自底向上的实现。从结构图的底层开始实现每一个函数,然后上一层模块 自然得到实现。就这样自底向上,直至主程序得到完全的实现。

    在模块化编程中,测试程序最适合采用单元测试技术,即先分别测试每一个小模块,然 后再逐步测试较大的模块,直至最后测试完整程序。以 calendar 程序为例,当我们实现了 days(y,m)函数后,就应该来测试此函数是否能完成预定的功能——返回 y 年 m+1 月有多 少天。我们可以将 days(y,m)的定义存入一个模块文件(假设文件名是 moduletest.py), 然后导入该文件并测试函数。下面是测试 days 函数的一个会话过程:

    >>> from moduletest import days
    >>> days(1900,0)
    31
    >>> days(1900,1)
    28
    >>> days(1900,11)
    31
    >>> days(2000,1)
    29
    >>> days(2012,1)
    29
    >>> days(2012,10)
    30


    注意,测试时应当使测试数据尽量覆盖所有关键情形。在我们的测试例子中,测试了合 法数据的边界情形 1900 年 1 月,也测试了 1900 年 2 月(这个年份虽然能被 4 整除但却不是闰年),还测试了 2000 年(能被 400 整除)是否闰年。所有测试结果都表明这个函数实现正 确。

    单元测试技术独立地测试每一个函数,这样能更容易定位程序错误。如果较小模块都正 确,那么由它们组成的较大模块出现错误的可能性也就较小。最终测试完整程序时,就更有 希望通过测试。

    最后,为了完整起见,我们将前面所有的代码汇集起来列在下面。

    【程序 4.8】calendar.py

    # calendar.py
    def getYear():
        print "This program prints the calendar of a given year." 
        year = input("Please enter a year (after 1900): ")
        return year
    def firstDay(year):
        k = leapyears(year)
        n = (year - 1900) * 365 + k return (n + 1) % 7
    def leapyears(year): count = 0
        for y in range(1900,year):
            if y%4 == 0 and (y%100 != 0 or y%400 == 0): 
                count = count + 1
        return count
    def printCalendar(year,w): print
        print "=========== " + str(year) + " =========="
        first = w
        for month in range(12):
            heading(month)
            first = oneMonth(year,month,first)
    def heading(m):
        months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sept","Oct","Nov","Dec"]
        print " %s " % (months[m]) 
        print "Mon Tue Wed Thu Fri Sat Sun"
    def oneMonth(year,month,first): d = days(year,month)
        frame = layout(first,d) 
        printMonth(frame) return (first + d) % 7
    def days(y,m):
        month_days = [31,28,31,30,31,30,31,31,30,31,30,31]
        d = month_days[m]
        if (m == 1) and (y%4 == 0 and (y%100 != 0 or y%400 == 0)): 
            d = d + 1
        return d
    def layout(first,d): frame = 42 * [""] 
        if first == 0:
            first = 7 
        j = first - 1
        for i in range(1,d+1): 
            frame[j] = i
            j = j + 1 
        return frame
    def printMonth(frame): 
        for i in range(42):
            print "%3s" % (frame[i]), 
            if (i+1)%7 == 0:
                print
    def main():
        year = getYear()
        w = firstDay(year) 
        printCalendar(year,w)
    main()
    

    4.3.5 开发过程小结

    calendar 程序的完整开发过程,展示了自顶向下设计方法的强大能力。当面临一个复杂 问题而感到无从下手的时候,可以尝试将原始问题分解为若干个子问题,然后再去考虑每个 子问题的解决方案。这个分解过程可以重复进行,从结构图的顶层开始,自顶向下逐步求精, 直至得到所有子问题的精确代码。

    自顶向下设计过程可以概括为以下四个步骤:

    (1)将问题分解为若干子问题;

    (2)为每个子问题设计一个函数接口;

    (3)将原问题的算法用各子问题对应的函数接口来表达;

    (4)对每个子问题重复(1)~(3)的过程。 经过以上步骤,高层的抽象接口在低层逐步得到细化,最终到达可以直接用 Python 基

    本语句实现的层次。 自顶向下设计是编写复杂程序的重要工具,虽然这种方法会导致很多小模块(函数),看上去设计起来有点麻烦,但这其实是事半而功倍的方法。事实上不采用模块化方法是不可 能设计出复杂系统的。

    模块化设计和单元测试都是分离关注点原则的具体体现,前者使我们能够设计复杂程 序,后者使我们能够调试复杂程序。作为初学者,应当不断地实践模块化方法,让模块化思 想和方法变成自己的本能思维方式。

     
  • 相关阅读:
    python字符串
    Python问题:SyntaxError: Non-ASCII character 'xe2' in file
    windows 运行库与dll文件
    sublime python 配置内容
    sublime ctrl b突然不能用解决方法
    c++ primer 的 textquery 例子。
    虚函数表
    理解各种数据类型和简单类在内存中的存在形式。
    最短路径纯贪心算法。
    中缀表达式生成二叉树
  • 原文地址:https://www.cnblogs.com/ldphoebe/p/14849642.html
Copyright © 2020-2023  润新知