首页 文章

更严格的Python代码覆盖率报告

提问于
浏览
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() ,其中任何一个's underlying functions. Our report is showing fantastic coverage for the entire project! Send it to the PO and let'都需要一个周末!

这虽然有误导性 . 我真正希望报告显示的是 Class2 ,因为我们编写了一个可靠地覆盖模块的单元测试 . 我 don't 希望它显示 Class1 被覆盖,因为我们没有't have any unit tests that check it'的内部功能 . 它只是假设 Class1 正常工作,如果单元测试失败,如果 Class1 出错,它的描述将不会非常有用也不透明 .

所以,简化:

通过单元测试适当覆盖

  • Class2

  • Class1 直接覆盖了 no 并使项目面临风险

  • 运行单元测试并生成代码覆盖率报告时,它会错误地显示两个模块并进行了测试

  • 相反,我希望报告显示 Class2 被覆盖,因为 foo() 被测试显式调用, Class1 未被覆盖,因为它的函数在 Class2.foo() 内被调用

这引出了以下问题:

  • 有没有办法防止在覆盖率报告中发生这种情况?

  • 用于引用此类保险的术语(如果有的话)是什么?

  • 是否有特定的编码模式有助于防止此问题?

谢谢!

1 回答

  • 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测试中,您测试每个函数并尝试查看其工作情况,而不关心依赖函数是否有效 .

相关问题