【问题标题】:Run pytest for each file in directory为目录中的每个文件运行 pytest
【发布时间】:2020-11-22 10:07:41
【问题描述】:

我正在尝试为当前目录中的每个 PDF 文档构建一个调用 Pytest 类的例程...让我解释一下

假设我有这个测试文件

import pytest

class TestHeader:
    #asserts...

class TestBody:
    #asserts...

此脚本需要测试我的 cwd 中的每个 pdf 文档

这是我最好的尝试:

import glob
import pytest

class TestHeader:
    #asserts...

class TestBody:
    #asserts...

filelist = glob.glob('*.pdf')

for file in filelist:
    #magically call pytest for each file

我将如何处理这个问题?

编辑:补充我的问题。

我有一个巨大的函数可以提取每个文档的数据,我们称之为extract_pdf 这个函数返回一个元组(header, body)。

当前尝试如下所示:

import glob
import pytest

class TestHeader:
    #asserts...

class TestBody:
    #asserts...

filelist = glob.glob('*.pdf')

for file in filelist:
    header, body = extract_pdf(file)
    pytest.main(<pass header and body as args for pytest>)

我需要在测试之前解析每个文档。这样可以吗?

【问题讨论】:

  • 这是一个相关的问题,有一些很好的答案。 stackoverflow.com/questions/3343205/…
  • 这很有用,但我忘了包括一个额外的小步骤,这给我带来了麻烦。我刚刚编辑了问题

标签: python flask pytest glob


【解决方案1】:

通过动态参数化测试用例来做到这一点的最佳方法..

这可以使用pytest_generate_tests 钩子来实现..

def pytest_generate_tests(metafunc):
    filelist = glob.glob('*.pdf')
    metafunc.parametrize("fileName", filelist )

注意:fileName 应该是您的测试函数的参数之一。

这将导致为目录中的每个文件执行测试用例,测试用例将像

TestFunc[File1]
TestFunc[File2]
TestFunc[File3]
.
.

等等..

【讨论】:

    【解决方案2】:

    这是对@ArunKalirajaBaskaran 现有答案的扩展。

    问题是您有不同的测试类想要使用相同的数据,但您只想解析数据一次。如果您可以一次读取所有数据,您可以将它们读入全局变量并使用它们来参数化您的测试:

    def extract_data():
        filenames = []
        headers = []
        bodies = []
        for filename in glob.glob('*.pdf'):
            header, body = extract_pdf(filename)
            filenames.append(filename)
            headers.append(header)
            bodies.append(body)
        return filenames, headers, bodies
    
    filenames, headers, bodies = extract_data()
    
    
    def pytest_generate_tests(metafunc):
        if "header" in metafunc.fixturenames:
            # use the filename as ID for better test names
            metafunc.parametrize("header", headers, ids=filenames)
        elif "body" in metafunc.fixturenames:
            metafunc.parametrize("body", bodies, ids=filenames)
    
    class TestHeader:
        def test_1(header):
            ...
    
        def test_2(header):
            ...
    
    class TestBody:
        def test_1(body):
            ...
    

    这和使用是一样的

    class TestHeader:
        @pytest.mark.parametrize("header", headers, ids=filenames)
        def test_1(header):
            ...
    
        @pytest.mark.parametrize("header", headers, ids=filenames)
        def test_2(header):
            ...
    

    pytest_generate_tests 只是增加了一点便利,因此您不必为每个测试重复 parametrize 装饰器。

    这样做的缺点当然是你会一次读入所有数据,如果文件很多,这可能会导致内存使用问题。您使用pytest.main 的方法将不起作用,因为这与使用给定参数在命令行上调用pytest 相同。参数化可以在夹具级别或测试级别完成(如这里),但两者都需要在加载时已经评估的参数,所以我看不出有可能懒惰地这样做(除了把它全部放在一个测试中)。也许其他人有更好的主意...

    【讨论】:

      猜你喜欢
      • 2012-05-02
      • 2016-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      相关资源
      最近更新 更多