You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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,问题出在以下两点:

  1. 文件路径错误:测试代码中硬编码的file_path = r'file_path\test_cards.txt'是无效路径,导致process_file触发异常,而函数的except块仅打印错误但无返回值,最终返回None。
  2. 卡号含换行符:readlines()会保留每行末尾的\n,导致后续check_card_number中card_number.isdigit()返回False(因为含非数字字符\n),同时测试用例中的键是无换行符的字符串,即使函数正常返回,断言也会失败。

解决步骤

  1. 修正文件路径:使用相对路径或动态获取文件路径,确保测试时能找到文件:

    import os
    # 获取当前测试文件所在目录,拼接目标文件路径
    file_path = os.path.join(os.path.dirname(__file__), 'test_cards.txt')
    

    或者直接用file_path = 'test_cards.txt'(确保文件在同一目录)。

  2. 修复异常处理逻辑:在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  # 抛出异常,便于测试定位问题
    
  3. 处理卡号的换行符:用strip()清理每行的空白字符,确保卡号是纯数字字符串,同时过滤文件中的空行,避免无效数据干扰。


内容的提问来源于stack exchange,提问作者Camocarrot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 14:13:14