【问题标题】:How to have two issued fixtures depend on each other?如何让两个已发布的夹具相互依赖?
【发布时间】:2016-03-19 10:44:56
【问题描述】:

test_something() 中,app 实例应与login 实例使用的相同。

@pytest.fixture
def app():
    # ...
    return app

@pytest.fixture
def login(app):
    # ...
    return login

def test_something(self, app, login):
    pass

我尝试的是从第二个夹具返回两个对象,但我不会称之为惯用语。

@pytest.fixture
def app_and_login(app):
    # ...
    return app, login

def test_something(self, app_and_login):
    app, login = login_and_login

有没有更好的方法来做到这一点?

【问题讨论】:

  • def test_something(app, login) 方法有什么问题?看起来一样,如果您不打算将 applogin 固定装置更改。

标签: python unit-testing pytest fixtures


【解决方案1】:

正如您所描述的,默认情况下,夹具已经为测试的运行时共享。

这实际上并没有在任何地方明确记录(或者至少我没有找到它),但它有些隐含:Sharing a fixture across tests in a module 描述了scope 参数,默认范围是function

其他范围,例如是module(共享/缓存同一模块中所有测试的夹具)或session(缓存整个测试会话的夹具)。

【讨论】:

    【解决方案2】:

    我没想到会这样,但这似乎是默认行为。不过,我找不到任何关于此的文档。提示表示赞赏。

    【讨论】:

    • 这确实有点含蓄——参见Sharing a fixture across tests in a module,它描述了scope 参数,默认范围是function,这意味着每个测试函数共享一次fixture。
    • @TheCompiler 谢谢,这是正确的答案。请随时写一个答案。
    【解决方案3】:

    您可以将其作为对象返回,并使用第三个固定装置:

    import pytest
    from collections import namedtuple
    
    Auth = namedtuple('Auth', 'app, login')
    
    @pytest.fixture
    def app():
        return 'APP'
    
    @pytest.fixture
    def login(app):
        return 'Login at %s' % app
    
    @pytest.fixture
    def auth(app, login):
        return Auth(app, login)
    
    def test_something(auth):
        assert auth.app in auth.login
    

    【讨论】:

      【解决方案4】:

      我知道这个问题很老了,但我没有看到你描述的行为,我被这个 Q&A 真正转移了注意力,直到我想,“它不能那样工作.. .”并为自己测试了它。我试过这个:

      platform darwin -- Python 3.7.7, pytest-6.0.1, py-1.9.0, pluggy-0.13.1 -- .../bin/python3

      我做了这个测试,它通过了:

      import collections
      import pytest
      
      AppObject = collections.namedtuple("App", ["name", "login"])
      
      @pytest.fixture
      def app():
          app = AppObject("appname", "applogin")
          return app
      
      @pytest.fixture
      def login(app):
          return app.login
      
      def test_something(app, login):
          assert isinstance(app, AppObject) and app.name == "appname"
          assert isinstance(login, str) and login == "applogin"
      
      

      OP 似乎担心 login 夹具接收的 app 对象与应用夹具返回的 app 不同。我不认为会发生这种情况。例如,如果您添加一些有用的 print 语句,如下所示:

      import collections
      import pytest
      
      AppObject = collections.namedtuple("App", ["name", "login"])
      
      @pytest.fixture
      def app():
          app = AppObject("appname", "applogin")
          print("Object id in app fixture: %d" % id(app))
          return app
      
      @pytest.fixture
      def login(app):
          print("Object id in login fixture: %d" % id(app))
          return app.login
      
      def test_something(app, login):
          print("Object id in test: %d" % id(app))
          assert isinstance(app, AppObject) and app.name == "appname"
          assert isinstance(login, str) and login == "applogin"
      

      我看到了这个输出:

      Object id in app fixture: 4451368624
      Object id in login fixture: 4451368624
      Object id in test: 4451368624
      

      ...所以这三个地方绝对是同一个对象。像这样的嵌套装置对我来说“只是工作”,所以我要么错过了你问的问题的重点,要么行为发生了变化,或者......其他的东西。但我想把它留在这里,以供其他寻找这样的嵌套/依赖装置的人使用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-26
        • 2021-09-19
        • 1970-01-01
        • 2020-04-06
        • 2020-02-13
        • 1970-01-01
        相关资源
        最近更新 更多