testing

Testing tools, testing philosophy & methodology...
athomasoriginal 2021-01-12T21:51:55.056600Z

Let’s say you have an app with a structure like this:

(defn some-route-handler [_] (do-stuff))

(defn routes [_] 
  "/some-route" some-route-handler)

(defn middleware-2 [handler] (fn [req] ...dostuff))

(defn middleware-1 [handler] (fn [req] ...dostuff))

(defn handler [_]
  (router routes {:middleware [middleware-1 middleware-2]}))

(http-server handler)
So, it’s pretty generic: app-server, handlers, middleware etc. Would you align to a testing strategy where you test middleware-1 , middleware-2 and some-route-handler as unit tests and then maybe setup a “happy path” integration style test which tests requests running through the whole http-server stack?

athomasoriginal 2021-01-12T21:54:19.057600Z

The reason I raise this is because I often see a mixture of the two and I often find myself wanting to lean towards unit testing most everything instead of creating a ton of integration tests. My theory: as long as all the little bits are tested, and the http server and routing libraries your using are tested, you should be confident that it will all work when pieced together

athomasoriginal 2021-01-12T21:55:13.058600Z

But then again integration tests also test all the bits, which possibly means less tests overall

seancorfield 2021-01-12T21:55:28.059200Z

If the middleware is simple, I probably wouldn't bother testing it separately. I may or may not test the underlying handler directly. I would definitely have tests of various routes through the whole stack though, because I'd want to ensure I had test coverage for the various documented error cases that the API/site could report back (as well as one or more happy cases).

seancorfield 2021-01-12T21:55:49.059600Z

I'd probably focus on unit-level tests for what the handler itself calls.

👍 1
Tim Robinson 2021-01-14T11:08:38.000100Z

I'd agree with this but also I'd say if the middleware is non-trivial you can usually factor it into 2 functions, one that fiddles with the request and another that fiddles with the response, which you can test separately.

athomasoriginal 2021-01-12T21:56:16.060100Z

Makes sense.

seancorfield 2021-01-12T21:57:01.061100Z

But that comes from a position where I often have a requirements spec for new features that is written at the level of HTTP requests (in some sense) and so I can write tests first for that level of functionality.

seancorfield 2021-01-12T21:58:37.062800Z

(specifically, at work we tend to get fairly solid specs for new REST endpoints for our main APIs and so I use TDD for those "in the large" -- even though, ultimately, those are integration level tests... I implement them using a mostly RDD workflow until I get passing tests, then review and refactor)

athomasoriginal 2021-01-12T22:03:09.063500Z

So, you’re approach would be different if you had an “evolving spec” + an “unestablished” system?

athomasoriginal 2021-01-12T22:03:46.064200Z

(i’m assuming your app, from what i’ve gathered, is pretty well defined overall…or maybe “mature” is a better word)

seancorfield 2021-01-12T22:28:36.065600Z

Yeah, how I go about writing tests usually depends on how well-specified the problem is 🙂 I try not to over-constrain my code in terms of tests if I think the behavior is going to change.

➕ 1