Quick question. Assuming you already use stable-* git tagging to target changed components for testing, what other strategies do people employ to keep the testing cycle under control? In a polylith repo with lots of projects, many sharing the same components, running the same unit tests multiple times soon adds up. More recently I've moved to unit testing the dev project only and, prior to push and pr, force-running a generic startup brick test for each project. Of course, it helps that all my project services start/stop the same way, and most of my historical project test failures are either: missing bricks in the project's deps, or missing requires for multi-methods that a project needs. Just curious as to the go-to strategy for you all.
poly test project:dev
poly test brick:test-startup :allThe real issue we've found is how stable those "widely-shared" components are? If a component is really widely-used, it should also be really stable and rarely need changes. In that case, you don't get a cascade of tests running. That said, of course we do sometimes make changes that cause "everything" to be re-tested. We just updated Clojure from 1.13 Alpha 6 to Alpha 7 so every project needed to be re-tested.
I also tend to run tests from the editor via the REPL while I'm working, so that's just tests for one ns, so that's how I shorten that feedback loop.
Thanks @seancorfield for sharing. As a segue, on the subject of widely-shared components, I deliberately put all my foundational components into their own https://github.com/repldriven/mono repo. This was not to circumvent testing overhead, but to promote component sharing across polylith more broadly (as a result, it's more inconvenient for me though). It's not for everyone, and is highly opinionated, but it stops me from doing system work when I should be focussing on product delivery.
We're fortunate enough to be able to have our entire company's backend code in a single (Polylith) monorepo but I can see how that might not work for larger companies.
I have the same experience as @seancorfield Also I think there are cases where stable could be used prematurely. Sometimes your tests pass but it was because of certain require order. That's why I wanted shuffling (in Sean's external-test-runner) And I think there is something with the use of protocols and multimethods where dependencies might go undetected. My intuition I didn't work out an isolated case. So in summary it is good to frequently do a full test anyway. But could be scheduled or something
One speed-up I employ is to use eftest in the external-test-runner, so namespace tests run in multiple threads in each project's test JVM. I do need to be mindful to annotate test namespaces with ^:eftest/synchronized where there is global JVM state (or with-redefs) but, conversely, that's helped in my understanding of state dependencies I didn't know I had when the tests failed in a multi-threaded use case. Using mono, this is a simple to drop into any polylith project now.
Interesting. How do you use eftest with the external-test-runner?
Oh, you built your own e.t.r.! Got it.
Well, I think you know, it's your code mangled for my purposes! I'll put together a simple example of how you can import it and use it in a minute, as I wasn't expecting this much interest :-)
We have a mix of clojure.test and LazyTest at work so eftest wouldn't work for us, but thanks.
So, I thought about pasting an example, but I'd make a typo. It's easier to just follow the instructions to create a new project from the mono template and look at the code instead: https://github.com/repldriven/mono#start-a-new-workspace-recommended