Python3使用doctest对项目中的单个函数进行测试

因为最近项目处于刚开展阶段,所以需要写的项目公共函数比较多。既然是公共函数,那么必然决定了它的属性是相对比较独立、功能比较单一的,这种函数使用doctest模块来保证质量再好不过了。并且doctest还有一个更大的好处就是可以清晰的把可能出现的使用场景以文档的形式保存在注释中,如果后面因为需求变更修改代码的话,只需要重新执行一遍doctest即可确保变更不会影响先有功能。好了,闲话少说,上代码。

 

def check_license_number(license_number):
    """
    >>> check_license_number("粤B1234港")
    True
    >>> check_license_number("粤B123456")
    True
    >>> check_license_number("粤B123ddr")
    False
    >>> check_license_number("粤B123dd")
    True
    >>> check_license_number("粤B12345")
    True

    :param license_number:
    :return: True or False
    """

    if not license_number:
        return False

    max_chat_number = 0
    for chat in license_number:
        if chat in string.ascii_letters:
            max_chat_number += 1
    if max_chat_number > CONST.LICENSE_NUMBER_MAX_CHAT:
        return False

    if len(set(license_number).intersection(string.ascii_letters)) > CONST.LICENSE_NUMBER_MAX_CHAT:                                    # 车牌最多包含三个字母
        return False

    if license_number[-1:] in CONST.LICENSE_NUMBER_LAST_STRING_LIST:    # ['港', '澳', '学', '领']
        source_string = set(license_number[1:][:-1])
    else:
        source_string = set(license_number[1:])

    check_string = string.ascii_letters + string.digits
    if len(set(source_string).difference(check_string)) > 0:            # 除字母、数字、首尾两个汉字外不能包含特殊字符
        return False
    else:
        return True

 

代码是一段检验车牌有效性的函数,写好之后上网找了一些doctest的用法,发现主要是两种:

  1. 在代码文件中执行测试:if __name__ == '__main__': import doctest doctest.testmod(verbose=True)
  2. 在命令行中执行测试:python -m doctest -v utils.py

 

这两种测试执行方法都有一个共同点,就是都是对整个py文件的测试代码进行执行。因为我的代码属于项目中的模块,所以会调用一些公共的配置参数,这个时候显然是无法进行单文件执行的。那么上面两种方法是不能满足需求了,于是打开doctest.testmod函数的源码:

def testmod(m=None, name=None, globs=None, verbose=None,
            report=True, optionflags=0, extraglobs=None,
            raise_on_error=False, exclude_empty=False):
    """m=None, name=None, globs=None, verbose=None, report=True,
       optionflags=0, extraglobs=None, raise_on_error=False,
       exclude_empty=False

    Test examples in docstrings in functions and classes reachable
    from module m (or the current module if m is not supplied), starting
    with m.__doc__.

    Also test examples reachable from dict m.__test__ if it exists and is
    not None.  m.__test__ maps names to functions, classes and strings;
    function and class docstrings are tested even if the name is private;
    strings are tested directly, as if they were docstrings.

    Return (#failures, #tests).
    """
    pass

发现他的注释中有说明:

  • 参数“m”代表从哪个模块开始,没有的话默认当前模块
  • 参数“name”代表函数名,没有的话全文执行

有这两条的话基本就能满足我的需求了,然后打开Pycharm的Python Clonsole交互式命令行开始执行测试

>>> from common import utils
>>> import doctest

>>> doctest.testmod(utils, "check_license_number", verbose=True)
Trying:
    check_license_number("粤B1234港")
Expecting:
    True
ok
Trying:
    check_license_number("粤B123456")
Expecting:
    True
ok
Trying:
    check_license_number("粤B123ddr")
Expecting:
    False
ok
Trying:
    check_license_number("粤B123dd")
Expecting:
    True
ok
Trying:
    check_license_number("粤B123")
Expecting:
    True
ok
20 items had no tests:
    check_license_number
    check_license_number.ImageFileDispose
    check_license_number.ImageFileDispose.__init__
    check_license_number.ImageFileDispose.base64_to_image
    check_license_number.ImageFileDispose.image_to_base64
    check_license_number.ImageFileDispose.save_img
    check_license_number.OSSFileSDK
    check_license_number.OSSFileSDK.__init__
    check_license_number.OSSFileSDK.download_file
    check_license_number.OSSFileSDK.get_flow_file_postfix
    check_license_number.OSSFileSDK.get_local_file_postfix
    check_license_number.OSSFileSDK.get_new_file_name
    check_license_number.OSSFileSDK.get_sign_url
    check_license_number.OSSFileSDK.upload_file_bytes_file
    check_license_number.OSSFileSDK.upload_file_local_file
    check_license_number.OSSFileSDK.upload_file_network_flow
    check_license_number.check_mobile_phone
    check_license_number.reset_dup_wxuser_phone
    check_license_number.timestamp_format
    check_license_number.wechat_cookie
1 items passed all tests:
   5 tests in check_license_number.check_license_number
5 tests in 21 items.
5 passed and 0 failed.
Test passed.
TestResults(failed=0, attempted=5)

 

到这里,整个测试就执行成功了,后面可以随便折腾函数的功能而不用担心对函数功能有什么影响了。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值