Python unittest:测试一个测试

时间:2013-09-09 09:17:10

标签: python unit-testing floating-point

我正在编写一些适用于非常大和非常小的浮点数的代码(例如,1e-150可能是一个有效的答案)。要进行单元测试,我想将浮点数与一些有效数字进行比较而不是小数位数,所以我有以下内容。

import unittest as ut
from numpy.testing import assert_approx_equal

class newTestCase(ut.TestCase):
"""Extends the basic unittest TestCase."""

def assertSFAlmostEqual(self, a, b, places=7):
    """Uses numpy to test if two floats are the same but to a defined
    number of significant figures rather than decimal places.

    Args:
        a: float to be compared
        b: float to be compared
        places: number of significant figures to match. unittest default
        for assertAlmostEqual is 7, so 7 is the default here
    """
    if isinstance(a, float) != True or isinstance(b, float) != True:
        raise TypeError

    raised = False
    try:
        assert_approx_equal(a, b, significant=places)
    except:
        raised = True
    self.assertFalse(raised, "FLoats %g and %g are not equal to %i "
                     "significant figures" % (a, b, places))

这似乎工作正常,但我打算在很多地方使用它,所以我想确定它确实可以正常工作。我的问题是我怎样才能最明智地做到这一点?是否有适当的机制来对单元测试进行单元测试?

我在这里找到了可能的答案,

How to unittest unittest TestCases

但我不明白这是如何运作的。

非常感谢!

2 个答案:

答案 0 :(得分:2)

unittest.TestCase的子类就像任何其他类,因此您可以编写一个unittest.TestCase来检查其方法是否正常工作。

特别是你应该构建一组应该通过和未通过测试的数字,然后使用这些输入调用assertSFAlmostEqual方法,看看测试是通过还是失败。

你联系的答案就是这样,即使它可能是一个比所需要的更复杂的解决方案。例如,我只是写了类似的东西:

import unittest


class MyBaseTestCase(unittest.TestCase):
    def assertSpec(self, thing):
        assert thing == 123


class TestMyTest(MyBaseTestCase):
    def test_failures(self):
        self.assertRaises(AssertionError, self.assertSpec, 121)

    def test_successes(self):
        self.assertSpec(123)

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

您只是将测试用例子类化,并且测试只是调用您使用您知道应该通过/不通过测试的特定参数编写的assert*方法。


关于您当前实施assert*方法的一些注意事项:

if isinstance(a, float) != True or isinstance(b, float) != True:

避免与TrueFalse进行比较。在你的情况下,你可以简单地写:

if not isinstance(a, float) or not isinstance(b, float):
# or:
if not (isinstance(a, float) and isinstance(b, float))

阅读起来也更清楚。

raised = False
try:
    assert_approx_equal(a, b, significant=places)
except:
    raised = True

从不使用普通except:捕获异常。在这种情况下,您确实只想捕获AssertionError引发的assert_approx_equal,因此您应该使用:

raised = False
try:
    assert_approx_equal(a, b, significant=places)
except AssertionError:
    raised = True

其次,您可以避免使用raised标志。 try-except语句允许仅在未引发异常时执行的else子句:

try:
    assert_approx_equal(a, b, significant=places)
except AssertionError:
    # here put the code to be executed when the assertion fails.
else:
    # here put the code to be executed when *no* exception was raised.

答案 1 :(得分:0)

一种方法是TDD(测试驱动开发):

  1. 写一个失败的测试。
  2. 让代码通过测试。
  3. 重构。
  4. 转到1。
  5. 这里的关键是先写一个失败的测试。