简体   繁体   English

为目录中的每个文件运行 pytest

[英]Run pytest for each file in directory

I'm trying to build a routine that calls a Pytest class for each PDF document in current directoy... Let me explain我正在尝试为当前目录中的每个 PDF 文档构建一个调用 Pytest class 文档的例程......让我解释一下

Lets say i have this test file假设我有这个测试文件

import pytest

class TestHeader:
    #asserts...

class TestBody:
    #asserts...

This script needs to test each pdf document in my cwd此脚本需要测试我的 cwd 中的每个 pdf 文档

Here is my best attempt:这是我最好的尝试:

import glob
import pytest

class TestHeader:
    #asserts...

class TestBody:
    #asserts...

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

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

How would i approach this?我将如何处理这个问题?

EDIT: Complementing my question.编辑:补充我的问题。

I have a huge function that extracts each document's data, lets call it extract_pdf this function returns a tuple (header, body).我有一个巨大的 function 提取每个文档的数据,我们称之为extract_pdf这个 function 返回一个元组(标题,正文)。

Current attempt looks like this:当前尝试如下所示:

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>)

I need to parse each document prior to testing.我需要在测试之前解析每个文档。 Can it be done this way?可以这样做吗?

The best way to do this through parameterization of the testcases dynamically..通过动态参数化测试用例来做到这一点的最佳方法..

This can be achieved using the pytest_generate_tests hook..这可以使用pytest_generate_tests钩子来实现。

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

NOTE: fileName should be one of the argument to your test function.注意: fileName应该是您的测试 function 的参数之一。

This will result in executing the testcase for each of the file in the directory and the testcase will be like这将导致为目录中的每个文件执行测试用例,测试用例就像

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

and so on..等等..

This is expanding on the existing answer by @ArunKalirajaBaskaran.这是对@ArunKalirajaBaskaran 现有答案的扩展。

The problem is that you have different test classes that want to use the same data, but you want to parse the data only once.问题是您有不同的测试类想要使用相同的数据,但您只想解析数据一次。 If it is ok for you to read all data at once, you could read them into global variables and use these for parametrizing your tests:如果您可以一次读取所有数据,您可以将它们读入全局变量并使用它们来参数化您的测试:

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):
        ...

This is the same as using这与使用相同

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 just adds a bit of convenience so you don't have to repeat the parametrize decorator for each test. pytest_generate_tests只是增加了一点便利,因此您不必为每个测试重复parametrize装饰器。

The downside of this is of course that you will read in all of the data at once, which may cause a problem with memory usage if there is a lot of files.这样做的缺点当然是您将一次读取所有数据,如果有很多文件,这可能会导致 memory 使用出现问题。 Your approach with pytest.main will not work, because that is the same as calling pytest on the command line with the given parameters.您使用pytest.main的方法将不起作用,因为这与使用给定参数在命令行上调用pytest相同。 Parametrization can be done at the fixture level or on the test level (like here), but both need the parameters alreay evaluated at load time, so I don't see a possibility to do this lazily (apart from putting it all into one test).参数化可以在夹具级别或测试级别完成(如这里),但两者都需要在加载时已经评估的参数,所以我看不出有可能懒惰地这样做(除了把它全部放在一个测试中)。 Maybe someone else has a better idea...也许别人有更好的主意...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM