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

单元测试报错:AssertionError - 自定义异常NotEnoughLetters未触发

问题:unittest断言自定义异常失败,手动触发正常

我写了一个带try/except块的Python函数,当输入字符串长度小于3时会抛出自定义异常NotEnoughLetters。手动输入短字符串(比如"ha")能得到正确错误信息,但用unittest的assertRaises检测该异常时,却提示AssertionError: NotEnoughLetters not raised。

函数文件代码

from collections import Counter


# set custom exception to raise when a word with less than 3 letters is given
class NotEnoughLetters(Exception):
    pass


# create a function that will return the 3 most common letters
def three_most_common(string: str):
    string = string.replace(" ", "")
    try:
        if not all(char.isalpha() for char in string):
            raise ValueError("Your input must contain a string")  # using all because in this instance I haven't accounted for strings and ints mixed

        if len(string) < 3:
            raise NotEnoughLetters("There are not enough letters in your sentence")

        most_common = Counter(string).most_common(3)
        letters = [key for key, value in most_common]

    except ValueError as err:
        return err
    except NotEnoughLetters as e:
        return e
    else:
        return f"Here are your most common letters: 1) {letters[0]}  2) {letters[1]}  3) {letters[2]}"

    finally:
        print("The program is running, please wait for your output")

测试文件代码

import unittest
from unittest import TestCase
from common_letters import three_most_common, NotEnoughLetters


class TestCommonLetters(TestCase):

    # valid input
    def test_good_string(self):
        expected_input = "cheesy puff"
        expected_output = "Here are your most common letters: 1) e  2) f  3) c"
        result = three_most_common(expected_input)
        self.assertEqual(expected_output, result)  # add assertion here

    # invalid input
    def test_bad_string(self):
        expected_input = "cheesy puff"
        false_output = "Here are your most common letters: 1) f  2) f  3) e"
        result = three_most_common(expected_input)
        self.assertNotEqual(false_output, result)

    # edge case 1, having 3 letters
    def test_having_three_letters(self):
        expected_input = "hay"
        expected_output = "Here are your most common letters: 1) h  2) a  3) y"
        result = three_most_common(expected_input)
        self.assertEqual(expected_output, result)

    # edge case 2, having 2 letters TODO this didn't work so get clarification tomorrow as to why not
    def test_having_two_letters(self):
        with self.assertRaises(NotEnoughLetters):
            three_most_common(string="ha")


if __name__ == '__main__':
    unittest.main()

报错信息

Traceback (most recent call last):
  File "C:\Homework-LivvyW\Homework-LivvyW\Homework_week7-LivvyW\test_common_letters.py", line 31, in test_having_two_letters
    with self.assertRaises(NotEnoughLetters):
AssertionError: NotEnoughLetters not raised

问题原因与解决方案

原因

函数内部的try/except块已经捕获了NotEnoughLetters异常,并且返回了异常对象,而不是让异常向上抛出。当unittest调用函数时,函数并没有抛出异常,只是返回了一个NotEnoughLetters的实例,所以assertRaises检测不到异常触发。

解决方案

方案1:让函数抛出异常(推荐,符合异常设计意图)

移除函数中捕获ValueError和NotEnoughLetters的except块,让异常直接向上抛出,这样assertRaises就能正常检测。修改后的函数代码:

from collections import Counter

class NotEnoughLetters(Exception):
    pass

def three_most_common(string: str):
    string = string.replace(" ", "")
    # 移除try/except块,直接做校验并抛出异常
    if not all(char.isalpha() for char in string):
        raise ValueError("Your input must contain only letters")
    if len(string) < 3:
        raise NotEnoughLetters("There are not enough letters in your sentence")
    
    most_common = Counter(string).most_common(3)
    letters = [key for key, value in most_common]
    # 将finally里的打印移到正常流程,避免异常时也打印(如果需要始终打印,可保留finally)
    print("The program is running, please wait for your output")
    return f"Here are your most common letters: 1) {letters[0]}  2) {letters[1]}  3) {letters[2]}"

方案2:修改测试用例,断言返回的异常对象

如果需要保留函数返回异常对象的逻辑,那么测试时不要用assertRaises,而是直接断言返回值是NotEnoughLetters的实例,并且消息正确:

def test_having_two_letters(self):
    result = three_most_common(string="ha")
    self.assertIsInstance(result, NotEnoughLetters)
    self.assertEqual(str(result), "There are not enough letters in your sentence")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 08:17:54