几天来一直在努力为我的代码制作一些测试用例。 我编写了一个代码来批量下载带有给定输入的文件,其形式为URL字符串或URL字符串列表。我的代码目前支持4种协议(http,https,ftp,sftp)
我一直在阅读有关Mock的内容并观看了一些视频。我仍然无法将我在互联网上看到的样本应用到我的实际代码中。 :(
下面是我的批量下载实现和我写的单元测试仍然失败:
def batch_download(url):
req = Request(url)
try:
print '\nStart downloading...'
response = urlopen(req)
except URLError as e:
# No network connection or Invalid URL or The specified server doesn't exist.
if hasattr(e, 'reason'):
print 'We failed to reach a server.'
print 'Reason: ', e.reason
# HTTP Response that is not 200.
elif hasattr(e, 'code'):
print 'The server couldn\'t fulfill the request.'
print 'Error code: ', e.code
else:
# Retrieve a redirected URL, if there is one.
real_url = response.geturl()
print real_url
saved_to = get_local_path(real_url)
urlretrieve(real_url, saved_to)
# meta_data = response.info()['Content-Length']
# file_on_disk = os.stat(saved_to).st_size
# print '\nContent-Length: ' + meta_data
# print 'File on Disk after Download: ' + str(file_on_disk)
remove_partially_downloaded(real_url, response, saved_to)
urlcleanup()
return
def remove_partially_downloaded(url, response, local_path_to_file):
meta_data = response.info()['Content-Length']
file_on_disk = os.stat(local_path_to_file).st_size
print '\nContent-Length: ' + meta_data
print 'File on Disk after Download: ' + str(file_on_disk)
partial_download = int(meta_data) - file_on_disk
if partial_download > 0:
print '\nThe following partially downloaded file ' + get_filename_from_url(url) + ' will be removed'
os.remove(local_path_to_file)
else:
return
格式化单元测试代码时出现问题。所以我在这里附上了我的unittest类的图像
感谢任何帮助。有关使用补丁和MagicMock的建议非常受欢迎。我知道这两者的基本概念,但仍然无法弄清楚将这些概念纳入我的代码的位置。我对此非常陌生。
答案 0 :(得分:1)
好吧,我认为有两个阻挡者在场。首先,您执行的不仅仅是代码。诸如urllib2之类的依赖关系未被正确隔离。实际上,该库的代码中引发了错误。其次,目前尚不清楚你要测试的是什么。为了解决这个问题,我建议使用AAA pattern来编写测试。
让我们从第二个问题开始吧。您希望测试有3个部分:
在测试中,您在设置模拟之前调用batch_download。然后,您设置了一些模拟(虽然不正确,见下文),然后调用代码的另一个函数。没有断言。
可能很难为您的方法提出一个简单的AAA,一个断言测试。那是因为你的功能做了很多事情。尝试重构几个函数,每个函数都做一个可直接测试的东西。 (我强烈建议您查看Robert Martin的书“清洁代码”,它提供了一些提高代码质量的技巧和指南。)
至于嘲笑。你不应该使用urllib2开启者。首先,因为那时您将测试该库以及您的代码。测试成为一种集成测试,并且它不是很好,因为它引入了原始方法中没有的新逻辑(额外的失败点)。其次,更容易使用模拟库。
模拟该依赖的简单方法是使用补丁。举个例子,让我们测试如果urlopen没有引发Error(返回响应),并且在响应上调用了geturl,那么将使用期望的url和save_to路径调用urlretrive:
import mock
...
@mock.patch('test_obj.urllib2')
def test_batch_download(self, urllib2_mock):
# Arrange:
response_mock = mock.MagicMock()
real_url = 'http://sample.com'
response_mock.geturl.return_value = real_url
urllib2_mock.urlopen.return_value = response_mock
# Act:
test_obj.batch_download('http://originalurl.com')
# Assert:
expected_save_to_path = '/var/dl/sample.com'
urllib2_mock.urlretrive.assert_called_once_with(real_url, expected_save_to_path)
我希望这会有所帮助。祝你好运!