2016-11-18 128 views
0

假设我在我的项目中的两个Python模块:严格的报告的代码覆盖率

/project 
    /module1 
    __init__.py [Empty] 
    class1.py 
    /module2 
    __init__.py [Empty] 
    class2.py 

Class1有一定的功能,但重要的是doEverythingAndGetData()。让我们假装它在执行几个内部函数时返回一个数字。

现在假设Class2使用Class1,然后实现了其他功能。 Class2只有两个功能 - __init__foo()

def foo(self): 
    #Create an instance of Class1 
    class1 = Class1() 

    #Get some information using class1 
    data = class1.doEverythingAndGetData() 

    #Do some logic on the data, it doesn't matter 
    result = (data + 10) * 2 

    #Return the result 
    return result 

现在我想写一个包含foo()的Class2的单元测试。

def test_Class2_foo(): 
    #Create the Class2 object 
    class2 = Class2() 

    #Get the result 
    bar = class2.foo() 

    #Compare the value 
    expectedBar = 1337 
    assert expectedBar == bar, "Mismatch! {} != {}".format(expectedBar, bar) 

该单元测试是唯一为该项目编写的测试。我们运行单元测试并生成代码覆盖率报告。

检查代码覆盖报告后,我们将看到Class2已被很好地覆盖,因为我们已经进行了单元测试,并且它正在做它应该做的事情。太棒了!

然而,我们也注意到,Class1也很好地覆盖,作为单元测试覆盖class1.doEverythingAndGetData()和任何它的基础功能。我们的报告展示了整个项目的精彩内容!将它发送给采购订单,让我们尽早周末吧!

虽然这是误导。我真的想要报告显示Class2被覆盖,因为我们已经编写了一个可靠地覆盖模块的单元测试。我不要希望它显示Class1被覆盖,因为我们没有任何单元测试,检查它的内部功能。它只是假设Class1正常工作,如果单元测试失败,它的描述将不会很有帮助,也不透明,如果Class1是错误的。

因此,要简化:

  • Class2通过单元测试适当覆盖
  • Class1没有直接覆盖,并把该项目在风险
  • 当单元测试运行,并且代码覆盖率报告生成,它不正确地显示模块以及测试
  • 而是,我想报告显示t帽子Class2覆盖,为foo()明确由测试调用,Class1不是盖的,因为它的功能范围内Class2.foo()

这使我对以下问题称为:

  1. 是否有一个方法来防止在覆盖报告中发生这种情况?
  2. 什么,如果有的话,是用来指称这种类型的覆盖?
  3. 有没有特定的编码模式可以帮助防止这个问题?

谢谢!

+0

您需要为'class1.doEverythingAndGetData()'提供一个虚拟号码。因此,'doEverythingAndGetData()'函数永远不会被调用,它只是返回一个值。这叫做'unittest.mock' – martianwars

回答

1

您需要mock来自class1.doEverythingAndGetData()的数据。在您当前的实现中,每当您调用class2的unittest时,该函数内的实际代码正在运行。像这样的事情会帮助你,

from mock import patch 
import class1 

@patch('class1.doEverythingAndGetData') 
def test_Class2_foo(self, doEverythingAndGetData): 
    # Let's assume we are mocking 10 as the return value 
    doEverythingAndGetData.return_value = 10 

    class2 = Class2() 

    # This will take mocked value in its implementation 
    bar = class2.foo() 

    #Compare the value 
    expectedBar = 1337 
    assert expectedBar == bar, "Mismatch! {} != {}".format(expectedBar, bar) 

现在你可以写class1.doEverythingAndGetData()单独unittest,并得到正确的覆盖报告!

所以回答您的3个问题,

是否有办法防止这种情况的覆盖率报告发生了什么?

有没有特定的编码模式可以帮助防止这个问题?

是的!使用mock

什么,如果有的话,是用来指称这种类型的覆盖?

从某种意义上说,您所做的可以参考integration测试,其中您可以针对一系列输入组合测试多个功能。另一方面,在unit测试中,您每函数测试,并尝试查看其工作,而不关心依赖函数是否工作。

+0

你好,谢谢你的详细回复。我会尝试这个解决方案,看看它是否符合我的需求,但它看起来应该是这样!但是,假设'class1.doEverythingAndGetData()'返回的是比'10'更复杂的对象。对于这种情况,这是否会起作用? – Grassman7z7

+0

是的,你需要相应地模拟数据。尝试在模拟不同代表性数据的地方进行多个单元测试 – martianwars

相关问题