Incremental development in Python versus actual tests
After writing yesterday's entry on how I need to add tests to our Djanog app, I've been thinking about why it doesn't have them already. One way to describe the situation is that I didn't bother to write any tests when I wrote the app, but another view is that I didn't write tests because I didn't need to. So let me explain what I mean by that.
When I ran into the startup overhead of small Python programs, my eventual solution was to write a second implementation in Go, which was kind of an odd experience (as noted). One of the interesting differences between the two versions is that the Go version has a fair number of tests and the Python one doesn't have any. There are a number of reasons for this, but one of them is that in Go, tests are often how you interact with your code. I don't mean that philosophically; I mean that concretely.
In Python, if you've written some code and you want to try it out
to see if it at least sort of works, you fire up the Python
interpreter, do '
import whatever' (even for your main program), and start poking away. In Go, you have no REPL,
so often the easiest way to poke at some new code is to open up
your editor, write some minimal code that you officially call a
'test', and run '
go test' to invoke it (and everything else you
have as a test). This is more work than running an interactive
Python session and it's much slower to iterate on 'what happens if
...' questions about the code, but it has the quiet advantage that
it's naturally persistent (since it's already in a file).
This is the sense in which I didn't need tests to write our Django app. As I was coding, I could use the Python REPL and then later all of Django's ready to go framework itself to see if my code worked. I didn't have to actually write tests in order to test my code, not in the way that you can really need to in Go. In Python, incremental development can easily be done with all of your 'tests' being ad hoc manual work that isn't captured or repeatable.
(Even in Go, my testing often trails off dramatically the moment I have enough code written that I can start running a command to exercise things. In the Go version of my Python program, basically all of the tests are for low-level things and I 'tested' to see if higher level things worked by running the program.)
PS: Django helps this incremental development along by making it
easy to connect bits of your code up to a 'user interface' in the
form of a web page. You need somewhat more than a function call in
the REPL but not much more, and then you can use '
...' to give you a URL you can use to poke your code, both to
see things rendered and to test form handling. And sometimes you
can check various pieces of code out just through the Django admin
PPS: Of course it's better to do incremental development by writing actual tests. But it takes longer, especially if you don't already know how to test things in the framework you're using, as I didn't when I was putting the app together (cf).