I’m working on making a Route type which can be used throughout my project to refer to the possible routes in my frontend and convert them to/from URLs. A common sanity check/test for this kind of thing is to try “round-tripping” routes through the to-URL/from-URL functions to ensure everything is covered and consistent. So I wrote a fuzzer for my Route type, which was straightforward.
I expect this type will change as I add pages to my project. When this happens, I will have to remember to update the fuzzer. If I don’t, my test will become invalid because the new cases I added will not be tested in the round trip.
Has anyone come up with a clever way to ensure that the fuzzer stays in sync with the underlying type? One idea I had was to add a dummy reminder function just under the fuzzer which does an exhaustive pattern match on the Route type. Then, if a constructor is added, at least the reminder function will break, and hopefully that will serve as a reminder to update the fuzzer. But maybe there’s another way?
I think the established pattern at this point is using a reminder, just like you said.
That is also what we used to do at my workplace. Now, we use a custom elm-review rule instead. By convention, we consider all values that look like allXyz : List Xyz to need to have all the constructors of the type Xyz, which gives us the following error message
-- ELM-REVIEW ERROR ------------------------------------------ src/Route.elm
NoMissingTypeConstructor: `allRoutes` does not contain all the type constructors for `Route`
11| allRoutes : List Route
12| allRoutes =
^^^^^^^^^
13| [ HomePage
We expect `allRoutes` to contain all the type constructors for `Route`.
In this case, you are missing the following constructors:
- SomePage
The code for it is in this gist. I will probably make a package for it at some point. The limitation is that you can only do this for types that are defined in the same file as the allXyz constant, but that limitating will change soon with an upcoming release of elm-review.
What I regret about this pattern, is that you lose this safety net as soon as someone renames the allXyz constant. But the reminder is brittle in a similar way, so