Sponsored Link •
Bill Venners: What is your opinion of unit testing? How important is unit testing in achieving overall system robustness?
Guido van Rossum: I like unit testing a lot when you're in the early phases of writing your application—especially when you write the application from the bottom up, as a library of components that your higher-level application can later use. If you follow a rule that you need a unit test for every function, and that you must unit test everything that's part of the function specification, then you prevent many mistakes that otherwise would be much harder to debug. If you have a large program that doesn't work because of a bug in a function, you'll have a hard time finding the buggy function. The function can return a result that is slightly off. That result gets passed on and used in another calculation, which returns a slightly wrong result. Then 17 steps later you have a negative result that you didn't expect could possibly be negative. Tracking that down could be really hard.
If you do unit testing, you test each function individually. Doing it properly, using the eXtreme Programming attitude, you write your unit tests and your actual function implementation at the same time—when what you should test is fresh in your mind.
I always recommend both black-box and white-box testing. A black box test is written only to the interface, but a white-box test is written with knowledge of the implementation. If you know that you're using a nasty implementation trick, make your unit test also contain a torture test for your implementation's end cases. If you know you're doing something completely different when your input is more than 512 bytes long, for example, I'd recommend you write a unit test to test a few small values, then test 510, 511, 512, 513, and 514. Make sure all those values work and that you don't have an end case where the transition between one algorithm and another introduces a bug.
Bill Venners: What's a good use for Jython?
Guido van Rossum: A good use for Jython is interactive testing. Even in a pure Java shop, you can use Jython to interactively test your Java classes. It's nice to be able to write unit tests, but sometimes you just want to poke at your system. You want to import your class and see what happens when you call a method with a particular parameter. Maybe you're not yet in the unit-testing phase, you're in the debugging phase. You're trying to determine which things work and which things don't work.
With Jython, you can just start the interactive interpreter, import your Java classes directly into Jython, instantiate classes as instances or even subclass the classes, and start typing away. You can see the results directly rather than having to type a program, compile it, link it, and run it. If you want to also see what it prints for 5 instead of for 4, you can just type that in the next line of the interpreter. If you want to tabulate the results for input values 1 to 10, you can just create a for loop around your Java call. That experimental approach is very helpful.
Frank Sommers: How do you test the correctness of large-scale Python systems—the kinds of systems you are working on currently?
Guido van Rossum: One thing my team and I do a lot, which is actually an area where Java programmers sometimes use Python, is write small tests that interact with the system. For unit tests, you can look at the function specification. This goes in. This comes out. You provide test cases to verify that the function works right. But when you want to test a large system, you often have to improvise.
How to test a larger system is much less obvious, because you may not be able to test all possible inputs or states of the system. In Python, you can easily write a little Python program, or sometimes a large one, that helps you test by providing test input or test data and monitoring what comes out.
Testing a Python program is especially easy, because you also have introspection. You can quite easily intercept output from Python methods. You can quite easily substitute one class that includes test instrumentation for another class. In Python, you can write a generic instrumentation class that acts as a proxy for another class, without knowing the interface of the other class. The proxy class is completely generic. That means if you change the underlying class, you don't need to change the proxy class, even though it implements the same type. The proxy just passes everything on but maybe logs all the method calls, or certainly the important or interesting ones.