如何通过测试修改类数据?

2024-06-29 00:43:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个luigi任务,它需要的输入是“test_file.txt”。我想通过测试类来更改所需的输入。我需要更改输入,以便可以使用文件测试类的功能。我尝试了下面的代码,但打印的结果仍然是初始路径--“test_file.txt”。如何仅在测试中更改路径?(以获取“data.json”作为打印结果

import pytest
import luigi


class LuigiToBeTested(luigi.ExternalTask):
    def requires(self):
        return luigi.LocalTarget("test_file.txt")


def test_Luigi():
    class_instance = LuigiToBeTested()
    class_instance.requires().path = 'data.json'
    print('/////', class_instance.requires().path) #to get data.json


Tags: 文件pathinstancetestimport路径txtjson
1条回答
网友
1楼 · 发布于 2024-06-29 00:43:14

这里有3个解决方案

  1. test_luigi_1-截取(通过函数)初始化luigi.LocalTarget的新对象并替换输入文件名的所有调用

  2. test_luigi_2-与1相同,但通过子类

  3. test_luigi_3-不要像1和2中那样进行修补,而是通过允许dependency injection重新设计源代码以使其可测试。这是一种更具扩展性的方式,也更能证明未来

    aAsk for things, Don't look for things (aka Dependency Injection / Law of Demeter)

    bFixing the Client API: Dependency Injection

    c。还有更多关于为什么这是首选方式的参考资料

import luigi
import pytest


class LuigiToBeTested(luigi.ExternalTask):
    def requires(self):
        return luigi.LocalTarget("test_file.txt")


class LuigiToBeTested2(luigi.ExternalTask):
    def requires(self, file_name):
        return luigi.LocalTarget(file_name)


@pytest.fixture
def amend_local_target_func_based(mocker):  # The <mocker> fixture is from pytest-mock. Install via <pip install pytest-mock>.
    orig = luigi.LocalTarget

    def fake(file_name):
        print(f"Intercepted initialization of luigi.LocalTarget via function. The file {file_name} might be replaced.")

        # If you only want to replace 'test_file.txt' but not the other files, then use this.
        # Otherwise, remove this if and just read from 'data.json' always.
        if file_name == 'test_file.txt':
            file_name = 'data.json'

        return orig(file_name)

    mocker.patch('luigi.LocalTarget', new=fake)



@pytest.fixture
def amend_local_target_class_based(mocker):
    class LocalTargetStub(luigi.LocalTarget):
        def __init__(self, file_name):
            print(f"Intercepted initialization of luigi.LocalTarget via subclass. The file {file_name} might be replaced.")

            # If you only want to replace 'test_file.txt' but not the other files, then use this.
            # Otherwise, remove this if and just read from 'data.json' always.
            if file_name == 'test_file.txt':
                file_name = 'data.json'

            super().__init__(file_name)

    mocker.patch('luigi.LocalTarget', new=LocalTargetStub)


def test_luigi_1(amend_local_target_func_based):
    class_instance = LuigiToBeTested()
    print('/////', class_instance.requires().path) #to get data.json


def test_luigi_2(amend_local_target_class_based):
    class_instance = LuigiToBeTested()
    print('/////', class_instance.requires().path) #to get data.json


def test_luigi_3():
    class_instance = LuigiToBeTested2()
    print('/////', class_instance.requires('data.json').path) #to get data.json
$ pytest -q -rP
================================================================================================= PASSES ==================================================================================================
______________________________________________________________________________________________ test_luigi_1 _______________________________________________________________________________________________
                                              Captured stdout call                                              -
Intercepted initialization of luigi.LocalTarget via function. The file test_file.txt might be replaced.
///// data.json
______________________________________________________________________________________________ test_luigi_2 _______________________________________________________________________________________________
                                              Captured stdout call                                              -
Intercepted initialization of luigi.LocalTarget via subclass. The file test_file.txt might be replaced.
///// data.json
______________________________________________________________________________________________ test_luigi_3 _______________________________________________________________________________________________
                                              Captured stdout call                                              -
///// data.json
3 passed, 1 warning in 0.07s

相关问题 更多 >