在unittest中如何正确清除导入的模块?

1 投票
1 回答
1709 浏览
提问于 2025-04-18 00:50

我正在对一个叫做Pigso的类进行单元测试,这个类在pigso模块里。

class Pigso(object):

    _count = 0

    def __init__(self):
        self.__class__._count += 1
        self.ident = self.__class__._count


我设置了一个单元测试,目的是检查第三个Pigso对象的self.ident是否等于3。

import unittest
import pigso


class TestPigID(unittest.TestCase):

    def setUp(self):
        reload(pigso)
        from pigso import Pigso
        self.pig1 = Pigso()
        self.pig2 = Pigso()
        self.pig3 = Pigso()

    def test_dummy(self):
        self.assertEqual(2 + 2, 4)

    def test_pig_ident(self):
        self.assertEqual(self.pig3.ident, 3,
                         msg="Pigso 'ident' {0} should be 'ident' 3"
                         .format(self.pig3.ident))

我有两个问题:

1) 为什么这个方法需要‘导入’、‘重载’和‘从模块导入’这三步?(这个是根据错误信息猜出来的)

2) 有没有更优雅的Python方式?我了解到,单元测试的方法要求每个测试用例的环境都要完全清理干净并重新建立。如果我没理解错,这就需要一个方法来恢复导入的单元和类到它们最初加载到测试单元时的状态。

...后来...
根据TheoretiCAL的回答和进一步的研究,我开始觉得正确的Python方式是要在测试的清理阶段显式或隐式地删除超类对象†。 如果是隐式的,那么单元测试需要修改;如果是显式的,那我需要添加一个tearDown方法,里面调用Pigso.destroy.__superclass__()。据我所知,这个函数在Python中还不可用。
我认为在单元测试的导入部分和测试准备阶段组织删除超类对象的做法既不符合Python的风格,也不符合单元测试的核心设计理念。

我很想听听其他人对此的看法,特别是关于如何实现Pigso.destroy.__superclass__的想法。

†我对‘超类对象’的理解是,它是_count所在的地方。

1 个回答

0
  1. 整体来说,所有的单元测试应该是相互独立的,这就是为什么在每个测试案例运行之前都会有一个设置函数。这个设置函数里有个重载的操作,因为如果没有它,当模块的状态发生变化时,你的测试就不再独立了。你用来获取对象的那条语句是必须的,无法避免。

  2. 根据你提供的测试,如果你只是检查缩进的话,可以去掉test_dummy,这样只保留一个测试案例,就可以去掉导入和重载的语句了。

撰写回答