开发者

Testing (unittest) if a variable is a nonempty string in python the right way?

开发者 https://www.devze.com 2023-03-16 12:04 出处:网络
Maybe this question is trivial, but I am still trying to warm up with unittests in python, so please have patience with me. :-) While trying to write some tests of my own, the following question arais

Maybe this question is trivial, but I am still trying to warm up with unittests in python, so please have patience with me. :-) While trying to write some tests of my own, the following question araised. Assuming a function that processes nonempty strings:

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

The first thing I wanted to make sure (by unittests) is that param is only a nonempty string. So I wrote my testcases this way.

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)

Is this acce开发者_开发百科ptable or am I making heavy rookie mistake? Your feedback means a lot!


Is this acceptable or am I making heavy rookie mistake?

Yes and No.

It's a fine example of how to write a unit test.

But it's a use case that shouldn't exist in your code in the first place.

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.

You can still test it like this.

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)

Notice that it's much simpler and also much more reliable, since you're not attempting to duplicate Python's extensive internal error-checking.


If it looks like a duck it is a duck. Don't worry so much about type. Just try to use param. If you absolutely must check that it seems kosher, you can always do:

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

... or, if it is really important that param is something (rather than nothing):

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

Quack, quack.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号