python模块大全doc_Python 测试模块 doctest

有时候我们想在 Python 中做一些测试,比如测试刚写的类的方法是否运行正常,或者测试代码是否产生预期异常。这种情况下使用 unittest 是麻烦且费事的,因为我们需要直观的在代码中看到这些测试,并且能运行这些测试。

doctest 模块为我们提供了一种在 Python docstring 中写测试用例并进行测试的方法。

在 Python 的官方文档中,对 doctest 的介绍是这样的:

doctest 模块会搜索那些看起来像是 Python 交互式会话中的代码片段,然后尝试执行并验证结果。

源码中的 doctest1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16# test_doctest.py

def multiply(x, y):

"""test multiply

>>> multiply(3, 4)

12

>>> multiply('x', 3)

'xxx'

"""

return x * y

if __name__ == '__main__':

import doctest

doctest.testmod(verbose=True)

测试:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18$ python doctest_test.py

Trying:

multiply(3, 4)

Expecting:

12

ok

Trying:

multiply('x', 3)

Expecting:

'xxx'

ok

1 items had no tests:

__main__

1 items passed all tests:

2 tests in __main__.multiply

2 tests in 2 items.

2 passed and 0 failed.

Test passed.

有两个地方可以放 doctest 的测试用例,一个位置是模块的开头,令一个位置是函数声明语句的下一行(如上例)。除此之外其他地方的 doctest 都无效,即使放了也不会被执行。

doctest 在 docstring 中寻找测试用例的时候,认为 >>> 是一个测试用例的开始,直到遇到空行或者下一个 >>>,在两个测试用例之间的其他内容会被 doctest 忽略掉。

当 __main__ 函数不方便调用 doctest 的时候,可以使用另一种执行方法:

1

2$ python -m doctest test_doctest.py

$ python -m doctest -v test_doctest.py

-v 参数用于输出详细信息。

独立文件中的 doctest

如果不想把 doctest 内嵌于 Python 源码中,可以建立一个独立文件来保存测试用例。

1

2

3

4

5

6

7

8

9

10

11test_doctest.txt

'>>>' 开头的行就是doctest测试用例。

不带 '>>>' 的行就是测试用例的输出。

如果实际运行的结果与期望的结果不一致,就标记为测试失败。

>>> from test_doctest import multiply

>>> multiply(3, 4)

12

>>> multiply('a', 3)

'aaa'

然后执行:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20$ python -m doctest -v test_doctest.txt

Trying:

from test_doctest import multiply

Expecting nothing

ok

Trying:

multiply(3, 4)

Expecting:

12

ok

Trying:

multiply('a', 3)

Expecting:

'aaa'

ok

1 items passed all tests:

3 tests in test_doctest.txt

3 tests in 1 items.

3 passed and 0 failed.

Test passed.

这里注意,from 一行也要以 >>> 开头。

处理可变变量

测试过程中,有些内容是不断变化的,如时间、对象ID等等。

1

2

3

4

5

6

7

8

9

10

11

12# test_changable.py

class T:

pass

def unpredictable(o):

"""return a new list contains object

>>> unpredictable(T())

[]

"""

return [o]

直接运行这个测试用例必然失败,因为对象在内存中的位置是不固定的。这个时候我们可以使用 doctest 的 ELLOPSIS 开关,并在需要忽略的地方用 ... 代替。

1

2

3

4

5

6

7

8

9

10

11

12# test_new_changable.py

class T:

pass

def unpredictable(o):

"""return a new list contains object

>>> unpredictable(T()) # doctest: +ELLIPSIS

[]

"""

return [o]

测试结果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14$ python -m doctest test_new_changable.py -v

Trying:

unpredictable(T()) # doctest: +ELLIPSIS

Expecting:

[]

ok

2 items had no tests:

test_new_changable

test_new_changable.T

1 items passed all tests:

1 tests in test_new_changable.unpredictable

1 tests in 3 items.

1 passed and 0 failed.

Test passed.

交互器跨多行1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17# test_multiline.py

def group_by_length(words):

"""return a dictionary grouping words into sets by length

>>> grouped = group_by_length(['python', 'module', 'of', 'the', 'week'])

>>> grouped == {2: {'of'},

... 3: {'the'},

... 4: {'week'},

... 6: {'python', 'module'}

... }

True

"""

ret = {}

for word in words:

s = ret.setdefault(len(word), set())

s.add(word)

return ret

测试结果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21$ python -m doctest test_multiline.py -v

Trying:

grouped = group_by_length(['python', 'module', 'of', 'the', 'week'])

Expecting nothing

ok

Trying:

grouped == {2: {'of'},

3: {'the'},

4: {'week'},

6: {'python', 'module'}

}

Expecting:

True

ok

1 items had no tests:

test_multiline

1 items passed all tests:

2 tests in test_multiline.group_by_length

2 tests in 2 items.

2 passed and 0 failed.

Test passed.

异常

Traceback 是一种特殊的可变变量,因为 Traceback 中的信息会随着系统平台、脚本文件位置变化而变化,所以匹配 Traceback 的时候我们需要忽略一些东西。可以只写第一行的 Traceback (most recent call last): 或者 Traceback (innermost last): 和最后一行的异常信息即可。

1

2

3

4

5

6

7

8

9

10# test_exception.py

def t():

"""raise a runtime error

>>> t()

Traceback (most recent call last):

...

RuntimeError: This is a runtime error!

"""

raise RuntimeError('This is a runtime error!')

测试结果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15$ python -m doctest test_exception.py -v

Trying:

t()

Expecting:

Traceback (most recent call last):

...

RuntimeError: This is a runtime error!

ok

1 items had no tests:

test_exception

1 items passed all tests:

1 tests in test_exception.t

1 tests in 2 items.

1 passed and 0 failed.

Test passed.

处理空白字符

有时测试用例的输出中会有空行、空格等空白字符,然而 doctest 默认空行代表测试用例的结束,这是我们可以用 代表空行。

1

2

3

4

5

6

7

8

9

10

11

12# test_blankline.py

def double_space(lines):

"""

>>> double_space(['Line 1', 'Line 2'])

Line 1

Line 2

"""

for line in lines:

print(line)

print()

测试结果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16$ python -m doctest -v test_blankline.py

Trying:

double_space(['Line 1', 'Line 2'])

Expecting:

Line 1

Line 2

ok

1 items had no tests:

test_blankline

1 items passed all tests:

1 tests in test_blankline.double_space

1 tests in 2 items.

1 passed and 0 failed.

Test passed.

关于 doctest 常用的就这么多,更多内容请参考官方文档。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值