Writing tests for the application was pretty interesting honestly. I had written tests before for both plain ole JavaScript and React in particular. I am familiar enough with Jest that designing tests were particularly challenging for me. What was new to me though was writing tests for an API which turned out to be an interesting experience.
I started by getting Supertest set up to test the API. It was highly recommended by Google and NPM so I got to work using it. Honestly, I think actually setting up the tests were pretty straight forward and most of the time I spent was really just getting it to properly send data to the server and get a result. In the middle of that, I wrote set up and tear down functions thinking that I would need them. In my head, I imagined that the server would need to be spun up, then I was able to send my data to be tested and get a result and then I’d have to stop the server. Didn’t take me long to get that working and getting some passing tests.
There was some other set up that I did as well which wasn’t dire but made the tests significantly more manageable. So remember, the API works with base64 images which are RIDICULOUSLY LONG strings. I think in one of my tests, I made the mistake of just chucking the image I planned on using into the file and the file suddenly started scrolling forever, lol. So that monstrous thing had to go into it’s own file. Secondly, there was taking the good data of the base64 string and making it into bad data (or at least bad enough for the API to throw an error) which took a bit of learning mostly because TypeScript would slap me on the hand every so often. I also tested some of the util files just to have a bit of confidence in them working while I messed around with the rest of the app.
A couple of weeks into writing the app things started getting a bit… strange…
So I’d finish writing some tests and be happy with myself. A job well done, I’d think. I’d run the tests and everything would pass. Hurray, right? And so what do you do? You run the tests again because… The thing is, this time some of the tests failed and not only did they fail, they’d hang before failing and give a specific error that the test ran too long before timing out. Then you’d run the tests a few more times and now you’d get a situation where tests would pass sometimes and then would fail other times because things were being timed out.
Let me explain what is happening (at least the best I can).
So when Supertest starts, it spins up the server and then does what your tests say before tearing down the server. I believe this happens for each test suite as opposed to each test but I’m not 100% sure. Either way, there will be times when Supertest would not be able to shut down a server before moving on and that would cause it to hang and the test sitting there waiting to time out and fail. I learned that my implementation caused this in a few ways. First of all, remember when I said I was starting up and tearing down the server for testing? Supertest does that on its own so you don’t need to do that and it was causing some issues. The main culprit though was the way I spun up my server.
So I’m sure you’ve done this before yourself when you write your app.js or your server.js and you start writing the basics of your Node app. You then start it with an app.listen and away you went. Turns out Supertest will call app.listen on its own to run your tests but every time it’s running a test, it’ll use your definition of the server which also has an app.listen in it and that’ll eventually cause problems in the teardown. Solution? Pull out the app.listen and define another file that you call to start the server and pass the server’s definition into the test and that’ll solve the problem. I learned this through this Stackoverflow answer and I’ll now define my server in one file and run it in another from now on (even in other technologies).
While unnecessary for completing the requirements of this project, testing was a fun part of doing this and I learned something particularly valuable trying to test this app. I’m pretty happy I went through this experience.
Here’s a commit with all my completed tests: https://github.com/chadstewart/you-go-backend-project/tree/b19f5b1b0c1d951ad1836e4a7d71754b3222199c/nodejs/src/tests
In the next article of this series, I’ll talk about converting the application from reading and writing from disk to passing around an image buffer.
Top comments (0)