One suggestion was to not bother writing tests, because my example
script has little logic to it and is short enough to throw away and
rewrite if it’s wrong. For this particular script, that’s probably
true. But this is part of a bigger library, and the example I posted
was intended to be simple enough to discuss the principles without
getting bogged down in details.
Another response pointed me to a talk by David Copeland at GoGaRuCo
Test-drive the development of your command-line applications.
This is a good talk, and worth watching. It definitely helped, but
still didn’t deal with some of the issues in my example problem, like
how to test the copying of files to a remote server or running
commands on a remote server.
Here’s my original solution to the example problem. It has the
redeeming quality of working for its intended purpose, but I’m not
totally happy with the tests.
I split the problem into two parts: building the package, and
uploading the package. I made little classes, essentially
MethodObjects, for each part.
First, the package building part:
As you can see, I’m not actually testing the effects of the various
commands; instead, I’m just testing that the commands look right. Not
ideal, but better than nothing. I’m testing the commands by mocking
the backtick method on the object under test. I realize that mocking
a method on the class under test is a smell, but it seemed better than
Here’s the code to make it pass:
Here’s the tests for the package upload part:
Note that I don’t test the commands that I’m executing in the remote
SSH session, because I couldn’t think of a good way to do that at the
time I wrote this.
Here’s the code:
To use these classes:
And there’s my less-than-ideal solution to the problem. Now that
you’ve seen the code, how would you improve it?