28 Apr 2014
don't give up
you know it's never been easy
-- Peter Gabriel
Bash
brings you back to the seventies. I've fought a couple more hours to get curl
working, changing the different types of quotes I use, with no real success.
I've started wrting a python meta-script, that would generate the bash script (pure curl calls, no functions, to mitigate quote problems). Then I looked at restAssured in Java, but the syntax is not as fluent as they claim.
And then I decided to stop.
That's one of the most important lessons I need to learn. When there's a problem, and you can spend hours solving it, using your programmer's skills, well, you don't have to. It's not a failure, it's an optimization of my time and happiness. It's not cowardice, it's wisdom. Sort of (it's still hard to admit).
24 Apr 2014
Yesterday I decided I needed some tests. Overnight, simple curl in a bash script seemed appropriate to test a REST API.
I created a new test
configuration in grunt-preprocess. It generates some duplicated code, that I was unable not remove.
I added grunt-shell to be able to launch scripts from grunt.
I had it all working in half an hour. Grunt is ok, but the ecosystem looks a bit young, with a lot of extensions providing the same service (grunt-exec, grunt-shell, grunt-run...), some allegedly no longer maintained.
Anyway, now on to my script.
Bash bashing
The shell script first calls mysql
to create and populate a test database.
I used mysql_config_editor
to persist a MySql login configuration and avoid the "Using a password on the command line interface can be insecure" warnings when setting the password from the command line.
I created an assert
bash function to check the JSON returned by a query, and an assertError
to check the http return code of invalid requests (hint: curl -s -o /dev/null -w "%{http_code}"
). A nice DSL with one-liner tests:
assert "POST" "user" "$USER" '{"id":"1","role":"user","token":".."}'
assertError "POST" "user" "$INVALID_USER" 403
But bash was not helping me. One line sums it up:
if [ "$RESULT" != "$EXPECTED" ]; then
where you learn that [
is not just a funny parenthesis, but an alias to the test
command, which expects ]
as it last argument. This explains why you need this ;
at the end to separate the then
. And do not try to remove any of the space characters here, they are all required. Same thing for the quotes, which prevent new spaces from appearing.
Bash is a dinosaur, coming from the seventies, when you were so proud you could format your 720k floppy using the command line. I knew it, but my script was short, and all I needed was to get these two assert
methods running.
And then a test fails
In this test, I give a new type of header parameter to curl, but it manages to mess with the parameters and their quotes. When I echo
the command and then run it in a shell, I get the correct result. But when bash runs it, I can see on the server log that the header parameters are wrong, maybe because it added some quotes this time.
I've spent more than half a day on these tests, and all the bugs I've found so far were in the tests.
23 Apr 2014
But it's a pain. I don't like testing.
Booooooo !
I hear you, agile craftsmen. But since I never make bugs...
Booooooo ! Booooooo !
Got it. Still, I'm not a big fan of tests, I feel like I'm wasting my time. Except for very specific / complex / sensitive parts of the code, I hardly test my code. The fact that my work is usually very UI-centric does not help either. Toggle a button, rotate the camera using the mouse and check that the wireframe is correctly displayed. Good luck.
More testing is definitively something I want to try in this post series. Maybe I wouldn't have tried if it wasn't for this blog actually.
And sometimes, your system explodes, as is the case now with my angularJS side project. Each defect leads to a new one. My architecture is probably really bad, since this is my first project using this technological stack. The first isolated part I'll try to test is the REST API.
Testing a REST API
It's a single PHP page, using the Slim framework and accessing a mySql database. Around 10 different actions, with various error return codes.
phpUnit, DbUnit, sure, but PHP should stay an implementation detail.
Frustrated after these long minutes looking for tools, I decided to do it by hand: Create a test grunt configuration, binding to a test database, maybe using SqlLite, and then I'll do simple curl requests and check the results. And yes, some requests will have side effects and their order will matter.
Booooooo !
That's exactly the kind of mistakes 'bad' programers do, for lack of knowledge of the appropriate tooling. They end up re-inventing the wheel and wasting even more time. So let's sleep over it.