【问题标题】:assertRaises only catch base Exception in unittestassertRaises 仅在 unittest 中捕获基本异常
【发布时间】:2021-01-30 18:22:07
【问题描述】:

我在 PyCharm 上工作,这是我的项目结构:

Python
|   utils
|   |  __init__.py
|   |  test_utils.py
|   main.py

utils/__init__.py

# -*- coding : utf-8 -*-
"""
Created on 15/10/2020

"""

import random

import datetime


def random_value(min_x, max_x):
    # Verification of the type of parameters
    try:
        assert(type(min_x) is type(max_x))
    except AssertionError:
        raise TypeError('Limits for x must be of the same type')

    # Verification of the inferiority of min_x in front of max_x
    try:
        assert(min_x < max_x)
    except AssertionError:
        raise ValueError('min_x has to be lower than max_x')

    # Definition of result
    x = None

    # If we want float
    if isinstance(min_x, float):
        x = random.uniform(min_x, max_x)

    # If we want int
    elif isinstance(min_x, int):
        x = random.randint(min_x, max_x)

    # If we want datetime.datetime
    elif isinstance(min_x, datetime.datetime):
        x = min_x + datetime.timedelta(seconds=random.randint(0, int((max_x - min_x).total_seconds())), )

    # In other cases, raise of exception
    else:
        raise TypeError('min_x and max_x type is not compatible with function')
    return x

utils/test_utils.py

import unittest
import utils
import datetime


class UtilsTest(unittest.TestCase):
    def test_random_value(self):
        self.assertRaises(TypeError, utils.random_value, 2.0, 3)

        self.assertAlmostEqual(utils.random_value(1.0, 1.5), 1.25, delta=0.25)
        self.assertIn(utils.random_value(1, 3), [1, 2, 3])

        start = datetime.datetime(1998, 5, 5)
        end = datetime.datetime(1998, 5, 10)
        x = utils.random_value(start, end)
        self.assertIsInstance(x, datetime.datetime)
        self.assertTrue((start <= x) and (x <= end))


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

当我运行utils/test_utils.py 来测试utils/__init__.py 时,我遇到了关于第一个self.assertRaises(TypeError, utils.random_value, 2.0, 3) 的错误:

Testing started at 10:23 ...
Python/utils/test_utils.py"
Launching unittests with arguments python -m unittest Python/utils/test_utils.py in Python\utils



Ran 1 test in 0.009s

FAILED (errors=1)

Error
Traceback (most recent call last):
  File "Python\utils\__init__.py", line 18, in random_value
    assert(type(min_x) is type(max_x))
AssertionError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "Python\lib\unittest\case.py", line 60, in testPartExecutor
    yield
  File "Python\lib\unittest\case.py", line 676, in run
    self._callTestMethod(testMethod)
  File "Python\lib\unittest\case.py", line 633, in _callTestMethod
    method()
  File "Python\utils\test_utils.py", line 8, in test_random_value
    self.assertRaises(AssertionError, utils.random_value, 2.0, 3)
  File "Python\lib\unittest\case.py", line 816, in assertRaises
    return context.handle('assertRaises', args, kwargs)
  File "Python\lib\unittest\case.py", line 202, in handle
    callable_obj(*args, **kwargs)
  File "Python\utils\__init__.py", line 20, in random_value
    raise TypeError('Limits for x must be of the same type')
TypeError: Limits for x must be of the same type


Process finished with exit code 1

Assertion failed

Assertion failed

Assertion failed

Assertion failed

Assertion failed

Assertion failed

但是当我使用self.assertRaises(Exception, utils.random_value, 2.0, 3) 时,它可以工作...(并且它不适用于AssertionError)。

为什么 assertRaises 只捕获基本异常?

【问题讨论】:

  • 请注意,您不应将四种不同的测试用例塞进一种测试方法中。
  • 将其缩减为minimal reproducible example,这似乎对我有用。 FWIW assert 不应该用于实际的程序逻辑并且引发错误只是为了捕获它并抛出一个不同的错误似乎毫无意义,例如if type(min_x) is not type(max_x): raise TypeError('Limits for x must be of the same type') 会更简单。
  • 感谢您的回答,您能举个例子说明我应该采用什么结构来测试?哦,我明白你所说的使用断言引发错误的意思,我修改了我的代码,非常感谢! :-)
  • 我建议为random_value 设置一个TestCase 类,而不是整个utils,然后每个测试方法 将涵盖不同的情况。例如。 def test_raises_error_on_type_mismatch(self): self.assertRaises(TypeError, utils.random_value, 2.0, 3)
  • 我很好地在项目变得太大之前提出了这个问题。非常感谢您的建议,我将修改我的代码! :-)

标签: python python-unittest assertraises


【解决方案1】:

我找到了解决方案: assertRaises((AssertionError, TypeError), utils.random_value, 2.0, 3)

但@jonrsharpe 给了我更好的建议:

utils/__init__.py:

替换结构:

try:
   assert(type(min_x) is type(max_x))
except AssertionError:
   raise TypeError

作者:

if not (type(min_x) is type(max_x)):
   raise TypeError

所以assertRaises(TypeError, utils.random_value, 2.0, 3) 命令在utils/test_utils.py 中有效。

【讨论】:

  • 我实际上看到assertRaises(TypeError, ...) 在 Python 2.x 和 3.x 中使用任一选项,它应该只关心 last 异常。但很高兴您找到了解决方案。
猜你喜欢
  • 1970-01-01
  • 2019-11-02
  • 1970-01-01
  • 2013-07-09
  • 2017-01-19
  • 2012-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多