模拟、导入和覆盖率

0 投票
1 回答
638 浏览
提问于 2025-04-18 04:44

我正在写一个小工具,用来给控制台添加一些好看的颜色。这里有我使用的模块的简化版:

from sys import stderr
try:
    from fabulous.color import fg256
    clog = lambda x: stderr.write(
        str(fg256(63, u'\u26A0 ' + str(x).encode('utf-8') + '\n').as_utf8))
except ImportError:
     _green = '\033[1;32m'
     _default = '\033[1;m'
     clog = lambda x: stderr.write(_green +
                                   u'\u26A0 ' +
                                   str(x).encode('utf-8') +
                                   _default +
                                   '\n')

我可以很容易地使用 from mycolour import clog 来写一些单元测试,根据是否有好看的颜色,合适版本的 clog 会被加载。不过,一旦 clog 这个函数被加载后,就不能再卸载它。因此,任何通过 py.test 测试代码的尝试都会失败,尤其是在测试第二条路径时。

我该如何做到让测试覆盖率达到100%呢?

这是我现在的测试脚本:

try:
    import builtins
except ImportError:
    import __builtin__ as builtins
import unittest
from mock import MagicMock
from mock import patch
from mock import call


class ColourFabulousTest(unittest.TestCase):

    def setUp(self):
        pass

    @patch('mycolours.stderr')
    def test_fabulous_clog(self, err):
        from mycolours import clog
        err.write = MagicMock()
        clog('ook')
        self.assertTrue(err.write.called)
        self.assertEqual([call('\x1b[38;5;63m\xe2\x9a\xa0 ook\n\x1b[39m')],
                         err.write.call_args_list)

    def tearDown(self):
        pass


class ColourANSITest(unittest.TestCase):

    def setUp(self):
        self.realimport = builtins.__import__
        def myimport(name, globals, locals, fromlist, level=0):
            if name == 'fabulous.color':
                raise ImportError
            return self.realimport(name, globals, locals, fromlist, level)
        builtins.__import__ = myimport

    def test_ansi_clog(self):
        from mycolours import clog
        builtins.__import__ = self.realimport
        with patch('mycolours.stderr') as err:
            clog('ook')
            self.assertTrue(err.write.called)
            self.assertEqual([call(u'\x1b[1;32m\u26a0 ook\x1b[1;m\n')],
                             err.write.call_args_list)

    def tearDown(self):
        builtins.__import__ = self.realimport

1 个回答

1

在你的 tearDown() 方法里加上这个:

try:
    del sys.modules['mycolours']
except KeyError:
    pass

可以看看 这个这个 更一般的问题。

撰写回答