路线适用于第一次测试,无法找到第二次测试(提示:第一次和第二次测试相同)

Routes works for the first test, can not be found for the second test (hint: 1st and 2nd tests are the same)

在问你之前,我尽量在 SO 中搜索类似的问题。我已经阅读 https://docs.pytest.org/en/latest/explanation/fixtures.html 页两次。但是,我无法解决我面临的问题。我是 Python 和 Flask 的新手。所以我认为我遗漏了一些明显的东西。

我有一个小型 micky-mouse Flask 应用程序。我正在尝试为此编写测试。我投票赞成使用 Pytest,因为 fixtures 似乎比 unittest 更灵活。令我惊讶的是,第一个测试用例 运行s 完全没有问题。然而,完全相同的测试用例第二次失败 运行。

这是我的 fixtures.py 文件:

from config import Config
import pytest

from app import create_app, db
from app.models import User, Role

class TestConfig(Config):
    SECRET_KEY = 'Shhhhh 007! Be quiet.!'
    SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    EXPLAIN_TEMPLATE_LOADING = True
    DEBUG = True
    API_VERSION = 'temp'


@pytest.fixture
def client():
    testConfig = TestConfig()
    app = create_app(testConfig)

    from app import routes, models

    with app.test_client() as client:
        with app.app_context():
            db.create_all()
            yield client

@pytest.fixture(autouse=True)
def role(client):
    role = Role()
    role.name = 'test role'
    db.session.add(role)
    db.session.commit()
    yield role
    db.session.delete(role)
    db.session.commit()

@pytest.fixture(autouse=True)
def user(role):
    user = User()
    user.role_id = role.id
    user.name = 'test name'
    user._normalized_name = 'test name'
    user.lastname = 'test lastname'
    user._normalized_lastname = 'test lastname'
    user.phonenumber = '+11231234567'
    user.setPassword('testPassword')
    db.session.add(user)
    db.session.commit()
    yield user
    db.session.delete(user)
    db.session.commit()

这是我的 test_login.py 文件:

import logging
from tests.fixtures import client, role, user

def test_login_page_Once(client):
    rv = client.get('/login')
    decodedRv = rv.data.decode('utf-8')
    print(decodedRv)
    assert '<title>Signin' in decodedRv

def test_login_page_Twice(client):
    rv = client.get('/login')
    decodedRv = rv.data.decode('utf-8')
    print(decodedRv)
    assert '<title>Signin' in decodedRv

我 运行 我的测试使用:

pytest -v -k test_login

结果如下:

tests/functional/test_login.py::test_login_page_Once PASSED                              [ 50%]
tests/functional/test_login.py::test_login_page_Twice FAILED                             [100%]

========================================== FAILURES ===========================================
____________________________________ test_login_page_Twice ____________________________________

client = <FlaskClient <Flask 'app'>>

    def test_login_page_Twice(client):
        rv = client.get('/login')
        decodedRv = rv.data.decode('utf-8')
        print(decodedRv)
>       assert '<title>Signin' in decodedRv
E       assert '<title>Signin' in '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n<title>404 Not Found</title>\n<h1>Not Found</h1>\n<p>The requested URL was not found on the server.
If you entered the URL manually please check your spelling and try again.</p>\n'

tests\functional\test_login.py:17: AssertionError
------------------------------------ Captured stdout call -------------------------------------
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>

=================================== short test summary info ===================================
FAILED tests/functional/test_login.py::test_login_page_Twice - assert '<title>Signin' in '<!D...

========================== 1 failed, 1 passed, 2 deselected in 1.57s ==========================

我错过了什么?任何帮助将不胜感激。非常感谢。

好吧,我找到了解决问题的办法,我为此苦苦思索了一会儿。虽然我通过尝试和错误找到了那个解决方案,但它仍然超出我的范围 why/how 它有效。如果有pytest/flask的高手给我解释一下就好了

如果有人能告诉我夹具范围之间的区别,我将不胜感激。 (我已经读过 https://docs.pytest.org/en/latest/reference/reference.html#pytest.fixture 但对我来说还不清楚。)

谢谢。

我在代码中所做的唯一更改是我添加了

scope='session'

到客户端夹具。

@pytest.fixture(scope='session')
def client():
    testConfig = TestConfig()
    app = create_app(testConfig)

    from app import routes, models

    with app.test_client() as client:
        with app.app_context():
            db.create_all()
            yield client

添加#2:

再往前走,我的另一项测试因类似症状而失败。不同之处在于这个测试用例存在于另一个文件中(我在测试登录时遇到了以前的问题page/behavior。现在我正在处理注册page/behavior)。我暂时找不到解决此错误的方法。 (我什至考虑放弃 pytest 并回到 unittest。但我仍然在这里,因为我有点固执。那是另一回事!)

无论如何,我意识到对灯具进行分组的一种方法是将它们放在名为 conftest.py 的文件中。我的名字叫 fixtures.py. 在我的脑海里,这只是一个名字,我认为我的更清楚。好吧,我错了。 conftest.py 似乎是一个神奇的文件。一旦我将 fixtures.py 重命名为 conftest.py test all marched pass in闪亮的绿色盔甲。

在这里加上我的两分钱,以防其他人在 fixtures/routes/imports 森林深处迷路。