gpt4 book ai didi

python - 文档测试中稳健的相对路径

转载 作者:太空宇宙 更新时间:2023-11-03 14:30:05 24 4
gpt4 key购买 nike

我有一个函数,它将文件的路径作为参数。

output = process('path/to/file.txt')

我想知道我是否可以轻松地记录这样的函数。我在源代码中的某个位置提供了一个示例输入文件,我可以将输出与我期望的内容(字符串、Python 对象,或者可能是另一个文件的内容)进行比较。

问题是我的测试中的路径必然是相对的。相对于调用脚本的工作目录

这意味着文档字符串中的所有路径都必须知道测试套件的入口点。显然这并不理想。在更复杂的测试环境中,我可以使用 __file__ 使路径成为绝对路径,但在文档测试中,__file__ 不存在。

以文件形式提供刺激时通常的设置是什么?

我希望听到一些更好的解决方案,而不仅仅是“始终从同一工作目录运行测试套件”。

编辑:我想从集中测试套件入口点运行文档测试。

import doctest
import mymodule

doctest.testmod(mymodule)

最佳答案

由于您是在模块级别执行此操作,因此我假设您还具有 packaged your modules as a proper Python package使用诸如 setuptools 之类的东西,并将其部署到某个环境中,然后在其中执行测试。另外,您在 __file__ 不存在的假设中只部分正确 - 它也没有为从压缩的 Python Egg 导入的模块定义(随着轮子成为事实上的事实,这种情况变得越来越罕见)包装方法,但它们可以并且确实存在)。

有多种可能的方法,其复杂性和权衡各不相同,其是否有效取决于要测试的模块的结构。

1) (不推荐,但无论如何都包含在内,因为有时这在最简单的示例中效果最好。)最懒,但最稳定、独立和跨平台的方式 - 它假设文件打开方法是仅在要测试的一个模块中完成,并且使用相同的调用(例如 open)完成,使用 extraglobs参数可用于替代 open 调用。例如

from io import StringIO
import doctest
import mymodule

files = {
'path/to/file1.txt': '... contents of file1.txt ...',
'path/to/file2.txt': '... contents of file2.txt ...',
}

def lazyopen(p, flag='r'):
result = StringIO(files[p] if flag == 'r' else '')
result.name = p
return result

doctest.testmod(mymodule, extraglobs={'open': lazyopen})

2)创建一个真正的测试套件,而不是通过doctest.testmod使用内置的测试套件

虽然简写很有用,但它的局限性太大,因为它是独立的,不能与可能构建的其他测试套件结合使用。考虑创建一个专用的测试模块(例如mymodule/tests.py)。我通常更喜欢创建一个名为 mymodule/tests 的目录,其中包含名为 test_mysubmodule.py 的单元测试,以及包含 test_suite 的 __init__.py像这样设置

def make_suite():
import mymodule
import os

def setUp(suite):
suite.olddir = os.getcwd() # save the current working directory
os.chdir(targetdir) # need to define targetdir

def tearDown(suite):
os.chdir(suite.olddir) # restore the original working directory

return doctest.DocTestSuite(mymodule, setUp=setUp, tearDown=tearDown)

我们已经介绍了基本的内容,但是需要定义targetdir。同样,您可以考虑多种事情:

1) 创建一个临时目录,并使用 setupos.chdir 填充所需文件,然后删除 中的临时目录拆解。要么手动写入以字符串形式存储在测试模块内的数据,要么从项目中复制或从存档中提取,但我们如何实际获取这些数据?这导致...

2) 如果源文件位于您的项目内,并且环境中可用/安装了 setuptools,则只需使用 pkg_resources.resource_filename获取位置,并将 targetdir 分配给它。 setUp 现在可能看起来像

    def setUp(suite):
suite.olddir = os.getcwd()
targetdir = pkg_resources.resource_filename('mymodule', '')
os.chdir(targetdir)

此外,最后,由于这是一个真正的测试套件,由 mymodules.tests 中的 make_suite 函数生成,因此必须使用testrunner,幸运的是它作为一个简单的命令包含在默认的unittest框架中,可以像这样完成:

$ python -m unittest mymodule.tests.make_suite
.
----------------------------------------------------------------------
Ran 1 test in 0.014s

OK

此外,由于这是一个真正的测试套件,因此它可以与 unittest 模块中的测试套件集成,将所有内容组合到整个包的单个完整测试套件中。

def make_suite():
# ... the other setup code

# this loads all unittests in mymodule from `test_*.py` files
# inside `mymodule.tests`
test_suite = test_loader.discover(
'mymodule.tests', pattern='test_*.py')
test_suite.addTest(
doctest.DocTestSuite(mymodule, setUp=setUp, tearDown=tearDown))
return test_suite

同样,python -m unittest 命令可用于执行完整测试套件返回的测试。

关于python - 文档测试中稳健的相对路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47353508/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com