Skip to main content

Control and Observe


This week I was testing a new piece of functionality that will sanitise query parameters on an API endpoint. The developer had implemented a first cut and I was looking at the code and the unit tests for a few minutes before we got together for a walkthrough.

After exercising the new function through the unit tests, trying other values, and checking that the tests could fail, I wanted to send some requests from an external client. I already had the service set up in IntelliJ and running under the debugger, so ...

Sending requests from Postman and inspecting sanitised values in a breakpoint was OK, but there was too much  jumping back and forth between applications, clicking on fields, scrolling and so on. Each iteration was many seconds long.

Luckily, we'd already  decided to log sanitised strings for monitoring and later review,  so I could disable the breakpoints and just look at the service console. That was better but still too heavy for me. There were many log lines and I had to find the one I was interested in and find the right field in it.

What I was looking for was a way to, in real time, run a request, see the sanitisation (or lack of it) immediately, and then try another request. I wanted to explore the implementation with minimal friction.

I wondered if I could get the console log out of IntelliJ to a file which I could then parse for the relevant log lines. A quick bit of Googling and it turns out I could! So I did! And then used this kind of command to pull out the sanitised text as it appeared:

$ tail -f /tmp/console.log | grep <my log line> | jq '.<sanitised text>'

I already had a tool that would let me submit requests with relevant input parameters. I built it when I first joined the company and I've been incrementally adding to it as I've needed new bits of functionality for testing.

This call would send "string" to the service to be sanitised and show the server response:

$ myrequest <string>

Now I had two windows in which I could see the request and response, whether there was sanitisation and, if so, what it was. One last thing,  could I see both request and log at the same time? I thought I would take a second to learn how to split one iTerm2 terminal horizontally. Bingo!

This pattern is one that I use a lot, so much so that it's become internalised. I want to do both of these things:

  • control: the application, the environment, and the input
  • observe: the output and relevant internals
These are also two important testability considerations for system design in Rob Meaney's CODS model.

On top of that, I seek to minimise the friction in each iteration. I want the time between having an idea about what I want to test next to seeing the result to be short. In this way I can do more experiments in the same time and stay in flow.

Making a temporary test rig in the console this way has other benefits too, including a built-in history and easy copy-pasting into test notes, Slack, or bug reports.

Giving myself permission to experiment with the way of approaching the testing is also important here. I thought I would want to try enough inputs that it was worth investing in finding an efficient approach. This has the bonus that I learned a couple of things that will be useful again in future.
Syntax highlighting: pinetools