使用Python unittest测试文件读取功能时返回None的问题排查
信用卡验证程序单元测试问题
我正在对一个信用卡验证程序做单元测试,程序接收包含虚假信用卡号的.txt文件,返回包含卡号、是否有效及卡类型(Visa、MasterCard等)的字典。
已通过unittest模块验证Luhn算法实现正确,且程序能通过硬编码卡号正确识别卡类型。但测试读取.txt文件的功能时,process_file函数返回None而非预期字典。.txt文件与函数文件、测试文件在同一目录,怀疑是否是unittest模块的特性导致无法对比读取文件的函数输出?
处理文件相关函数
def process_file(file_path): try: with open(file_path, 'r') as file: card_numbers = file.readlines() results = {} for card_number in card_numbers: is_valid = check_card_number(card_number) card_type = get_card_type(card_number) results[card_number] = (is_valid, card_type) return results except Exception as e: print(f"Error reading file: {e}")
def check_card_number(card_number): if not card_number.isdigit(): return False return luhn_algorithm(card_number)
import re def get_card_type(card_number): patterns = { 'Visa': r"^4[0-9]{12}(?:[0-9]{3})?$", 'MasterCard': r"^5[1-5][0-9]{14}$", 'American Express': r"^3[47][0-9]{13}$", 'Discover': r"^6(?:011|5[0-9]{2})[0-9]{12}$", 'JCB': r"^(?:2131|1800|35\d{3})\d{11}$", 'Diners Club': r"^3(?:0[0-5]|[68][0-9])[0-9]{11}$", 'Maestro': r"^(5018|5020|5038|56|57|58|6304|6759|676[1-3])\d{8,15}$" } for type, pattern in patterns.items(): if re.match(pattern, card_number): return type return 'Unknown'
def luhn_algorithm(card_number:str) -> bool: payload = [int(d) for d in card_number[:-1]] even, odd = payload[-1::-2], payload[-2::-2] total = sum(odd) + sum([(i * 2) - 9 if i >= 5 else i * 2 for i in even]) return 10 - (total % 10) == int(card_number[-1])
测试处理文件的代码
import unittest class TestProcessFile(unittest.TestCase): def test_validate_card_and_get_type(self): file_path = r'file_path\test_cards.txt' credit_cards = ('6390448951544', '3507088898930091') correct_card_types = ('Unknown', 'JCB') correct_validation = (False, True) correct_results = dict(zip(credit_cards, zip(correct_validation, correct_card_types))) self.assertEqual(process_file(file_path), correct_results)
问题原因及解决方法
核心原因
unittest本身不会导致函数返回None,问题出在以下两点:
- 文件路径错误:测试代码中硬编码的
file_path = r'file_path\test_cards.txt'是无效路径,导致process_file触发异常,而函数的except块仅打印错误但无返回值,最终返回None。 - 卡号含换行符:
readlines()会保留每行末尾的\n,导致后续check_card_number中card_number.isdigit()返回False(因为含非数字字符\n),同时测试用例中的键是无换行符的字符串,即使函数正常返回,断言也会失败。
解决步骤
修正文件路径:使用相对路径或动态获取文件路径,确保测试时能找到文件:
import os # 获取当前测试文件所在目录,拼接目标文件路径 file_path = os.path.join(os.path.dirname(__file__), 'test_cards.txt')或者直接用
file_path = 'test_cards.txt'(确保文件在同一目录)。修复异常处理逻辑:在
process_file的except块中抛出异常,让测试能明确捕获文件读取错误,而非静默返回None:def process_file(file_path): try: with open(file_path, 'r') as file: # 去掉每行的换行符和空白字符,过滤空行 card_numbers = [line.strip() for line in file.readlines() if line.strip()] results = {} for card_number in card_numbers: is_valid = check_card_number(card_number) card_type = get_card_type(card_number) results[card_number] = (is_valid, card_type) return results except Exception as e: print(f"Error reading file: {e}") raise # 抛出异常,便于测试定位问题处理卡号的换行符:用
strip()清理每行的空白字符,确保卡号是纯数字字符串,同时过滤文件中的空行,避免无效数据干扰。
内容的提问来源于stack exchange,提问作者Camocarrot
相关产品推荐
相关产品推荐

