zoukankan      html  css  js  c++  java
  • 9、pytest -- 集成文档测试

    1. 集成doctest模块

    doctestpython内置的一个标准库,它可以查找代码中类似交互式会话形式的注释,并检查它们是否正确;

    1.1. 通过指定文本文件的方式

    默认情况下,pytest会自动收集所有名称匹配test*.txt规则的文件,并调用doctest执行它们;

    下面,我们来看一个简单的例子:

    # src/chapter-9/test_example.txt
    
    >>> x = 3
    >>> x
    3
    

    直接使用pytest命令就可以执行它:

    λ pipenv run pytest src/chapter-9/test_example.txt
    ====================== test session starts ======================= 
    platform win32 -- Python 3.7.3, pytest-5.1.3, py-1.8.0, pluggy-0.13.0
    rootdir: D:Personal FilesProjectspytest-chinese-doc
    collected 1 item
    
    srcchapter-9	est_example.txt .                            [100%]
    
    ======================= 1 passed in 0.03s ========================
    

    我们也可以使用命令行选项--doctest-glob添加文件名称的匹配规则;

    例如,匹配rst格式的文件:

    pytest --doctest-glob='*.rst'
    

    注意:--doctest-glob可以多次指定,它们之间是或者的关系,并且依旧支持默认的test*.txt规则;

    1.1.1. 文本文件的编码

    doctest文件的默认编码是UTF-8,你可以在pytest.ini中使用doctest_encoding选项指定新的编码;例如,使用latin1编码:

    [pytest]
    doctest_encoding = latin1
    

    1.2. 通过编写文档字符串的方式

    除了文本文件外,pytest还支持检查文档字符串中的注释;例如:

    # src/chapter-9/test_module.py
    
    def something():
        '''文档字符串示例
        
        >>> something()
        42
        '''
        return 42
    
    
    def test_module():
        assert something() == 42
    

    执行时,需要添加--doctest-modules命令行选项:

    λ pipenv run pytest --doctest-modules src/chapter-9/test_module.py
    ====================== test session starts ======================= 
    platform win32 -- Python 3.7.3, pytest-5.1.3, py-1.8.0, pluggy-0.13.0
    rootdir: D:Personal FilesProjectspytest-chinese-doc
    collected 2 items
    
    srcchapter-9	est_module.py ..                             [100%]
    
    ======================= 2 passed in 0.03s ========================
    

    --doctest-modules会查找所有名称匹配*.py的文件,收集文档字符串中类似交互式会话形式的注释,并把每一个文档字符串作为一个用例来执行,所以上面我们执行了两个测试,其中一个是文档测试;

    如果想让pytest --doctest-modules正确收集到相关注释,需满足以下条件:

    • 文件名称符合*.py规则,但无需满足test_*.py或者*_test.py规则;
    • 文档字符串中的注释必须是类似python交互式会话形式的注释;

    如果你不想每次执行都指定--doctest-modules选项,可以考虑在pytest.ini中添加如下配置:

    [pytest]
    addopts = --doctest-modules
    

    文档字符串是一个多行字符串,使用'''或者"""包裹;一般推荐形式为,第一行简述功能,第二行空行,第三行具体描述;

    并且,可以通过__doc__属性访问它;例如,上面例子的__doc__属性为:

    >>> print(something.__doc__)
    文档字符串示例
    
        >>> something()
        42
    

    1.3. 指定额外的选项

    1.3.1. doctest标准库自带的选项

    pythondoctest标准库自带一些选项,用于定义文档测试的模式,我们同样可以在pytest.ini中使用这些功能;例如,忽略尾随的空格:

    # src/chapter-9/pytest.ini
    
    doctest_optionflags = NORMALIZE_WHITESPACE
    

    另外,你也可以在行注释中使能这些选项;

    例如,使用# doctest: +NORMALIZE_WHITESPACE同样能忽略尾随的空格:

    def something():
        '''文档字符串示例
        
        >>> something()  # doctest: +NORMALIZE_WHITESPACE
        42 
        '''
        return 42
    

    更多细节可以参考:https://docs.python.org/3/library/doctest.html#option-flags

    1.3.2. pytest自有的选项

    ALLOW_BYTES:在输出时,剔除字符串的b前缀;例如,以下文档测试是成功的:

    # src/chapter-9/options.py
    
    def str_bytes():
        '''返回字节编码
    
        >>> str_bytes()  # doctest: +ALLOW_BYTES
        'bytes'
        ''' 
        return b'bytes'
    

    ALLOW_UNICODE:相似的,在输出时,剔除字符串的u前缀;

    NUMBER:为了避免出现以下导致测试失败的情况:

    Expected:
        3.14
    Got:
        3.141592653589793
    

    我们可以通过配置NUMBER选项,只比较列出的精度:

    # src/chapter-9/options.py
    
    def number():
        '''浮点数的精度
    
        >>> import math
        >>> math.pi  # doctest: +NUMBER
        3.14 
        '''
        return 1
    

    注意:我们并不建议在全局使能NUMBER选项,因为它会修改输出中所有的浮点数的精度,甚至是在字符串或者列表中;

    例如,以下文档测试也是成功的:

    # src/chapter-9/options.py
    
    def str_number():
        '''浮点数字符串的精度
    
        >>> str_number()  # doctest: +NUMBER
        '3.14' 
        '''
        return '3.1415'
    

    2. 失败时继续执行

    默认情况下,对于一个给定的文档测试,pytest在遇到第一个失败点时退出执行;但是,我们可以通过--doctest-continue-on-failure命令行选项,让其继续执行;

    例如,对于以下文档字符串,包含两个测试点,pytest --doctest-continue-on-failure会报告两个错误(默认只会报告第一个错误):

    def str_bytes():
        '''返回字节编码
    
        >>> str_bytes()  
        'bytes' 
        >>> import math
        >>> math.pi  
        3.14 
        ''' 
        return b'bytes'
    

    3. 指定输出的格式

    文档测试失败时,你可以通过以下方式更改测试输出的格式:

    pytest --doctest-modules --doctest-report none
    pytest --doctest-modules --doctest-report udiff
    pytest --doctest-modules --doctest-report cdiff
    pytest --doctest-modules --doctest-report ndiff
    pytest --doctest-modules --doctest-report only_first_failure
    

    更多细节可以参考:https://docs.python.org/3/library/doctest.html#doctest.REPORT_UDIFF

    4. 文档测试中使用fixture

    通过getfixture可以让你在文档字符串中使用fixture

    >>> tmp = getfixture('tmpdir')
    >>> ...
    >>>
    

    5. 文档测试的命名空间

    doctest_namespace fixture可以用于向运行doctest测试的命名空间中注入一些信息,它是一个标准的字典对象;

    例如,我们在conftest.py中定义一个方法,注入到doctest的命名空间中:

    # src/chapter-9/conftest.py
    
    import pytest
    
    
    def func():
        return 42
    
    
    @pytest.fixture(autouse=True)
    def add_func(doctest_namespace):
        doctest_namespace['function'] = func
    

    可以在文档字符串中直接使用它:

    # src/chapter-9/func.txt
    
    >>> function()
    42
    

    6. 跳过文档测试

    pytest 4.4版本新增功能

    我们可以通过pytest.skip跳过文档测试;例如,跳过Windows系统上的文档测试:

    >>> import sys, pytest
    >>> if sys.platform.startswith('win'):
    ...     pytest.skip('this doctest does not work on Windows')
    >>> function()
    42
    

    GitHub仓库地址:https://github.com/luizyao/pytest-chinese-doc

  • 相关阅读:
    通过HOOK控制进程的创建
    进程退出前删除自身EXE
    Unicode(UTF&UCS)深度历险
    《12个有趣的C语言问答》评析2
    float的深入剖析
    UML六种关系
    socket1
    ios学习之常见问题记录
    栈和队列总结篇
    Entity Framework做IN查询
  • 原文地址:https://www.cnblogs.com/luizyao/p/11796892.html
Copyright © 2011-2022 走看看