Luigi 参数默认值和模拟
Posted
技术标签:
【中文标题】Luigi 参数默认值和模拟【英文标题】:Luigi parameter default values and mocks 【发布时间】:2015-09-09 13:29:46 【问题描述】:我正在尝试模拟为 luigi 参数提供默认值的东西。
一个愚蠢的例子展示了我想要完成的事情:
正在测试的任务:
import luigi
from bar import Bar
bar = Bar()
class Baz(luigi.Task):
qux = luigi.Parameter(default=bar.bar())
def baz(self):
return self.qux;
def foo(self):
return bar.bar()
单元测试代码:
import unittest
from mock import Mock, patch
from sut.baz import Baz
class TestMocking(unittest.TestCase):
def test_baz_bar(self):
self.assertEquals("bar", Baz().baz())
@patch('sut.baz.bar')
def test_patched_baz(self, mock_bar):
mock_bar.bar = Mock(return_value="foo")
self.assertEquals("foo", (Baz().baz()))
@patch('sut.baz.bar')
def test_patched_foo(self, mock_bar):
mock_bar.bar = Mock(return_value="foo")
self.assertEquals("foo", (Baz().foo()))
luigi.Parameter 逻辑似乎比补丁更早发生。
在本例中,test_patched_foo
通过,test_patched_baz
失败。所以补丁确实发生了,但发生在来自luigi.Parameter(default=bar.bar())
行的调用之后。
是否可以模拟和修补以这种方式调用的东西?
【问题讨论】:
在实际代码中,我通过延迟加载解决了这个问题。在我的玩具示例中复制解决方案时遇到问题,因此我不会将其作为自我答案发布。但我也不是特别喜欢这种解决方法。 【参考方案1】:尝试将qux = luigi.Parameter(default=bar.bar())
行移动到Baz
类的__init__
方法中。将它放在__init__
之外,它是在类定义时设置的,而不是实例创建,但是将它放入__init__
将延迟它的创建到Baz
实例创建的位置。不要忘记在super
类上调用__init__
:
class Baz(luigi.Task):
def __init__(self, *args, **kwargs):
super(Baz, self).__init__(*args, **kwargs)
self.qux = luigi.Parameter(default=bar.bar())
...
【讨论】:
一个有前途的想法,但与 luigi 参数的工作方式不兼容。qux = luigi.Parameter(default=bar.bar())
行创建了一个字段,稍后可以将其引用为 self.qux
但它不是 luigi.Parameter
- 它是传递的值或默认规范的结果,在这种情况下是一个字符串。可能有一种方法可以绕过它并使用更标准的kwargs.pop
默认值,但我不确定 luigi 会喜欢它。不过可以试试看。以上是关于Luigi 参数默认值和模拟的主要内容,如果未能解决你的问题,请参考以下文章