Pytest: как издеваться над переменной метода класса класса команды управления django

Существует команда менеджера django, которая работает с файлом csv. app/my_app/my_command.py

class Command(BaseCommand):
    def handle(self,  *args, **options):
        path = (os.path.join(os.path.abspath(os.path.dirname(__name__)), 'data.csv'))
        # other logic with file

Я пишу тест для этого в pytest, проблема в том, что я не могу понять, как подружить переменную path для проверки доступа не к реальному data.csv, а к временному test.csv файлу

@pytest.fixture
def create_test_csv_file(tmpdir_factory):
    path = tmpdir_factory.mktemp('data').join('test.csv')
    # other logic
    return str(path)

@pytest.mark.django_db
def test_function(mocker, create_test_csv_file):
   # smth like mock_path =  create_test_csv_file  <- NEW CODE HERE
    call_command('my_command')

Вы можете сделать path аргументом со значением по умолчанию. В тесте вы можете передать путь к тестовому файлу.

class Command(BaseCommand):
    def add_arguments(self, parser):
        parser.add_argument(
            "--path",
            dest="path",
            default=os.path.join(os.path.abspath(os.path.dirname(__name__)), 'data.csv')
        )

    def handle(self, *args, **options):
        path = options.get("path")
        ...

Тогда в тестах вы можете вызывать call_command('my_command', path=<path>)

Вы не можете высмеять локальную переменную path, но вы можете высмеять место, откуда она была получена, то есть из os.path.join.

src.py

import os

class Command:
    def handle(self):
        path = (os.path.join(os.path.abspath(os.path.dirname(__name__)), 'data.csv'))
        print(path)
        return path

test_src.py

from src import Command


def test_real_path(mocker, tmp_path):
    result = Command().handle()
    assert str(result).endswith("data.csv")  # Real file


def test_mock_path(mocker, tmpdir_factory):
    path = tmpdir_factory.mktemp('data').join('test.csv')
    mocker.patch("os.path.join", return_value=path)  # Or "src.os.path.join"

    result = Command().handle()
    assert str(result).endswith("test.csv")  # Test file
    assert result == path

Выход:

$ pytest -q -rP
..
[100%]
================================================================================================= PASSES ==================================================================================================
_____________________________________________________________________________________________ test_real_path ______________________________________________________________________________________________
------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------
/home/nponcian/Documents/data.csv
_____________________________________________________________________________________________ test_mock_path ______________________________________________________________________________________________
------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------
/tmp/pytest-of-nponcian/pytest-15/data0/test.csv
2 passed in 0.06s
Вернуться на верх