Fast & Curious
Gilles Debunne

Don't give up

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).

Bash, back to the seventies

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.

You shall test

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.