Python 如何模拟pysvn
我正在开发一个Python模块,该模块假设要从SVN签出一些代码并构建它。在对一些遗留代码进行了大量重构之后,我对代码进行了相当不错的覆盖,但是,我使用的代码中有一个很大的漏洞 诚然,Mock对象的概念对我来说是新概念,但在阅读了and的一些文档(两者都在我的环境中可用)后,我得出结论,我需要捕获一些pysvn输出,并将其返回到测试代码中 但在这里,我发现自己(请原谅我的双关语)陷入了困境。当我试图对pysvn.Client()命令返回的对象进行pickle处理,甚至比较它们时,这些对象的行为并不好 有没有关于如何序列化或以其他方式模拟pysvn或其他一些非pythonic行为的对象的建议 当然,我愿意接受我从错误的方向处理这个问题,或者我只是一个白痴。在这种情况下,任何建议都会有帮助 附加信息0: 一些Python 如何模拟pysvn,python,svn,mocking,tdd,pysvn,Python,Svn,Mocking,Tdd,Pysvn,我正在开发一个Python模块,该模块假设要从SVN签出一些代码并构建它。在对一些遗留代码进行了大量重构之后,我对代码进行了相当不错的覆盖,但是,我使用的代码中有一个很大的漏洞 诚然,Mock对象的概念对我来说是新概念,但在阅读了and的一些文档(两者都在我的环境中可用)后,我得出结论,我需要捕获一些pysvn输出,并将其返回到测试代码中 但在这里,我发现自己(请原谅我的双关语)陷入了困境。当我试图对pysvn.Client()命令返回的对象进行pickle处理,甚至比较它们时,这些对象的行为并
pysvn
对象可以通过访问其数据
属性而简化为dict
,并且可以通过将该dict
传递到相应的\uuu init\uuu()中来复制
例如:
>>> 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'>
你考虑过用:pickle代替cPicles吗?
“cPickle模块可调用的Pickler()和Unpickler()是函数,而不是类。这意味着您不能使用它们派生自定义pickle和unpickle子类。”在这个回答中,我使用了minimock,实际上我对它不太熟悉,建议改用minimock。这段代码最终会更干净一些。但您指定了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对象中转储字典。您可以进一步阐述为什么需要pickle这些实际对象吗?您可以模拟pysvn的返回值,然后断言使用返回值调用cPickle.dumps。有时候不值得深入研究。对不起,我误读了这个问题。我的实际评论是,为什么你要腌制这些东西?这是你的模拟库的限制吗?我不知道我是否需要腌制任何东西。然而,我的代码处理pysvn
命令的返回值,因此我需要一种方法来处理一些东西。我错了吗?好吧,我在一家严格的TDD商店工作,我很高兴能通过模拟之类的方式进行测试。你能用测试中的代码样本来扩展你的问题吗?只举一个使用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()
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()