如何使 py.test 或鼻子在所有 python 文件中查找测试?

发布于 2024-09-18 06:39:04 字数 417 浏览 6 评论 0 原文

我确实有几个小模块,其中的测试位于其中,并且 py.testnose 不会查找它们,因为它们不包含 test在他们的文件名中。

我怎样才能说服py.testnose在所有python文件中递归地寻找测试 - '''包括那些没有test 在他们的文件名'''?

在源文件中,我确实保留了标准命名约定:class testSomeName 和方法def test_some_name

如果这是不可能的,我可以使用什么其他解决方案来获得相同的结果。

我不想手动创建包含测试的所有文件的列表,我想要一个支持发现的解决方案。

I do have several small modules where the tests are inside them and py.test or nose does not look for them because they do not contain test in their filename.

How can I convince py.test or nose to look for tests inside all python files, recursively - '''including the ones that do not have test in their filenames'''?

Inside the source files I do keep the standard naming convention: class testSomeName with methods def test_some_name.

If this is not possible, what other solution can I use to obtain the same result.

I do not want to manually create a list of all files containing the test, I want a solution that supports discovery.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

灼痛 2024-09-25 06:39:22

对于 pytest-6,我必须更改 @hpk42 答案以直接返回给定源/测试代码布局的模块实例。最初的答案对这个主要版本的 pytest 提出了例外,因为 API 同时发生了变化。

def pytest_collect_file(path, parent):
    """Look in all Python files for test cases."""
    from _pytest.python import Module

    if path.ext == ".py":
        return Module.from_parent(parent, fspath=path)

For pytest-6 I had to change @hpk42 answer to directly return a Module instance for the given source/test code layout. The original answer raised an exception for this major version of pytest, as the API has changed in the meantime.

def pytest_collect_file(path, parent):
    """Look in all Python files for test cases."""
    from _pytest.python import Module

    if path.ext == ".py":
        return Module.from_parent(parent, fspath=path)
兮颜 2024-09-25 06:39:19

文档

默认情况下,所有不以点开头的目录都会被遍历,寻找 test_*.py 和 *_test.py 文件。这些 Python 文件将以其包名称导入。

您能确保您的代码就是这种情况吗?

更新

(买者自负:我还没有尝试/测试过这个)如何使用hooks 提供用于收集目录和文件吗?

py.test 调用以下两个基本钩子来收集文件和目录:

def pytest_collect_directory(path, parent):
    """ return Collection node or None for the given path. """

def pytest_collect_file(path, parent):
    """ return Collection node or None for the given path. """

两者都返回给定路径的集合节点 。所有钩子实现返回的所有节点都将参与收集和运行协议。 parent 对象是父节点,可用于通过 parent.config 对象访问命令行选项。

The documentation says that

By default all directories not starting with a dot are traversed, looking for test_*.py and *_test.py files. Those Python files are imported under their package name.

Can you ensure that this is the case with your code?

Update

(Caveat Emptor: I haven't tried/tested this) How about using the hooks provided for collecting directories and files?

py.test calls the following two fundamental hooks for collecting files and directories:

def pytest_collect_directory(path, parent):
    """ return Collection node or None for the given path. """

def pytest_collect_file(path, parent):
    """ return Collection node or None for the given path. """

Both return a collection node for a given path. All returned nodes from all hook implementations will participate in the collection and running protocol. The parent object is the parent node and may be used to access command line options via the parent.config object.

说好的呢 2024-09-25 06:39:15

使用 py.test 就很简单了。创建一个包含以下内容的 conftest.py 文件:

# content of conftest.py file at root of your project
def pytest_collect_file(path, parent):
    if path.ext == ".py":
        return parent.Module(path, parent)

这将扩展收集过程,为每个“.py”文件创建一个测试“模块”节点。将其放入 conftest.py 文件中使其成为特定于项目的扩展,如果您键入以下内容,则会自动加载该扩展:

py.test 

出于信息目的,您还可以键入:

py.test --collectonly

以查看收集了哪些测试和文件,示例输出:

<Directory 'morecollect'>
   <Module 'conftest.py'>
   <Directory 'pkg'>
     <Module 'test_x.py'>
        <Function 'test_hello2'>
   <Module 'x.py'>   # this is collected because of our conftest.py extension
     <Function 'test_hello'>

如果需要,您还可以将上述 conftest.py 文件打包为 可安装插件 并通过安装插件使扩展可用。在这种情况下,您根本不需要任何 conftest.py 文件。

With py.test it's simple. Create a conftest.py file with this content:

# content of conftest.py file at root of your project
def pytest_collect_file(path, parent):
    if path.ext == ".py":
        return parent.Module(path, parent)

This will extend the collection process to create a test "Module" node for each ".py" file. Putting this into a conftest.py file makes it a project-specific extension which is automatically loaded if you type:

py.test 

For informational purposes you can also type:

py.test --collectonly

to see what tests and files are collected, example output:

<Directory 'morecollect'>
   <Module 'conftest.py'>
   <Directory 'pkg'>
     <Module 'test_x.py'>
        <Function 'test_hello2'>
   <Module 'x.py'>   # this is collected because of our conftest.py extension
     <Function 'test_hello'>

If needed you can also package the above conftest.py file as an installable plugin and make the extension available by installing the plugin. In this case you do not need any conftest.py file at all.

油焖大侠 2024-09-25 06:39:13

您还可以查看 Nose ,它会发现测试,而无需使用固定的文件名约定。

您可以使用以下代码绕过鼻子中用于过滤文件的正则表达式。
创建一个 python 模块(即 my_nosetests.py

import nose
from nose.plugins.base import Plugin

class ExtensionPlugin(Plugin):

    name = "ExtensionPlugin"

    def options(self, parser, env):
        Plugin.options(self,parser,env)

    def configure(self, options, config):
        Plugin.configure(self, options, config)
        self.enabled = True

    def wantFile(self, file):
        return file.endswith('.py')

    def wantDirectory(self,directory):
        return True

    def wantModule(self,file):
        return True


if __name__ == '__main__':
    includeDirs = ["-w", ".", ".."]
    nose.main(addplugins=[ExtensionPlugin()], argv=sys.argv.extend(includeDirs))

)请注意,您实际上正在加载所有模块并在其中搜索测试。注意模块加载的任何副作用。

You can also have a look at Nose which will discover tests without having to use a fixed file name convention.

You can bypass the regexp used to filter files in nose with the following code.
Create a python module (i.e. my_nosetests.py)

import nose
from nose.plugins.base import Plugin

class ExtensionPlugin(Plugin):

    name = "ExtensionPlugin"

    def options(self, parser, env):
        Plugin.options(self,parser,env)

    def configure(self, options, config):
        Plugin.configure(self, options, config)
        self.enabled = True

    def wantFile(self, file):
        return file.endswith('.py')

    def wantDirectory(self,directory):
        return True

    def wantModule(self,file):
        return True


if __name__ == '__main__':
    includeDirs = ["-w", ".", ".."]
    nose.main(addplugins=[ExtensionPlugin()], argv=sys.argv.extend(includeDirs))

Now run my_nosetests.py as if you were running nosetests and you should have your tests running. Be aware that you are in fact loading all modules and searching for tests in them. Beware of any side effect of module loading.

表情可笑 2024-09-25 06:39:10

将文件“setup.cfg”放在项目的根目录下,其中包含以下两行:

[pytest]
python_files=*.py

然后 py.test 从所有 *.py 文件中选择测试。这里有解释:pytest docs

with Nose:

nosetests --all-modules

Put a file "setup.cfg" at the root of project, and it contains this two lines:

[pytest]
python_files=*.py

then py.test select tests from all *.py files. Here it's explained: pytest docs

with Nose:

nosetests --all-modules
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文