announcements

tony.kay 2025-10-09T18:00:03.483019Z

Announcing test-filter (not feeling creating on naming šŸ˜„ ) Here’s the idea: I work on very large projects. Our test suite runs 7 different groups of tests and still takes 12 minutes. This wastes a lot of time and CI money. But, what if you had a tool that could analyze your source code, find all the transitive dependencies, look at your recent work (compare the SHA of current functions with the last successful run of that function) and tell you which tests could possibly be affected? That’s the goal of test-filter: Find the tests that matter, so you can just run those. So, far I know there are cases I’ve missed, and I think right now the best use of this tool is from the REPL during development to quickly run things you might have broken before handing it off to CI. Here are the cases I think it handles right: • Direct transitive dependency analysis. If test calls f calls g calls h, then a change to f, g, or h will run the test • Content normalization (remove docstrings) and hashing (every function’s code is hashed SHA256) so that trivial formatting edits/rearrange don’t affect tracking • Integration tests via metadata (integratoin tests probably use EVERY function in your code, so you can mark what is actually under test via metadata) • Work flow for REPL and CI Here are things that I have thought about, but won’t work: • Changing a global var (e.g. alter-var-root). For example imagine you change the global locale of your program, and a bunch of strings change. • More careful git analysis (in various ways) In fact, I really didn’t look at the git logic much at all, and haven’t personally tested it much. Consider this an alpha phase, even though it might look a bit polished in the readme šŸ˜„ https://github.com/fulcrologic/test-filter

šŸ‘ 4
šŸ‘šŸ» 1
6
šŸŽ‰ 22
tony.kay 2025-10-12T09:05:15.478919Z

Of course. I’ve been doing this for a few years, you know? ;)

Ben Sless 2025-10-12T09:07:41.598449Z

Hey, I try not to assume anything šŸ™ƒ How many people do you know who profiled their tests?

Ben Sless 2025-10-12T09:12:21.725849Z

;; btw all of this is not meant to knock your work, it's a good problem to solve and a good solution, I'm just biased against things being slow

tony.kay 2025-10-12T09:14:35.765999Z

Oh believe me so am I. I would have never written this many integration tests. But at a startup in the early phases you take what you can get to get things making money, and then you deal with it later.

tony.kay 2025-10-12T09:16:41.560539Z

and I’m an optimization/profiling fanatic. Look at the library code I just released…completely instrumented with tufte. Analyze on 250k LOC went from 3 minutes in the first iteration to about 1, etc. Kaocha has a nice plugin for profiling, but all of my slow tests are ā€œspin up server, run REST call, drop serverā€ā€¦The actual ā€œtestā€ guts is fast. It’s all that up/down/reseed db that’s the mess

Ben Sless 2025-10-12T09:17:35.761909Z

That's what I meant btw in another comment, can't you keep the server and DBs live between tests?

tony.kay 2025-10-12T09:17:37.035319Z

Combinatorial testing via integration tests…sooo bad šŸ˜ž

tony.kay 2025-10-12T09:18:23.854819Z

The db is h2 in memory for tests or datomic local. Those two are actually really fast. But the stack also spins up lots of other things (e.g. for job processing etc). It’s all in-memory stuff.

tony.kay 2025-10-12T09:18:54.623999Z

I’m sure there are ways I could make it faster, but not as fast as not having to run the tests to begin with. Most of these endpoints rarely change. Running them every time is the real waste

Ben Sless 2025-10-12T09:19:09.361709Z

Absolutely, the fastest code is the one which isn't ran

tony.kay 2025-10-12T09:19:45.662139Z

And I’m actually really pumped to have this working…I’ve been sitting on the idea for some time. Occurred to me Claude might push me over the edge for building it.

tony.kay 2025-10-12T09:20:21.082679Z

and in 3 days I got what would have probably take 3 weeks to get to this point. I had to direct it a lot, and do a lot of manual testing and suggesting automated tests

tony.kay 2025-10-12T09:21:55.435009Z

but I was also able to work on 2 other things (using CC) at the same time šŸ˜„

Ben Sless 2025-10-12T09:24:15.704859Z

I'm actually suffering some buyer's remorse for having used a LLM for writing something, hold the praise for Mr Certainly for a month or so šŸ™‚

Ben Sless 2025-10-11T11:10:02.398089Z

Can I ask why tests were taking 12 minutes to begin with?

tony.kay 2025-10-11T18:26:48.266989Z

We have a LOT of integration tests and 250k lines of code. So, loading the code in the JVM with tests takes a couple of minutes. Caching restore or deps download takes a few minutes. Roughly 5-6 minutes of the time is just overhead BEFORE the test even start running. So the tests themselves are about 5-7 minutes. There are 4379 tests total, with maybe a total of 20k or more assertions. Make even 10% of those integration tests that have to spin up a resources and it gets bad quickly

šŸ¤” 1
tony.kay 2025-10-11T18:27:55.395529Z

So, an MR that does a simple front-end fix (no CLJ changes) can now skip all of the tests. Someething that fixes a leaf node bug in clojure: probably skips 99% of them. I don’t have it fully integrated yet, but it’s going to make things a whole lot better.

🄳 1
Ben Sless 2025-10-11T19:22:41.801769Z

Depending on the CI environment, caching the dependencies can shave that down from minutes to a few seconds from my experience. Integration tests I also tweaked to persist external dependencies between tests in the same run and just clear their states. But judicious change detection and running only dependent tests is cool. Unison does that too.

Ben Sless 2025-10-11T19:24:38.965759Z

You also have a use case for asking for a faster compiler 😁

tony.kay 2025-10-11T20:15:51.586859Z

Of course I’m using caching, and we just happen to have a lot of transitive deps, so it isn’t seconds (unfortunately). There are all sorts of ways I can get the tests started quicker, but the reality is I’ve got 6 minutes (avg) for each of the parallel groups if I run all tests. So, with an instant cache AND instant compile I’ve still got six minutes. With this tool I hope to turn that into seconds (on average)

tony.kay 2025-10-11T20:17:03.179289Z

Also, with the code analysis it is much more likely that a dev will be able to run the set of tests in their already-initialized REPL in seconds, but will catch these ā€œdependent casesā€ before ever pushing an MR. That’s probably the real win.

🄳 1
Ben Sless 2025-10-12T03:31:23.711489Z

It's a bit of a long shot but have you ever tried profiling the tests to find if there are any glaring CPU hogs?

tony.kay 2025-10-10T09:35:36.051509Z

I have a number of almost immediate improvements in progress: change detection by function SHA, support for fulcro-spec’s specifications, better clarity around what’s cached, etc.

šŸŽ‰ 1
nberger 2025-10-10T18:25:23.847179Z

This looks great, thank you! Do you plan (or would you be open to a contribution) adding support for leiningen by any chance?

tony.kay 2025-10-10T19:57:58.579689Z

Contribute away! šŸ˜„ I’m doing this for my own company’s needs for faster turnaround in CI. So, my main interest is seeing my CI times go from 12 minutes to less than 5 (just restoring the caches and loading the project in the JVM takes 3-4 minutes…at that point I can rework the runner infra and maybe shave off another few) I got a lot more done on it earlier today, but it’s crashing on my large project, so a bit more bug fixing to go still.

šŸ‘ 1
tony.kay 2025-10-09T18:00:53.722069Z

Oh, and a shout-out to @borkdude. What I’ve got so far took 3 hours with Claude Code, but only because clj-kondo already has source analysis and works as a library!

5
6
šŸŽ‰ 6
beders 2025-10-16T20:35:56.038479Z

exactly what we were looking for! Awesome