1

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

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

触发调用是必要的,因为我们需要更新映射而不想拔下并重新插入正在映射的设备。我的问题是“调用”行在某一点被删除,导致程序其他部分的副作用不明显,因此没有被捕获。

我通常的解决此类问题的方法是对该方法(写入映射文件并调用触发器)进行单元测试以强制执行预期的行为,但这种行为似乎超出了单元测试的范围。这是一个系统调用,更不用说 udevadm 触发器需要 sudo 访问权限。我不知道在这种情况下如何/模拟什么。

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

没有抛出一个大的“#永远不要删除这条线!” 在“呼叫”行上方,我可以在这里做些什么来防止将来将其删除吗?“不要删除”行很容易被忽略,比如一年后没有人知道它为什么在那里。

4

1 回答 1

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

这样做的灵感来自阅读有关行为驱动开发的文章。BDD 的整个想法对我来说是全新的,所以我不确定 BDD 支持者在风格/功能上会如何看待我的解决方案,但它确实符合我的要求 - 如果在未来。

我计划将来将其切换为使用monkeypatch,以便我可以创建一个可以检查状态的存根函数(调用触发器的顺序也很重要)。但是原理还是一样的:

  1. 包裹在一个可以模拟的方法中
  2. 编写测试以确保正确的功能行为
  3. 模拟包装方法
于 2012-10-17T17:08:53.280 回答