Fork me on GitHub
Mark Wardle07:05:15

Dear all, is the spec registry cleared between tests? I was just bitten by a surprising 'spec not found' exception during instrumentation in a project that uses one of my other projects as a library. My tests run successfully from the command-line, but when run in a brand-new, just loaded REPL, they fail because a specification was not found. It's an easy fix, as I haven't included a require, but surprised my tests didn't catch it. Finding it quite easy to accidentally omit the necessary requires as one flits back and forth between namespaces so the specs get loaded and then everything works. It's only in the context of trying to use as a library that I got an exception.


This seems no different to working with multimethods or protocols where you need to require the namespaces for the various implementations ahead of use?

Mark Wardle07:05:09

I guess so. But in that situation, my tests would fail. Here they worked, perhaps because the specs were loaded from one namespace, persist into a test on another namespace. At least, I presume that is what is happening.


If you're running multiple tests in the same process, state will persist, just as it would with multimethods or protocols.

Mark Wardle09:05:22

Thanks. I suppose trying to reset the global registry prior to running a test namespace might work, but sounds more complicated. I guess it an issue because I have specifications not linked to a clojure namespace reflecting my domain - so one doesn't notice easily if you don't have a require in a specific namespace.

Mark Wardle09:05:22

Is there an argument in favour of a test runner resetting global state before running a namespace?That would, I think, fix the issue.

Mark Wardle09:05:22

I'm finding it difficult that running all tests fails to throw an exception, but specifying a single namespace does throw an exception: I understand why this happens, but it is confusing, at least to me!


I don't think that a test runner could realistically "reset (all) global state)" -- partly because the test runner itself maintains global state about what tests it ran and what failures and successes (and some of that state is baked into clojure.test directly) unless you arrange to run the tests for each namespace in a separate process, which will add a huge amount of overhead to running your test suite.


At work, we run tests for each artifact's project in separate processes (via the Polylith test runner). Well, isolated classloader instances. We also have our build.clj perform each test run in a separate process (a separate JVM process) so we can test modules in isolation in our monorepo.


The Spec registry contains all the clojure.core.specs to, BTW.

Mark Wardle18:05:26

Thanks Sean. I didn't know that. So trying to reset the internal atom might not be such a good idea. Just shows the issues with global state :)