2

我正在研究一个 Python 模块,该模块假设从 SVN 签出一些代码并构建它。在对一些遗留代码进行大量重构之后,我得到了相当不错的代码覆盖率,但是,我在使用pysvn的代码中有一个巨大的漏洞。

诚然,Mock 对象的概念对我来说是新的,但是在阅读了MiniMockpymox的一些文档(两者都在我的环境中可用)之后,我得出的结论是我需要捕获一些 pysvn 输出并将其返回我的测试代码。

但在这里,我发现自己(请原谅双关语)陷入困境。当我尝试腌制它们,甚至比较它们时,从 pysvn.Client() 命令返回的对象表现不佳。

关于如何序列化或以其他方式模拟 pysvn 或其他一些非 Python 行为对象的任何建议?

自然地,我愿意接受我从错误的方向处理这个问题,或者我只是一个白痴。在这种情况下,任何建议都会有所帮助。

附加信息0:

某些pysvn对象可以dict通过访问它们的data属性来简化为 a,并且可以通过将其传递dict给适当的__init__()

例如:

>>> svn=pysvn.Client()
>>> svn.list('http://svn/svn/')[0][0]
<PysvnList u'http://svn/svn'>
>>> d=svn.list('http://svn/svn/')[0][0].data
>>> pysvn.PysvnList(d)
<PysvnList u'http://svn/svn'>

然而在这个对象内部可能有一些不可腌制的对象:

>>> cPickle.dumps(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
cPickle.UnpickleableError: Cannot pickle <type 'node_kind'> objects

附加信息1:

至于@H。Dunlop请求,这是我的代码的(简化)片段,它允许从 SVN 中获取列表,并让用户从该列表中选择一个项目:

class Menu(object):
    """a well covered class"""
    # ...

class VersionControl(object):
    """A poorly covered class"""

    def __init__(self):
        self.svn = pysvn.Client()

    # ...

    def list(self, url):
        """svn ls $url"""
        return [os.path.basename(x['path']) for (x,_) in self.svn.list(url)[1:]]

    def choose(self, choice, url):
        """Displays a menu from svn list, and get's the users choice form it.

        Returns the svn item (path).
        """
        menu = Menu(prompt="Please choose %s from list:\n" % choice,
                    items=self.list(url),
                    muliple_choice=False)
        menu.present()
        return menu.chosen()
4

2 回答 2

2

在这个答案中,我使用了 minimock,我实际上并不熟悉它,并建议改用http://www.voidspace.org.uk/python/mock/。这段代码最终会更干净一些。但是你指定了 minimock 或 pymox 所以这里是:

from minimock import TraceTracker, Mock, mock
import unittest

import pysvn

from code_under_test import VersionControl


class TestVersionControl(unittest.TestCase):


    def test_init(self):

        mock_svn = Mock(name='svn_client')
        mock('pysvn.Client', returns=mock_svn)

        vc = VersionControl()

        self.assertEqual(vc.svn, mock_svn)


    def test_list_calls_svn_list_and_returns_urls(self):

        tracker = TraceTracker()
        test_url = 'a test_url'
        mock_data = [
            ({'path': 'first result excluded'}, None),
            ({'path': 'url2'}, None),
            ({'path': 'url3', 'info': 'not in result'}, None),
            ({'path': 'url4'}, None),
        ]

        vc = VersionControl()
        mock('vc.svn.list', returns=mock_data, tracker=tracker)

        response = vc.list(test_url)
        self.assertEqual(['url2', 'url3', 'url4'], response)
        self.assertTrue("Called vc.svn.list('a test_url')" in tracker.dump())


if __name__ == '__main__':
    unittest.main()

如果你想测试更多由 pysvn 返回的底层字典,那么你可以修改包含字典的元组列表,让它返回。您甚至可以编写一些代码,将字典从 pysvn 对象中转储出来。

于 2012-07-03T00:20:40.767 回答
0

您是否考虑过使用:pickle 代替 cPicles?“ cPickle 模块的可调用函数 Pickler() 和 Unpickler() 是函数,而不是类。这意味着您不能使用它们来派生自定义酸洗和解酸子类。

于 2012-07-02T22:43:32.233 回答