在 Python 中测试私有方法:单元测试还是功能测试?

dar*_*sky 7 python unit-testing

在阅读了关于在 Python 中测试私有方法的内容后,具体参考以下接受的答案:如何对方法对象中的方法进行单元测试?,看来最好只测试公共接口。但是,我的班级看起来像这样:

class MyClass:

  def __init__(self):
    # init code

  def run(self):
    self.__A()
    self.__B()
    self.__C()
    self.__D()

  def __A(self):
    # code for __A

  def __B(self):
    # code for __B

  def __C(self):
    # code for __C

  def __D(self):
    # code for __D
Run Code Online (Sandbox Code Playgroud)

本质上,我创建了一个类,用于通过函数管道处理一些输入数据。在这种情况下,最好测试私有函数而不测试公共run()函数吗?做这个的最好方式是什么?

Nat*_*ord 27

Python 在将实际执行的代码放在一起时会进行一些名称修改。因此,如果你有一个私有方法__AMyClass,你需要像这样在你的单元测试运行它:

from unittest import TestCase

class TestMyClass(TestCase):
    def test_private(self):
        expected = 'myexpectedresult'
        m = MyClass()
        actual = m._MyClass__A
        self.assertEqual(expected, actual)
Run Code Online (Sandbox Code Playgroud)

问题是关于由单个下划线界定的所谓“受保护”值。这些方法名称没有被破坏,可以简单地显示出来:

from unittest import TestCase

class A:

    def __a(self):
        return "myexpectedresult"

    def _b(self):
        return "a different result"


class TestMyClass(TestCase):

    def test_private(self):
        expected = "myexpectedresult"
        m = A()
        actual = m._A__a()
        self.assertEqual(expected, actual)

    def test_protected(self):
        expected = "a different result"
        m = A()
        actual = m._b()
        self.assertEqual(expected, actual)
        # actual = m._A__b() # Fails
        # actual = m._A_b()  # Fails
Run Code Online (Sandbox Code Playgroud)

  • 正是我正在寻找的,应该是公认的答案 (3认同)

Ben*_*dee 14

首先,你可以访问“私人”的东西,不是吗?(或者我在这里遗漏了什么?)

>>> class MyClass(object):
...     def __init__(self):
...             pass
...     def __A(self):
...             print('Method __A()')
... 
>>> a=MyClass()
>>> a
<__main__.MyClass object at 0x101d56b50>
>>> a._MyClass__A()
Method __A()
Run Code Online (Sandbox Code Playgroud)

但是MyClass如果你必须测试内部的东西,你总是可以编写一个测试函数:

class MyClass(object):
    ...
    def _method_for_unit_testing(self):
        self.__A()
        assert <something>
        self.__B()
        assert <something>
        ....
Run Code Online (Sandbox Code Playgroud)

当然,这不是最优雅的方法,但它只是类底部的几行代码。

  • 您不应该将测试代码放入生产代码中。 (22认同)
  • 这是编写代码的超级危险方式 - 您的生产值中不应该有任何用于测试的代码 - 至少它会提供误报,最坏的情况可能导致所述代码意外在生产中运行。请任何搜索此内容的人不要使用此答案。 (3认同)