class 的 Pytest fixture 通过 self 而不是方法参数

Pytest fixture for a class through self not as method argument

我通常会编写一个测试 class,在每个方法中使用 pytest fixture。这是一个例子。我希望能够避免必须在每个方法的签名中写下夹具名称。这不是干的。如何才能做到这一点?

我希望能够通过将夹具作为测试的属性来访问夹具 class。在此示例中,我希望将 google 夹具视为 TestGoogle 的一个属性。这可能吗?

from bs4 import BeautifulSoup
import pytest
import requests

@pytest.fixture()
def google():
    return requests.get("https://www.google.com")


class TestGoogle:
    def test_alive(self, google):
        assert google.status_code == 200

    def test_html_title(self, google):
        soup = BeautifulSoup(google.content, "html.parser")
        assert soup.title.text.upper() == "GOOGLE"

当然可以,只需使用自动夹具即可。 Here is the relevant spot in pytest docs。在您的示例中,更改将引入一个额外的固定装置(我将其命名为 _request_google_page):

from bs4 import BeautifulSoup
import pytest
import requests

@pytest.fixture()
def google():
    return requests.get("https://www.google.com")


class TestGoogle:

    @pytest.fixture(autouse=True)
    def _request_google_page(self, google):
        self._response = google

    def test_alive(self):
        assert self._response.status_code == 200

    def test_html_title(self):
        soup = BeautifulSoup(self._response.content, "html.parser")
        assert soup.title.text.upper() == "GOOGLE"

您甚至可以完全删除 google 夹具并将代码移动到 _request_google_page:

@pytest.fixture(autouse=True)
def _request_google_page(self):
    self._response = requests.get("https://www.google.com")

请注意 _request_google_page 默认情况下每个测试都会调用一次,因此每个测试都会得到一个新的响应。如果您希望响应初始化一次并在 TestGoogle class 中的所有测试中重复使用,请调整夹具范围(scope='class' 用于 _request_google_page scope='module'scope='session' 对于 google)。示例:

from bs4 import BeautifulSoup
import pytest
import requests


@pytest.fixture(scope='module')
def google():
    return requests.get("https://www.google.com")


@pytest.fixture(autouse=True, scope='class')
def _request_google_page(request, google):
    request.cls._response = google


class TestGoogle:

    def test_alive(self):
        assert self._response.status_code == 200

    def test_html_title(self):
        soup = BeautifulSoup(self._response.content, "html.parser")
        assert soup.title.text.upper() == "GOOGLE"

我不得不解决一个类似的问题,但公认的解决方案对 class-scoped fixture 不起作用。

我想在每个测试中调用一次夹具 class 并在使用 self 的测试方法中重新使用该值。这实际上也是 OP 打算做的。

您可以使用 request 夹具访问正在使用它的 class (request.cls) 并在 class 属性中分配夹具值。然后您可以从 self 访问此属性。这是完整的片段:

from bs4 import BeautifulSoup
import pytest
import requests

@pytest.fixture(scope="class")
def google(request):
    request.cls.google = requests.get("https://www.google.com")


@pytest.mark.usefixtures("google")
class TestGoogle:
    def test_alive(self):
        assert self.google.status_code == 200

    def test_html_title(self):
        soup = BeautifulSoup(self.google.content, "html.parser")
        assert soup.title.text.upper() == "GOOGLE"

希望能帮助其他人解决这个问题。

import pytest
from sqlalchemy import create_engine

@pytest.fixture(scope="class")
def test_connection():
    engine = "abc"#create_engine()
    return engine

@pytest.fixture(scope="class")
def test_patient_id():
    engine = "123"#create_engine()
    return engine


@pytest.mark.usefixtures("test_connection","test_patient_id")
class TestRuleEngine:
    def test_table_setup(self, test_connection, test_patient_id):
        assert 1
        assert test_connection=="abc"
        assert test_patient_id=="123"
    def test_data_insert(self):
        assert 1
    def test_data_delete(self):
        assert 1
    def test_table_delete(self):
        assert 1