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

如何解决unittest测试中的AssertionError: !=None问题?

Braves Stats程序测试AssertionError问题排查与修复

问题描述

我开发了名为Braves Stats的Python程序,包含lookup_player、add_player_to_dict、delete_in_dict三个球员字典操作函数,并用unittest编写测试用例。运行测试时出现AssertionError,例如test_add_player_success用例提示预期字典与None不相等。相关代码及错误信息如下:

主程序代码

import unittest

def main():
    #initial roster#
    brave_roster = {"Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273",
        "Ronald Acuna": "AB: 467, R: 71, H: 124, HR: 15, AVG: 0.266",
    }

def lookup_player(brave_roster,name):
    name = input("Enter the name of the player you want to lookup:\n")
if name in brave_roster:
    print("Here are the", [name], "stats:", brave_roster[name])
else:
    print("That player does not exist.")

def add_player_to_dict(brave_roster,name,stats):
    name = input("Enter the name of the player you want to add:\n")
    if name not in brave_roster:
        stats = input("Please add stats:\n")
        brave_roster[name] = stats
        brave_roster.update([(name, stats)])
        print("Here's", [name],"'s stats:\n")
        for name, stats in brave_roster.items():
            print(name, ':', stats)
    else:
        print("That player is already on our roster.")

def delete_in_dict(brave_roster, name):
    name = input("Enter the name of the player you want to remove:\n")
    if name in brave_roster:
        del brave_roster[name]
        return brave_roster
    else:
        print("\n uh typo?", [name], "does not play for us")

if __name__ == '__main__':
    print("\t ***  Braves Stats!  ***\n")
    print("Welcome to My Braves Stats!")
    
    brave_roster = {
        "Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273",
        "Ronald Acuna": "AB: 467, R: 71, H: 124, HR: 15, AVG: 0.266",
    }
    name = main()
    choice = input("Please type your choice number:")
if (choice == "1"):
    lookup_player(brave_roster,name)
elif (choice == "2"):
    add_player_to_dict(brave_roster,name)
else: 
    (choice == "3")
    delete_in_dict(brave_roster,name)
        

print("\nThanks for using my Braves Stats.")

测试用例代码

class TestDictFunctions(unittest.TestCase):

    def test_search_player_success(self):
        test_dict = {
            "Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"
        }
        actual = test_dict["Austin Riley"]
        expected = lookup_player(test_dict, "Austin Riley")
        self.assertEqual(actual, expected)

    def test_search_player_no_result(self):
        test_dict = {
            "Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"
        }
        actual = "N/A"
        expected = lookup_player(test_dict, "Ronald Acuna")
        self.assertEqual(actual, expected)

    def test_add_player_sucess(self):
        test_dict = {
            "Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"
        }
        actual = {
            "Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273",
            "Ronald Acuna": "AB: 467, R: 71, H: 124, HR: 15, AVG: 0.266"
        }
        expected = add_player_to_dict(test_dict, "Ronald Acuna", "AB: 467, R: 71, H: 124, HR: 15, AVG: 0.266")

        self.assertEqual(actual, expected)

    def test_add_player_duplicate(self):
        test_dict = {"Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"}
        actual = {"Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273", "Austin Riley(2)": "AB: 350, R: 20, H: 120, HR: 5, AVG: 0.214"}
        expected = add_player_to_dict(test_dict, "Austin Riley", "AB: 350, R: 20, H: 120, HR: 5, AVG: 0.214")
        self.assertEqual(actual, expected)

    def test_delete_player_sucess(self):
        test_dict = {"Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"}
        expected = {}
        actual = delete_in_dict(test_dict, "Austin Riley")
        self.assertEqual(actual, expected)

    def test_delete_word_no_result(self):
        test_dict = {"Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"}
        expected = test_dict
        actual = delete_in_dict(test_dict, "Shohei Ohtani")
        self.assertEqual(actual, expected)

#uncomment to run tests
unittest.main()

错误信息

FAIL: test_add_player_sucess (main.TestDictFunctions.test_add_player_sucess)
Traceback (most recent call last):
File "/Users/ray/Documents/DSCI HW/Homework 1/test_roster.py", line 100, in test_add_player_sucess
self.assertEqual(actual, expected)
AssertionError: {'Austin Riley': 'AB: 615, R: 90, H: 168,[78 chars]266'} != None


问题原因

1. 函数缺少返回值

add_player_to_dict和lookup_player函数没有定义return语句,Python默认会返回None。测试用例中直接将这两个函数的调用结果与预期字典/字符串比较,自然会出现字典 != None的断言错误。

  • delete_in_dict仅在删除成功时返回字典,删除失败时无返回值,同样会导致测试失败。

2. 函数内部覆盖传入参数

三个函数都在内部通过input()重新获取参数,完全忽略了测试用例传入的name和stats参数:

  • 测试时程序会卡住等待手动输入,无法自动完成测试;
  • 实际执行逻辑与测试用例预设的参数不符,导致结果不可控。

3. 逻辑与测试用例不匹配

  • add_player_to_dict中brave_roster.update([(name, stats)])是多余的,因为前面已经通过brave_roster[name] = stats完成了添加;
  • test_add_player_duplicate预期会添加Austin Riley(2),但原函数遇到重复球员仅打印提示,不会创建新的键,测试逻辑不成立;
  • 主程序中else: (choice == "3")是无效代码,应该改为elif choice == "3"。

修复方案

1. 调整函数设计,分离输入与业务逻辑

将用户输入和字典操作逻辑分离,让函数专注于处理字典,参数通过外部传入,避免在函数内使用input():

def lookup_player(brave_roster, name):
    if name in brave_roster:
        result = brave_roster[name]
        print(f"Here are the {name} stats: {result}")
        return result
    else:
        print("That player does not exist.")
        return "N/A"

def add_player_to_dict(brave_roster, name, stats):
    if name not in brave_roster:
        brave_roster[name] = stats
        print(f"Here's {name}'s stats:\n")
        for player, stat in brave_roster.items():
            print(f"{player} : {stat}")
        return brave_roster.copy()  # 返回副本避免原字典被修改影响后续测试
    else:
        print("That player is already on our roster.")
        return brave_roster.copy()

def delete_in_dict(brave_roster, name):
    if name in brave_roster:
        del brave_roster[name]
        print(f"{name} has been removed from the roster.")
        return brave_roster.copy()
    else:
        print(f"\n uh typo? {name} does not play for us")
        return brave_roster.copy()

2. 修正测试用例

确保测试用例的预期结果与函数实际逻辑匹配:

class TestDictFunctions(unittest.TestCase):

    def test_search_player_success(self):
        test_dict = {
            "Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"
        }
        actual = lookup_player(test_dict, "Austin Riley")
        expected = test_dict["Austin Riley"]
        self.assertEqual(actual, expected)

    def test_search_player_no_result(self):
        test_dict = {
            "Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"
        }
        actual = lookup_player(test_dict, "Ronald Acuna")
        expected = "N/A"
        self.assertEqual(actual, expected)

    def test_add_player_success(self):
        test_dict = {
            "Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"
        }
        expected = {
            "Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273",
            "Ronald Acuna": "AB: 467, R: 71, H: 124, HR: 15, AVG: 0.266"
        }
        actual = add_player_to_dict(test_dict, "Ronald Acuna", "AB: 467, R: 71, H: 124, HR: 15, AVG: 0.266")
        self.assertEqual(actual, expected)

    def test_add_player_duplicate(self):
        test_dict = {"Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"}
        expected = test_dict.copy()  # 重复添加时字典不变
        actual = add_player_to_dict(test_dict, "Austin Riley", "AB: 350, R: 20, H: 120, HR: 5, AVG: 0.214")
        self.assertEqual(actual, expected)

    def test_delete_player_success(self):
        test_dict = {"Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"}
        expected = {}
        actual = delete_in_dict(test_dict, "Austin Riley")
        self.assertEqual(actual, expected)

    def test_delete_player_no_result(self):
        test_dict = {"Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273"}
        expected = test_dict.copy()
        actual = delete_in_dict(test_dict, "Shohei Ohtani")
        self.assertEqual(actual, expected)

3. 修正主程序语法错误

将主程序中的无效代码改为正确的分支判断:

if __name__ == '__main__':
    print("\t ***  Braves Stats!  ***\n")
    print("Welcome to My Braves Stats!")
    
    brave_roster = {
        "Austin Riley": "AB: 615, R: 90, H: 168, HR: 38, AVG: 0.273",
        "Ronald Acuna": "AB: 467, R: 71, H: 124, HR: 15, AVG: 0.266",
    }
    choice = input("Please type your choice number (1: lookup, 2: add, 3: delete): ")
    if choice == "1":
        name = input("Enter the name of the player you want to lookup:\n")
        lookup_player(brave_roster, name)
    elif choice == "2":
        name = input("Enter the name of the player you want to add:\n")
        stats = input("Please add stats:\n")
        add_player_to_dict(brave_roster, name, stats)
    elif choice == "3":
        name = input("Enter the name of the player you want to remove:\n")
        delete_in_dict(brave_roster, name)
    else:
        print("Invalid choice!")

    print("\nThanks for using my Braves Stats.")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:38:08