在Python中如何正确测试变量是否为非空字符串(unittest)?

3 投票
2 回答
2939 浏览
提问于 2025-04-16 20:32

也许这个问题很简单,但我还在努力熟悉Python中的单元测试,所以请多多包涵。:-) 在尝试写一些自己的测试时,我遇到了一个问题。假设有一个函数是用来处理非空字符串的:

class BadInputError(Exception): pass

class FooBar(object):
    def take_a_string_and_do_something(param):
        if param == '':
            raise BadInputError('param should not be an empty string')
        if param is None:
            raise BadInputError('param should not be None')
        if not isinstance(param, basestring):
            raise BadInputError('param must be of type string)
        # process nonempty string

我首先想通过单元测试确保param只是一条非空字符串。所以我这样写了我的测试用例。

class TestFooBar(unittest.TestCase):
    def test_take_a_string_and_do_something(self):
        foo = FooBar()
        self.failUnlessRaises(BadInputError, foo.take_a_string_and_do_something, '')
        self.failUnlessRaises(BadInputError, foo.take_a_string_and_do_something, None)
        self.failUnlessRaises(BadInputError, foo.take_a_string_and_do_something, 234)

这样做可以吗,还是我犯了个大错?你的反馈对我很重要!

2 个回答

3

如果它看起来像只鸭子,那就是只鸭子。别太担心类型的问题。只要尽量使用参数。如果你真的需要确认这个参数看起来没问题,你可以这样做:

if not hasattr(param, 'replace'):
    raise ValueError('I cant work with param')

...或者,如果你真的很在意这个参数必须是某种东西(而不是空的):

if not param:
    raise ValueError('param should not be empty')

嘎嘎。

3

这样做可以吗,还是我犯了个大错?

可以,也不可以。

这是一个写单元测试的好例子。

但是,这种情况在你的代码中本来就不应该存在。

class FooBar(object):
    def take_a_string_and_do_something(self, param):
        # process nonempty string
        # If they couldn't provide a non-empty string, they get an exception.

你仍然可以这样测试。

class TestFooBar(unittest.TestCase):
    def setUp( self ):
        self.foo= FooBar()
    def test_zero_length_should_fail(self):
        self.failUnlessRaises(IndexError, foo.take_a_string_and_do_something, '')
    def test_none_should_fail(self):
        self.failUnlessRaises(TypeError, foo.take_a_string_and_do_something, None)
    def test_non_string_should_fail(self):
        self.failUnlessRaises(TypeError, foo.take_a_string_and_do_something, 234)

注意,这样做简单多了,而且更可靠,因为你不需要重复Python内部复杂的错误检查。

撰写回答