【问题标题】:How to load variables from .env file for pytests如何从 .env 文件中为 pytests 加载变量
【发布时间】:2020-09-06 10:31:45
【问题描述】:

我正在用 Flask 编写一个 API,有时我会向注册的用户发送电子邮件。我将有关此电子邮件服务的变量存储在 .env 文件中。现在想测试一个我使用这些变量的部分,但我不知道如何从 .env 文件中加载它们。

我基本上在这里尝试了所有答案https://rb.gy/0nro1a,猴子修补 setenv 在这里显示https://rb.gy/kd07wa + 其他提示在这里和那里。每个都在某个点上失败了。我也尝试使用 pytest-dotenv。 pytest-env、pytest.ini 等。但没有什么能像预期的那样工作,这一切都让我很困惑。

我的 pytests 夹具看起来像这样

@pytest.fixture(autouse=True)
def test_client_db():

    # set up
    app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///"
    app.config["JWT_SECRET_KEY"] = "testing"

    with app.app_context():
        db.init_app(app)
        db.create_all()
    testing_client = app.test_client()
    ctx = app.app_context()
    ctx.push()

    # do testing
    yield testing_client

    # tear down
    with app.app_context():
        db.session.remove()
        db.drop_all()

    ctx.pop()

我想知道为什么我不能简单地在 .env 文件中加载带有类似 load_dotenv(path/to/.env) 这样的行的夹具设置中的某处并完成?

作为新手,有人可以向我解释如何以简单直接的方式读取 .env 变量以使用 pytest 吗?

真正对我有用的唯一方法是在我运行测试时在命令行上传递环境变量。

FROM_EMAIL="some@email.com" MAILGUN_DOMAIN="sandbox6420919ab29b4228sdfda9d43ff37f7689072.mailgun.org" MAILGUN_API_KEY="245d6d0asldlasdkjfc380fba7fbskfsj1ad3125649esadbf2-7cd1ac2b-47fb3ac2" pytest tests

但这是一种糟糕的方式,我不想每次运行测试时都将所有这些 var 写入命令行。

我只想写pytest test,我相信 .env 文件应该会自动加载到某个地方。但是在哪里以及如何?

任何帮助表示赞赏。

【问题讨论】:

  • 使用def setup_class(cls):并加载文件怎么样?
  • 在哪里?不是在夹具中完成设置吗? yield 之前的所有内容都是“设置”.. 不是吗?
  • 您可以使用 python-dotenv 读取 env 文件,并在会话范围的夹具中执行此操作(使用 autouse=True)。
  • 你能说得更具体些吗?因为这是我试图在我的夹具中做的。这也是我问的原因:为什么我不能简单地在夹具设置中的某处使用类似 load_dotenv(path/to/.env) 的行加载 .env 文件——它只是不起作用
  • 不确定你做了什么不同,但我只是按照答案所示进行了测试,它对我来说很好。

标签: python flask pytest


【解决方案1】:

如果您安装了python-dotenv,您可以使用它从.env 文件中加载变量。这是一个最小的例子:

.env

SQLALCHEMY_DATABASE_URI="sqlite:///"
JWT_SECRET_KEY="testing"

test.py

import os

import pytest
from dotenv import load_dotenv


@pytest.fixture(scope='session', autouse=True)
def load_env():
    load_dotenv()


@pytest.fixture(autouse=True)
def test_client_db():
    print(f"\nSQLALCHEMY_DATABASE_URI"
          f"={os.environ.get('SQLALCHEMY_DATABASE_URI')}")
    print(f"JWT_SECRET_KEY={os.environ.get('JWT_SECRET_KEY')}")


def test():
    pass

python -m pytest -s test.py 给出:

============================================ test session starts ============================================
...
collected 1 item

test.py
SQLALCHEMY_DATABASE_URI=sqlite:///
JWT_SECRET_KEY=testing
.

============================================= 1 passed in 0.27s =============================================

例如环境变量在整个测试会话中设置,可用于配置您的应用程序。请注意,我没有在 load_dotenv() 中提供路径,因为我将 .env 文件放在与测试相同的目录中 - 在您的代码中,您可能必须添加路径 (load_dotenv(dotenv_path=your_path))。

【讨论】:

  • 嗯,是的,它就像你描述的那样工作。我的问题实际上在其他地方。我有一些 env 变量封装在一个类中,我需要将 load_dotenv(dotenv_path=your_path) 行直接放入该类中。仅在夹具中使用它是不够的。
  • 不确定我是否理解,但您似乎找到了解决方案,所以这已为您解决,对吧?
【解决方案2】:

您可以使用 pytest 提供的 monkeypatch 夹具来操作 env 变量:

@pytest.fixture(scope="function")
def configured_env(monkeypatch):
    monkeypatch.setenv("SQLALCHEMY_DATABASE_URI", "sqlite:///")
    monkeypatch.setenv("JWT_SECRET_KEY", testing)
def test_client(configured_env):
 #env variables are set here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 2017-11-24
    • 2021-01-13
    • 2020-01-11
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多