2

我有一个以迭代方式构建的对象。我想测试每一步。这是一个糟糕的测试功能:

def test_object:
    o = object.Object()
    o.step1()  # in place method
    assert(o.step1property)
    o.step2()  # in place method
    assert(o.step2property)
    o.step3()  # in place method
    # ...

因此,在每一步之后,我都会检查对象是否具有一些应该存在的所需属性。我可以使用 yield 关键字将其拆分为子测试,例如:

def test_object:
    o = object.Object()
    yield o.step1
    assert(o.step1property)
    yield o.step2
    # ...

此时您可能会问:为什么不将这些调用放在单独的测试中呢?如果他们需要前一个结果的正确输出,请将其放在 .pickle 文件中并使其独立。我大体上同意。但是,我有一个用例不是很有帮助:假设 step1() 初始化类,而 step2() 是 JSON 导出。然后我需要确保即使我在 step1() 中更改内容,JSON 导出也始终有效。依赖 .pickle 文件会很危险,因为它们可能已过时,并且 JSON 导出可能会通过,而实际上它会因我的最新对象而失败。我可以在两个单独的测试中将断言分开并运行step1()两次(一次在它自己的测试中,一次在测试 2 的设置方法中),但是step1()非常耗时。

这样做的首选方法是什么?有没有办法调用“子测试”而不是产量,我可以获得这些子测试的返回值吗?就我而言,我很想拥有 JSON 字符串,因为我将所有测试结果保存到输出目录,并且我想将字符串传递给write_to_output_dir函数(如果这是糟糕的设计,请告诉我!)。

4

1 回答 1

3

如果一个类很难像这样测试,那么你很有可能在面向对象的设计中做了一些不太理想的事情。如果你有空的话,看看这个关于单元测试的技术讲座。它还处理良好的(如可测试的)OO 设计。

tl;博士本质上,使单元测试尽可能原子化是一种好习惯。此外,您可以模拟未在特定单元测试中测试的不相关功能。

专注于您的示例:您想独立检查初始化。我想这是一种工厂。然后你就有了一个导出到 JSON 的方法。这可能是您要模拟初始化对象并在此模拟上测试 JSON 导出的关键点。也就是说,JSON 导出器可能也应该是一个单独的类,以避免将初始化与操作逻辑混为一谈。重构代码后,您可能会发现测试它要容易得多。

于 2013-08-29T15:25:33.470 回答