5

我确实有几个小模块,其中测试在其中,py.test或者nose不查找它们,因为它们test的文件名中不包含它们。

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

在源文件中,我确实保留了标准命名约定:class testSomeNamewith methods def test_some_name

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

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

4

5 回答 5

5

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.

于 2010-09-08T18:23:02.450 回答
5

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.

于 2010-09-14T07:58:41.960 回答
5

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
于 2012-04-07T07:15:28.303 回答
1

文件说_

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

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

更新

(Caveat Emptor:我还没有尝试/测试过)如何使用提供的用于收集目录和文件的钩子?

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对象访问命令行选项。

于 2010-09-08T17:49:21.890 回答
0

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)
于 2021-09-29T08:51:03.700 回答