【问题标题】:PyTest fails on a directory with multiple test files when modularizing fixtures模块化夹具时,PyTest 在具有多个测试文件的目录上失败
【发布时间】:2017-10-17 14:19:54
【问题描述】:

我正在使用 Py.Test 在 Python Flask 应用程序中测试函数。

当我使用一个包含所有固定装置和测试的“app_test.py”文件时,我的测试通过了。现在我已经将灯具拆分成它们自己的模块,并将测试分成不同的模块,每个模块都会导入我遇到的问题的灯具模块。

如果我对每个模块单独运行测试,一切都会顺利进行: pytest tests/test_1.pypytest tests/test_2.pypytest tests/test_3.py 等。但是,如果我想使用一个命令按顺序运行所有测试,例如pytest tests.

我的第一个测试模块通过,所有未来的测试都报告错误:

AssertionError: A setup function was called after the first request was handled.  
This usually indicates a bug in the application where a module was not imported 
and decorators or other functionality was called too late.
E  To fix this make sure to import all your view modules, database models 
and everything related at a central place before the application starts 
serving requests.

一个文件中的所有测试和固定装置看起来像这样:

# app_test.py

from flask_app import create_app
@pytest.fixtures(scope="session")
def app(request):
    app = create_app()
    with app.app_context():
        yield app

@pytest.fixture(scope="session"):
def client(request, app):
    client = app.test_client()
    return client


def test1(client):
    # test body

def test2(client):
    # test body

...

我运行$ pytest app_test.py,一切运行良好。

现在假设我们将它们分成三个不同的模块:fixures.py、test_1.py 和 test_2.py。现在的代码如下所示。

# tests/fixtures.py
from flask_app import create_app
@pytest.fixtures(scope="session")
def app(request):
    app = create_app()
    with app.app_context():
        yield app

@pytest.fixture(scope="session"):
def client(request, app):
    client = app.test_client()
    return client

# tests/test_1.py
from tests.fixtures import app, client
def test_1(client):
    # test body

# tests/test_2.py
from tests.fixtures import app, client
def test_2(client):
    # test body

如果我们运行$ pytest tests,那么tests/test_1.py 将通过,而tests/test_2.py 将引发错误。

我查看了这个gist,并尝试使用@pytest.mark.usefixture 标记测试功能,但没有成功。

如何在包含多个测试文件的目录上运行带有模块化夹具的 Py.Test?

【问题讨论】:

    标签: python python-3.x unit-testing flask pytest


    【解决方案1】:

    你对固定装置的使用稍有不当。

    具体来说,您声明了多个具有相同名称和相同功能对象的装置,但在不同的模块中检测到。从 pytest 的角度来看,这些应该是单独的函数,因为 pytest 使用dir(module) 来检测文件中的测试和固定装置。但不知何故,由于相同的函数对象,我认为 pytest 将它们记住是相同的;所以一旦你进入第二个测试文件,它会尝试本地检测到的夹具名称,但发现它已经准备好并失败。

    正确的用法是创建一个伪插件conftest.py,并将所有的固定装置放在那里。声明后,这些设备将可用于该目录和所有子目录中的所有文件。

    注意:不得将此类夹具导入到测试文件中。固定装置不是功能。 Pytest 会自动准备它们并将它们提供给测试。

    # tests/conftest.py
    import pytest
    from flask_app import create_app
    
    @pytest.fixtures(scope="session")
    def app(request):
        app = create_app()
        with app.app_context():
            yield app
    
    @pytest.fixture(scope="session")
    def client(request, app):
        client = app.test_client()
        return client
    

    还有测试文件(注意没有导入!):

    # tests/test_1.py
    def test_1(client):
        # test body
    
    # tests/test_2.py
    def test_2(client):
        # test body
    

    查看更多:https://docs.pytest.org/en/latest/writing_plugins.html

    【讨论】:

    • 第一个 @pytest.fixtures(scope="session") 中的“s”太多,第二个之后的冒号太多。
    【解决方案2】:

    如果您使用的是应用程序实例,那么这对您有用:

    import os
    import tempfile
    import pytest
    from my_app import app, db
    
    @pytest.fixture
    def client():
        db_fd, app.config["DATABASE"] = tempfile.mkstemp()
        app.config["TESTING"] = True
    
        with app.app_context():
            db.init_app(app)
    
        yield app
    
        os.close(db_fd)
        os.unlink(app.config["DATABASE"])
    
    @pytest.fixture
    def client(request):
        client = app.test_client()
        return client
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-04
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-24
      • 1970-01-01
      相关资源
      最近更新 更多