【发布时间】:2014-11-18 15:34:44
【问题描述】:
我的 Fake Mock Class 如下所示:
class FakeResponse:
method = None #
url = None # static class variables
def __init__(self, method, url, data):#, response):
self.status_code = 200 # always return 200 OK
FakeResponse.method = method #
FakeResponse.url = url #
@staticmethod
def check(method, url, values):
""" checks method and URL.
"""
print "url fake: ", FakeResponse.url
assert FakeResponse.method == method
assert FakeResponse.url == url
我还有一个适用于所有测试用例的装饰器:
@pytest.fixture(autouse=True)
def no_requests(monkeypatch):
monkeypatch.setattr('haas.cli.do_put',
lambda url,data: FakeResponse('PUT', url, data))
monkeypatch.setattr("haas.cli.do_post",
lambda url,data: FakeResponse('POST', url, data))
monkeypatch.setattr("haas.cli.do_delete",
lambda url: FakeResponse('DELETE', url, None))
我正在使用 Py.test 测试代码。
一些示例测试用例是:
class Test:
#test case passes
def test_node_connect_network(self):
cli.node_connect_network('node-99','eth0','hammernet')
FakeResponse.check('POST','http://abc:5000/node/node-99/nic/eth0/connect_network',
{'network':'hammernet'})
# test case fails
def test_port_register(self):
cli.port_register('1') # This make a indirect REST call to the original API
FakeResponse.check('PUT','http://abc:5000/port/1', None)
# test case fails
def test_port_delete(self):
cli.port_delete('port', 1)
FakeResponse.check('DELETE','http://abc:5000/port/1', None)
我收到的示例错误消息:
method = 'PUT', url = 'http://abc:5000/port/1', values = None
@staticmethod
def check(method, url, values):
""" checks method and URL.
'values': if None, verifies no data was sent.
if list of (name,value) pairs, verifies that each pair is in 'values'
"""
print "url fake: ", FakeResponse.url
> assert FakeResponse.method == method
E assert 'POST' == 'PUT'
E - POST
E + PUT
haas/tests/unit/cli_v1.py:54: AssertionError
--------------------------------------------- Captured stdout call -------------------------------------
port_register <port>
Register a <port> on a switch
url fake: http://abc:5000/node/node-99/nic/eth0/connect_network
--------------------------------------------- Captured stderr call -------------------------------------
Wrong number of arguements. Usage:
而如果我以下列方式调用第二个测试用例,考虑到 检查函数采用“self”参数并且不使用@staticmethod,则测试用例有效:
def test_port_register(self):
cli.port_register('1')
fp = FakeResponse('PUT','http://abc:5000/port/1', None) #Create a FakeResponse class instance
fp.check('PUT','http://abc:5000/port/1', None) # Just call the check function with the same
arguments
问题:
- 使用猴子补丁和@staticmethod 是否有任何副作用
- 如何为下一个函数调用中使用的前一个测试函数定义 url。
- 不应该有一个参数范围来禁止上述不需要的行为。
- 有没有更好的猴子补丁方法。
抱歉,这篇文章太长了,我已经尝试解决这个问题一个星期了,想要一些观点 其他程序员。
【问题讨论】:
-
不清楚您期望在这里发生什么。你明确地使用了类属性,所以我不明白为什么当它们在实例之间持续存在时你会感到惊讶:这就是类属性的全部意义。
-
有没有更好的方法来完成假测试。在内部,FakeResponse 类的属性在另一个模块中用于进行一些计算。
-
尝试调试
cli.port_register('1')并检查它是否在PUT之后调用POST请求。您的代码并不漂亮,但它应该可以工作......但只检查 last 调用FakeResponse() -
您可以尝试使用
mock框架来构建一个模拟请求。稍后我可以尝试使用mock框架来填写答案。
标签: python unit-testing monkeypatching