代码之家  ›  专栏  ›  技术社区  ›  guidoism

在Python中,在单元测试期间禁用某些代码的好模式是什么?

  •  10
  • guidoism  · 技术社区  · 15 年前

    一般来说,我想禁用尽可能少的代码,我希望它是明确的:我不希望被测试的代码决定它是否是一个测试,我希望测试告诉代码“嘿,顺便说一句,我正在运行一个单元测试,你能不能不要打电话给solr,相反,你能不能把你要发送给solr的东西贴在这个位置上,这样我就可以检查一下。我有我的想法,但我不喜欢其中的任何一个,我希望有一个好的蟒蛇方法来做到这一点。

    6 回复  |  直到 15 年前
        1
  •  5
  •   manifest    15 年前

    使用迈克尔·福德的 Mock 在单元测试中,请执行以下操作:

    from mock import Mock
    
    class Person(object):
        def __init__(self, name):
            super(Person, self).__init__()
            self.name = name
    
        def say(self, str):
            print "%s says \"%s\"" % (self.name, str)
    
    
    ...
    
    #In your unit test....
    #create the class as normal
    person = Person("Bob")
    #now mock all of person's methods/attributes
    person = Mock(spec=person)
    #talkto is some function you are testing
    talkTo(person)
    #make sure the Person class's say method was called
    self.assertTrue(person.say.called, "Person wasn't asked to talk")
    
    #make sure the person said "Hello"
    args = ("Hello")
    keywargs = {}
    self.assertEquals(person.say.call_args, (args, keywargs), "Person did not say hello")
    
        2
  •  7
  •   Community CDub    7 年前

    你可以使用 Mock objects 截获您不想执行的方法调用。 例如,你上了一些课 A ,在不需要方法的地方 no() 在测试中被调用。

    class A:
      def do(self):
        print('do')
      def no(self):
        print('no')
    

    模拟对象可以继承自 超驰 () 什么也不做。

    class MockA(A):
      def no(self):
        pass
    

    然后创建 MockA 对象而不是 在您的测试代码中。另一种模仿的方法是 莫卡 实现一个公共接口 InterfaceA .

    有大量的模拟框架可用。参见 StackOverflow: Python mocking frameworks .

    具体见: Google's Python mocking framework .

        3
  •  1
  •   guidoism    15 年前

    我遇到的大问题是依赖注入的机制。我现在已经把那部分算出来了。

    我需要在两个地方以完全相同的方式导入模块,以成功地注入新代码。例如,如果我有以下要禁用的代码:

    from foo_service.foo import solr
    solr.add(spam)
    

    在我的测试运行程序中,我似乎无法执行此操作:

    from foo import solr
    solr = mock_object
    

    python解释器必须处理模块 foo_service.foo foo 作为不同的条目。我变了 from foo import solr 更明确地说 from foo_service.foo import solr 我的模拟对象被成功注入。

        4
  •  0
  •   Daniel    15 年前

    通常情况下,当出现这种情况时,您可以使用猴子修补(也称为鸭子穿孔)来达到所需的效果。退房 this link 了解更多关于猴子修补的信息。

    例如,在本例中,您将覆盖solr以只打印您要查找的输出。

        5
  •  0
  •   Community CDub    7 年前

    你有两种方法可以做到这不是 或最小 DI , 对源代码的修改

    这个 cleanest 使用方式 dependency injection 但是 I don't really like extensive monkeypatching 还有一些事情是不可能/很难做到的 dependency injection 容易。

        6
  •  0
  •   kriss    15 年前

    我知道这是模拟对象的典型用例,但这也是一个古老的论点…模拟物体到底是必要的还是必要的? 邪恶的 ?

    我支持那些相信嘲笑的人 邪恶的 并尽量避免更改测试代码。我甚至认为修改测试代码的这种需要是一种代码味道…

    如果您希望更改或拦截内部函数调用以进行测试,您也可以在安装时将此函数设置为一个显式的外部依赖项集,由生产代码和测试代码提供。如果你这样做,问题就消失了,最终你得到了一个更干净的界面。

    注意,这样做根本不需要更改测试代码,无论是在内部还是通过正在执行的测试。