jeudi 19 octobre 2017

API test design: placement of asynchronous requests (Node, Mocha/Chai)

I was figuring out how to write test suites for APIs and I started with this tutorial, which structures tests roughly like this:

beforeEach { restore database }

  • send a POST request, test the POST response
  • create a new resource, send a GET for it, test the GET response
  • create a new resource, send a PUT with a field update, test the PUT response

    etc.

This seems like a reasonable approach, but I didn’t like that all the assertions for each route are stacked inside one test - my feeling was that they should be more granular so that it’s immediately clear from the feedback which part is failing. So I wanted to have multiple it blocks for each route, but avoid making a new HTTP request inside each test, which feels stupidly redundant. The first thing I tried was to run the tests asynchronously from the request callback, but that didn’t agree with Mocha. There’s supposed to be a workaround for that, which is basically to wrap the tests in the callback in another describe (Node.js: Run mocha tests in a request callback). I don’t find it very elegant, but it could be the right solution, except I don’t seem to be able to get it to work.

One thing that did work for me was:

beforeAll {

  • restore database
  • send a POST request, cache the response
  • send a GET request, cache the response

    etc.

}

  • test the POST response
  • test the GET response

etc.

Here's the code for this approach.

What I like about this is that it minimizes the number of database operations, and even though I don’t reset the database before each test, I could run them in any order despite the fact that some of them (DELETE route tests) actually alter the database. But from what I’ve read about TDD/BDD, I gather that this is not a good design. The obvious flaw is the lack of isolation - if the first request fails, all of them will fail. What this means in practice is that if the API is broken, I would have to fix it in a specific order (POST first, etc.), which is not such a big deal in a small-scale application that I’m writing. But I understand that tests should never depend on external factors, so this is likely to be considered a bad testing practice.

Is the best solution here to go back to the first approach, i.e. place all assertions in one test per route? Or is there a better alternative?

Aucun commentaire:

Enregistrer un commentaire