Протестируйте настройки Django с помощью pytest

Я пытаюсь установить некоторые переменные среды, которые управляют конфигурацией проекта Django в некоторых тестах, чтобы я мог издеваться над некоторыми значениями и делать утверждения более простыми и явными.

Я хочу установить переменную среды с именем файла, в котором хранится некоторая конфигурация, которая загружается, если переменная установлена ​​и файл существует. то есть:

# proj.settings.py

CONFIG = None
if _filename := os.environ.get('FILE_PATH', None):
    with open(_filename) as f:
        CONFIG = json.load(f)

Я попробовал фикстуру, которая устанавливает переменную окружения (см. set_env), поэтому мои тесты выглядят так:

# some_app.tests.test_settings.py

import os

@fixture
def data_raw():
    return dict(
        foo = "bar"
    )

@fixture
def data_file(data_raw):
    with NamedTemporaryFile(mode = "w+") as f:
        json.dump(data_raw, f)
        yield f.name

@fixture
def set_env(data_file):
    os.environ['FILE_PATH'] = data_file

def test_it_loads_data(set_env, data_raw, settings):
    assert settings.CONFIG == data_raw

Но set_env не выполняется перед конфигурацией Django, поэтому CONFIG никогда не устанавливается.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Настройки Django запускаются во время импорта, поэтому они будут выполняться до любого фикстура.

Вероятно, вы могли бы обойти это, установив переменную среды во время импорта:

os.environ['FILE_PATH'] = ...

def test_it_loads_data(set_env, data_raw, settings):
    assert settings.CONFIG == data_raw

Но, сказав это, я не думаю, что это лучший подход для проверки этого. Я думаю, что предпочтительнее вынести эту логику в отдельную функцию, а затем протестировать ее саму:

# utils.py
def loan_config():
    if _filename := os.environ.get('FILE_PATH', None):
        with open(_filename) as f:
            return json.load(f)
    return None

# settings.py
CONFIG = loan_config()

Затем вы тестируете load_config саму по себе:

from tempfile import NamedTemporaryFile
import json

def test_load_config():
    mock_data = {"key": "value"}

    # Create a temp file with the mock data
    with NamedTemporaryFile("w", suffix = ".json", delete=False) as temp_file:
        json.dump(mock_data, temp_file)
        temp_file.close()

        # Store the temp file path in an env variable
        os.environ["FILE_PATH"] = temp_file.name

        # Call the loan_config function
        result = loan_config()

        # Assert that the function returns the file parsed by json
        assert result == mock_data

        # Clean up the temp file
        os.remove(temp_file.name)

Вам также, вероятно, следует восстановить предыдущее значение env FILE_PATH после завершения теста. В противном случае это будет «дырявый» тест.

Другие вопросы по теме