문제

I can't find the answer on SO but it's very likely that the argument has been already discussed.

I'm trying to write a quite small size program using the Python language. It's my first "real" experience with a dynamic language and I would prefer to do everything in the right way. One of the practice that I would try to apply since the beginning is unit-testing.

How can I quickly test that the parameters of a method are of the right type? Should I do it?

With right type I mean for instance to check that a method that works with float numbers is not called with a String. In this case consider the possibility that the method should obviously accept even integers and not only float.

도움이 되었습니까?

해결책

How can I quickly test that the parameters of a method are of the right type?

The quickest way is to do nothing.

Seriously. The dynamic language interpreter (Python in this case) will check far more quickly than any code you could ever write. It will simply raise an exception and that's all you need to do. Nothing.

Should I do it?

Never test for the right type. You can't -- in general -- do it.

Let's say you have a function that requires a "number"

def some_func( x ):
    assert isinstance(x, int)

Bad policy. Your function may work for long or float just as well as int.

assert instance( x, (int, long, float) )

Bad policy. You've still excluded complex. Indeed, you've also excluded decimal.Decimal and fractions.Rational which are also valid numbers.

By "type checking" you're going to exclude valid types. The only thing you can do is assume the types are proper and handle the exception gracefully when someone "misuses" your function or class and provides wrong types.

The most graceful way to handle TypeError?

Do nothing. The program should totally crash.

다른 팁

You shouldn't test for specific types. According to the docs, you should simply use the passed-in object as needed and give the user the opportunity to supply a custom implementation.

Depending on what your function does, it may be appropriate to convert the arguments to the expected type:

def my_func(a):
    a = float(a)
    # ...do stuff...

Another excellent option is to use hasattr() to check for the desired member before using it. That would let you throw a helpful exception, instead of the default AttributeError.

Unit testing with complete coverage is really the only way to handle any development work which relies on dynamic languages. Clearly it's very beneficial to have strong coverage tests for statically typed languages but in my experience it's even more important when you have dynamic typing.

If you aren't covering all the code that can run in your tests, then really you are asking for trouble. So you want to use a coverage analysis tool in tandem with your unit tests to prove that you are reaching all of your code.

Even that won't guard against all pitfalls – your tests really need to exercise all the possibly erroneous input data errors your program may receive.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top