doctest --- 一个改善python代码质量的工具

简介

  说实话吧,之前一直没有怎么重视给自己的代码加上测试逻辑;也就是说我只是写了代码,但是并没有给自己的代码加上测试代码;

  整个过程就是写完后自己测试一下,看一下跑出来的结果是正确的就心满意足了。过一段时间之后总是对自己的代码有一种陌生感,

  就算有完好的注释,我也不能100%保证它的功能上是OK的。

 

  一方面是对于功能上的细节我已经忘记的差不多了,另一方面就算是有注释我也要看上一会才能回想起自己当初是怎么想的,大声

  的说出我的代码没有问题确实是一件比较难的事。

 

给自己的代码加上测试代码的必要性

  1、一种态度问题,就我现在而言不给自己的代码加上测试代码是对质量的不负责任;我希望自己尽可能的生成出没有Bug的代码

  然而给代码加上测试代码就是一个比较好的解决方案

 

  2、虽然给代码加上测试代码会用到更多的人天,但是对于一个大点的项目来说它更加的可按;也就是说当我改动现有代码或增加

  新的功能的时候是不是会引发bug,我们只要跑一遍测试用例,如果测试用例都能通过那么说明是OK的,如果有用例没有通过这个

  时候开发人员就可以自己查了,不用等到测试发现之后再报给我们。

 

  3、总的来说给自己的代码加上测试代码,这会使我对自己的 代码|项目 更加的放心

 

doctest模块的功能

  doctest模块会读取python代码中的文档字符串,并按文档字符串中的内容来运行测试逻辑;那我们的测试逻辑怎么加到文档字符串

  中去呢?这个doctest已经帮我们想好了,开发工程师只要把python交互式下的内容写入到文档字符串中就行了。

 

doctest使用举例

  一个简单的选择排序算法为例子

def select_sort(lst):
    """
    选择排序算法
    """
    for i in range(0,len(lst)):
        min_item_index = i
        for j in range(i,len(lst)):
            if lst[j] < lst[min_item_index]:
                min_item_index = j
        if min_item_index != i:
            lst[min_item_index],lst[i] = lst[i],lst[min_item_index]

  

  可以看到的代码只提供了一个简单的文档字符串,用来说明了一下这个函数的作用。那我们怎么给这个方法加上测试代码呢?

  事实上这个就是从简单的手工测试(工程师自己在python交互式模式下测试自己的代码)演化而来的,假设工程是在交互模式下

  测试了三个用例

>>> from selectsort import select_sort
>>> lst = [3,2,1,4,5,6,-1]
>>> select_sort(lst)
>>> lst
[-1, 1, 2, 3, 4, 5, 6]
>>> 
>>> lst = [2,1]
>>> select_sort(lst)
>>> lst
[1, 2]
>>> 
>>> lst = [0]
>>> select_sort(lst)
>>> lst
[0]

  

  doctest只要求我们把复制到文件字符串中就行了,当然啦还是另外加两行代码不过这个是死的,记下来就是了

def select_sort(lst):
    """
    选择排序算法

    >>> lst = [3,2,1,4,5,6,-1]
    >>> select_sort(lst)
    >>> lst
    [-1, 1, 2, 3, 4, 5, 6]
    >>> 
    >>> lst = [2,1]
    >>> select_sort(lst)
    >>> lst
    [1, 2]
    >>> 
    >>> lst = [0]
    >>> select_sort(lst)
    >>> lst
    [0]
    """
    for i in range(0,len(lst)):
        min_item_index = i
        for j in range(i,len(lst)):
            if lst[j] < lst[min_item_index]:
                min_item_index = j
        if min_item_index != i:
            lst[min_item_index],lst[i] = lst[i],lst[min_item_index]


if __name__ == "__main__":
    import doctest
    doctest.testmod()

 

  可以看到最后三行表示当我们单独运行这个文件的时候就执行测试,那我测试下看看

python3 selectsort.py -v
Trying:
    lst = [3,2,1,4,5,6,-1]
Expecting nothing
ok
Trying:
    select_sort(lst)
Expecting nothing
ok
Trying:
    lst
Expecting:
    [-1, 1, 2, 3, 4, 5, 6]
ok
Trying:
    lst = [2,1]
Expecting nothing
ok
Trying:
    select_sort(lst)
Expecting nothing
ok
Trying:
    lst
Expecting:
    [1, 2]
ok
Trying:
    lst = [0]
Expecting nothing
ok
Trying:
    select_sort(lst)
Expecting nothing
ok
Trying:
    lst
Expecting:
    [0]
ok
1 items had no tests:
    __main__
1 items passed all tests:
   9 tests in __main__.select_sort
9 tests in 2 items.
9 passed and 0 failed.
Test passed.

  

  最后一行的 "Test passed" 表示测试通过了,之所以有这么多输出是因为我们加了 -v 参数,不加这个的话就是真正的linux哲学了

  “没有输出就是最好的输出”

yifengliu-nb:sorts jianglexing$ python3 selectsort.py 
yifengliu-nb:sorts jianglexing$ 
yifengliu-nb:sorts jianglexing$ 

 

总结

  python中还有一个专门用于单元测试的unittest框架,这个相比doctest来说要强大不少,一次再说吧!

      https://www.sqlpy.com

 

---

posted on 2019-01-26 16:50  蒋乐兴的技术随笔  阅读(508)  评论(0编辑  收藏  举报

导航