如何针对Python中依赖网络的Zip下载功能进行TDD测试?
Zip文件下载功能的有效测试用例编写方案
现有测试的问题
你的测试代码存在几个关键问题:
- 断言逻辑错误:
self.assertGreater(len(os.listdir(...)), list_of_zip_links)错误地将列表与长度值比较,应该用len(list_of_zip_links) - 断言方法误用:
self.assertEqual(file.endswith('.zip'))参数数量不匹配,应改用self.assertTrue() - 过度依赖真实外部链接:测试稳定性差,无法覆盖异常场景,且不符合"不依赖外部服务"的要求
符合要求的测试思路(不Mock、不依赖外部服务)
通过搭建本地临时HTTP服务器模拟真实下载服务,完全控制测试场景,既验证真实下载逻辑,又避免依赖外部资源。
测试用例实现
import os import tempfile import unittest from http.server import HTTPServer, SimpleHTTPRequestHandler import threading from your_module import download_zip_links # 导入你的下载函数 class TestZipDownload(unittest.TestCase): @classmethod def setUpClass(cls): # 启动本地HTTP服务器,提供测试用Zip文件 cls.server_port = 8000 # 创建临时目录存放测试Zip文件 cls.test_files_dir = tempfile.mkdtemp() # 生成2个合法的空Zip文件(避免下载后解压报错) for i in range(2): zip_path = os.path.join(cls.test_files_dir, f"test_{i}.zip") with open(zip_path, 'wb') as f: f.write(b'PK\x03\x04\x14\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') # 启动服务器线程 cls.server = HTTPServer(('localhost', cls.server_port), SimpleHTTPRequestHandler) cls.server_thread = threading.Thread(target=cls.server.serve_forever) cls.server_thread.daemon = True cls.server_thread.start() @classmethod def tearDownClass(cls): # 关闭服务器并清理临时文件 cls.server.shutdown() for root, dirs, files in os.walk(cls.test_files_dir, topdown=False): for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) os.rmdir(cls.test_files_dir) def test_download_valid_zip_links(self): """测试从本地服务器下载指定数量的Zip文件,验证数量、格式与完整性""" test_links = [ f"http://localhost:{self.server_port}/test_0.zip", f"http://localhost:{self.server_port}/test_1.zip" ] # 使用临时目录作为下载目标,避免污染正式环境 with tempfile.TemporaryDirectory() as temp_zip_dir: download_zip_links(test_links, temp_zip_dir) downloaded_files = [f for f in os.listdir(temp_zip_dir) if os.path.isfile(os.path.join(temp_zip_dir, f))] # 断言下载文件数量与链接数一致 self.assertEqual(len(downloaded_files), len(test_links)) # 断言所有文件都是Zip格式 for file in downloaded_files: self.assertTrue(file.endswith('.zip')) # 断言文件非空(验证下载完整) for file in downloaded_files: file_path = os.path.join(temp_zip_dir, file) self.assertGreater(os.path.getsize(file_path), 0) def test_download_invalid_links(self): """测试下载无效链接,验证函数异常处理能力""" test_links = [ f"http://localhost:{self.server_port}/non_existent.zip", # 不存在的文件 f"http://invalid-host-12345.com/test.zip" # 无法访问的主机 ] with tempfile.TemporaryDirectory() as temp_zip_dir: # 假设函数会跳过错误链接而非崩溃,可根据实际逻辑调整断言 download_zip_links(test_links, temp_zip_dir) downloaded_files = [f for f in os.listdir(temp_zip_dir) if os.path.isfile(os.path.join(temp_zip_dir, f))] self.assertEqual(len(downloaded_files), 0)
补充边界测试场景
- 空链接列表:验证函数无报错、不生成多余文件
- 重复链接:根据需求验证是否覆盖或跳过重复下载
- 大文件下载:在本地服务器放置大体积测试Zip,验证下载完整性
优化建议
- 始终使用临时目录替代固定目录,保证测试独立性与环境清洁
- 给
download_zip_links添加超时、HTTP错误等异常处理逻辑,并在测试中覆盖这些场景 - 可选:添加Zip文件合法性验证(尝试解压测试,确保文件未损坏)
内容的提问来源于stack exchange,提问作者Martin Müsli
相关产品推荐
相关产品推荐

