This is somewhat related to the conversation, would probably warrant a different enhancement issue on the tracker if accepted, but felt like I should mention it here before I make an issue. Note that this is just an idea and I have no clue if it would be feasible in the compiler, as I am not a compiler dev, but I believe it should be?
Imagine the following:
fn foo() !void {
try bar();
}
test foo {
try foo();
}
fn bar() !void {
return error.Bogus;
}
test bar {
try bar();
}
We can see that bar() will always fail and the decltest for it will always fail. As far as I’m aware, builtin.test_functions is ordered by the compiler evaluation order, which in my experience has meant that test foo will fail before test bar does (NOTE: this is based on 0.15.2, I have limited 0.16 testing experience, but AFAIK it hasn’t changed)
I propose that a test graph is generated, where each node is a test, with the goal of executing leafs first, then the parents of the leafs, the parents of the parents of the leafs and so on, with potentially the ability to do the reverse of that, first evaluating higher level test cases and going down.
This has the advantage of, for example, in a HTTP server if your database query is failing, your database tests would fail before your endpoint implementation tests do, thus making it easier on the reader to determine who’s fault it was.
This works the most straightforward with decltests as the compiler would be able to go "oh, foo calls the function bar and we have a decltest for bar", as opposed to a regular test where it is more implicit what the test block is doing and the compiler has no clue on what to do.
I have written a custom test runner for this a while back, but it’s not as complicated as it is just for one usecase only, so it looks something like
for (builtin.test_functions) |t| {
const name = makeNameFriendly(t.name);
if (isEndpoint(name)) { // std.mem.startsWith(u8, test_name, "Endpoint |");
try endpoint_queue.test_functions.append(allocator, t);
continue;
}
if (isModel(name)) { // std.mem.startsWith(u8, test_name, "Model |");
try model_queue.test_functions.append(allocator, t);
continue;
}