在py.test中,conftest.py文件有什么用处?

我最近发现了py.test 。 这似乎很棒。 不过,我觉得文件可能会更好。

我试图了解什么conftest.py文件是用来作为。

在我的(目前很小的)testing套件中,我在项目根目录下有一个conftest.py文件。 我用它来定义我注入到testing中的灯具。

我有两个问题:

  1. 这是conftest.py的正确使用吗? 它有其他用途吗?
  2. 我可以有多个conftest.py文件吗? 我什么时候想要这样做? 例子将不胜感激。

更一般地说,你如何定义pytesttesting套件中conftest.py文件的目的和正确使用?

这是conftest.py的正确使用吗?

是的,Fixtures是conftest.py一个潜在和常见的用途。 您将定义的灯具将在testing套件中的所有testing中共享。 但是在conftest.py根目录下定义灯具可能是没有用的,如果所有的testing都没有使用这样的灯具,它会减慢testing的速度。

它有其他用途吗?

是的,它确实。

  • 夹具 :为testing使用的静态数据定义夹具。 这个数据可以被套件中的所有testing访问,除非被指定。 这可能是数据以及将传递给所有testing的模块的助手。

  • 外部插件加载 :conftest.py用于导入外部插件或模块。 通过定义以下全局variables,pytest将加载模块并使其可用于其testing。 插件通常是在您的项目或其他模块中定义的文件,可能在您的testing中需要。 这里也可以加载一组预定义的插件。

    pytest_plugins = "someapp.someplugin"

  • 钩子 :你可以指定钩子,比如设置和拆卸方法等,以改善你的testing。 对于一组可用的钩子,请阅读这里 。 例:

     def pytest_runtest_setup(item): """ called before ``pytest_runtest_call(item). """ #do some stuff` 
  • testing根path :这是一个隐藏的function。 通过在你的根path中定义conftest.py ,你可以在不指定PYTHONPATH情况下通过pytest识别你的应用程序模块。 在后台,py.test通过包含从根pathfind的所有子模块来修改你的sys.path

我可以有多个conftest.py文件吗?

是的,你可以和强烈build议,如果你的testing结构是复杂的。 conftest.py文件具有目录范围,因此创build有针对性的装置和帮手是很好的做法。

我什么时候想要这样做? 例子将不胜感激。

有几种情况可以适用:

为特定的一组testing创build一组工具或挂钩

根/ MOD / conftest.py

 def pytest_runtest_setup(item): print("I am mod") #do some stuff test root/mod2/test.py will NOT produce "I am mod" 

为一些testing加载一套灯具 ,但不适用于其他灯具

根/ MOD / conftest.py

 @pytest.fixture() def fixture(): return "some stuff" 

根/ MOD2 / conftest.py

 @pytest.fixture() def fixture(): return "some other stuff" 

根/ MOD2 / test.py

 def test(fixture): print(fixture) 

将打印“一些其他的东西”

覆盖从根conftest.pyinheritance的conftest.py

根/ MOD / conftest.py

 def pytest_runtest_setup(item): print("I am mod") #do some stuff 

根/ conftest.py

 def pytest_runtest_setup(item): print("I am root") #do some stuff 

通过在root/mod运行任何testing,只打印“我是mod”。

你可以在这里阅读更多关于conftest.py

编辑:

如果我需要简单的帮助函数从不同的模块中进行多个testing,那么如果我把它们放在conftest.py中,它们是否可用? 或者我应该把它们放在一个helpers.py模块中,然后导入并在我的testing模块中使用它?

你可以使用conftest.py来定义你的助手,但你应该遵循惯例。 至less在py.test助手可以作为灯具使用。 例如,在我的testing中,我有一个嘲笑的redis助手,我用这种方式注入到我的testing中。

根/辅助/ redis的/ redis.py

 @pytest.fixture def mock_redis(): return MockRedis() 

根/testing/材料/ conftest.py

 pytest_plugin="helper.redis.redis" 

根/testing/材料/ test.py

 def test(mock_redis): print(mock_redis.get('stuff')) 

这将是一个testing模块,您可以在testing中自由导入。 请注意 ,如果您的模块redis包含更多testing,则可以将redis.pyconftest.py 。 不过,这种做法因含糊不清而令人灰心。

如果你想使用conftest.py你可以把这个助手放在你的根conftest.py中,并在需要的时候注入。

根/testing/ conftest.py

 @pytest.fixture def mock_redis(): return MockRedis() 

根/testing/材料/ test.py

 def test(mock_redis): print(mock_redis.get(stuff)) 

你可以做的另一件事是写一个可安装的插件。 在这种情况下,你的助手可以在任何地方编写,但是它需要定义一个入口点来安装在你的潜在的testing框架中。 看到这个

如果你不想使用灯具,你当然可以定义一个简单的助手,只需要使用普通的旧导入。

根/testing器/辅助/ redis.py

 class MockRedis(): # stuff 

根/testing/材料/ test.py

 from helper.redis import MockRedis def test(): print(MockRedis().get(stuff)) 

但是,在这里,您可能会遇到path问题,因为模块不在testing的子文件夹中。 你应该可以通过向你的帮手添加一个init来克服这个(未testing)

根/testing器/辅助/ __ init__.py

 from .redis import MockRedis 

或者简单地将辅助模块添加到您的PYTHONPATH

从广义上讲,conftest.py是一个本地的per-directory插件。 在这里你可以定义特定于目录的钩子和灯具。 在我的情况下,有一个根目录包含项目特定的testing目录。 一些常见的魔法是驻扎在“根”conftest.py。 项目具体 – 在他们自己的。 在conftest.py中存储灯具,除非它们没有被广泛使用,否则看不出什么坏东西(在这种情况下,我更喜欢直接在testing文件中定义它们)