模拟,导入和覆盖

时间:2014-04-29 12:10:36

标签: python mocking code-coverage

我正在编写一个小型控制台包装器,以便我们可以在控制台上使用一些漂亮的颜色。我使用的模块的简化版本在这里:

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 improt clog轻松编写一些单元测试,而clog的正确版本将根据神奇与否的存在而被选中。但是,一旦加载了clog lambda,就无法卸载它。因此,任何尝试测试(通过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 个答案:

答案 0 :(得分:1)

将此添加到您的tearDown()方法:

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

查看thisthis更一般的问题。