单元测试python udev交互

时间:2012-10-16 02:33:23

标签: python udev

我继承了一些编写新的'/etc/udev/rules.d'映射文件的python代码,然后对udev进行子进程调用,让它刷新其设备列表:

call(['/sbin/udevadm', 'trigger', '--action=change'])

触发器调用是必要的,因为我们需要更新映射而不需要拔出并插回正在映射的设备。我的问题是'call'行被删除了一次,导致程序的其他部分出现非明显的副作用,因此没有被捕获。

我通常的修复方法是对此方法(写入映射文件并调用触发器)进行单元测试以强制执行预期的行为,但这种行为似乎超出了单元测试的范围。这是一个系统调用,更不用说udevadm触发器需要sudo访问。在这个例子中,我无法弄清楚如何模拟出来。

我考虑使用pyudev库,因为我看到它可以模拟udev的某些行为,但看起来它不能模拟触发器行为(甚至可以访问它)。

没有抛出一大笔“#DO NOT DELETE THIS LINE EVER!”在“呼叫”线之上,我可以做些什么来防止将来被删除吗? “不要删除”的行很容易被忽略,比如从现在起一年后没有人知道为什么它会在那里。

1 个答案:

答案 0 :(得分:1)

这是我决定在这个例子中做的事情,如果有人不同意我的回答,请加入!

这是两个人。

首先,我把我关注的电话包裹起来,然后在我的代码中直接“调用”。

class UdevWrapper:
    def udevadm_trigger(self):
        call(['/sbin/udevadm', 'trigger', '--action=change'])

(该类包含的不仅仅是这个,为了清楚起见,这里简化了一下)

接下来,我嘲笑了包装器方法并进行了测试,以确保它被称为

@patch.object(utils.UdevWrapper,'udevadm_trigger')
def test_trigger_called(self,mock_udevadm_trigger):
    mock_udevadm_trigger.return_value = True

    # name changed for clarity
    ClassWhereTriggerCalled.func()
    assert mock_udevadm_trigger.called

以这种方式这样做的灵感来自阅读Behaviour Driven Development。 BDD的整个想法对我来说都是全新的,所以我不确定BDD支持者对我的解决方案的风格/功能如何,但是我做了我想要的 - 如果这行代码被删除,那么显然会破坏我的测试(我的测试)将来

我打算将来切换到使用 monkeypatch ,这样我就可以创建一个可以检查状态的存根函数(调用触发器的顺序也很重要)。但原则保持不变:

  1. 包装可以模拟的方法
  2. 编写测试以确保正确的功能行为
  3. 模拟包裹方法