Python Unittest 如何使用教程

3
我想了解如何对以下模块进行单元测试。
def download_distribution(url, tempdir):
    """ Method which downloads the distribution from PyPI """
    print "Attempting to download from %s" % (url,)

    try:
        url_handler = urllib2.urlopen(url)
        distribution_contents = url_handler.read()
        url_handler.close()

        filename = get_file_name(url)

        file_handler = open(os.path.join(tempdir, filename), "w")
        file_handler.write(distribution_contents)
        file_handler.close()
        return True

    except ValueError, IOError:
        return False
3个回答

5

单元测试的提议者会告诉你,单元测试应该是自包含的,也就是说,它们不应该访问网络或文件系统(尤其不是以写入模式)。网络和文件系统测试超出了单元测试的范围(虽然你可以将它们提交给集成测试)。

一般来说,对于这种情况,我会将 urllib 和文件写入代码提取到单独的函数中(这些函数不会进行单元测试),并在单元测试期间注入模拟函数。

即:

def get_web_content(url):
    # Extracted code
    url_handler = urllib2.urlopen(url)
    content = url_handler.read()
    url_handler.close()
    return content

def write_to_file(content, filename, tmpdir):
    # Extracted code
    file_handler = open(os.path.join(tempdir, filename), "w")
    file_handler.write(content)
    file_handler.close()

def download_distribution(url, tempdir):
    # Original code, after extractions
    distribution_contents = get_web_content(url)
    filename = get_file_name(url)
    write_to_file(distribution_contents, filename, tmpdir)
    return True

同时,在测试文件中:

import module_I_want_to_test

def mock_web_content(url):
    return """Some fake content, useful for testing"""
def mock_write_to_file(content, filename, tmpdir):
    # In this case, do nothing, as we don't do filesystem meddling while unit testing
    pass

module_I_want_to_test.get_web_content = mock_web_content
module_I_want_to_test.write_to_file = mock_write_to_file

class SomeTests(unittest.Testcase):
    # And so on...

我赞同丹尼尔的建议,你应该阅读更深入的单元测试相关材料。


5
模糊的问题。如果你只是想了解Python单元测试的基础知识,我推荐Mark Pilgrim的《Dive Into Python》,其中包括Python单元测试章节。否则,你需要澄清你在测试该代码时遇到的具体问题。

0

为模拟urllib.urlopen()方法,您可以预先获取一些示例,然后在单元测试中使用它们。以下是一个让您开始的示例:

def urlopen(url):
    urlclean = url[:url.find('?')] # ignore GET parameters
    files = {
        'http://example.com/foo.xml': 'foo.xml',
        'http://example.com/bar.xml': 'bar.xml',
    }
    return file(files[urlclean])
yourmodule.urllib.urlopen = urlopen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接