单元测试报错: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
相关产品推荐
相关产品推荐

