okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

nekomimi.pettest: run the wall-clock-timed modules first and alone, not beside a hundred others9b3df98

main
2.3 KiB54 linesraw
1%% gleeunit's runner with every test module started at once, after the timed
2%% ones. A module's tests keep running in order, one after another, so tests
3%% that share a module's fixtures never race each other. There is no cap:
4%% eunit's {inparallel, N, _} runs batches of N and waits out each batch's
5%% slowest module.
6-module(albedo_test_runner).
7
8-export([main/0]).
9
10%% Modules whose tests wait out a wall-clock window (a runtime that must answer
11%% in a second while its store is suspended, a loopback server that must be
12%% reached in time). With a hundred modules starting at once those windows are
13%% starved, so these run first and alone: each passes under machine load by
14%% itself, and failed only against the rest of the suite.
15-define(TIMED, ['harness@runtime_test', 'harness@antigravity_errors_test',
16                'openai_api@transport_test']).
17
18main() ->
19    %% albedo_test.gleam is the executable entrypoint, not a test suite.
20    Modules = [module(Path) || Path <- filelib:wildcard("**/*_test.{erl,gleam}", "test"),
21                              Path =/= "albedo_test.gleam",
22                              not lists:prefix("manual/", Path)],
23    case Modules of [] -> error(no_test_modules); _ -> ok end,
24    lists:foreach(fun require_tests/1, Modules),
25    Timed = [Module || Module <- ?TIMED, lists:member(Module, Modules)],
26    Options = [
27        verbose,
28        no_tty,
29        {report, {gleeunit_progress, [{colored, true}]}},
30        {scale_timeouts, 10}
31    ],
32    Result = eunit:test([{inorder, Timed}, {inparallel, Modules -- Timed}], Options),
33    albedo_test_home:cleanup(),
34    erlang:halt(case Result of ok -> 0; _ -> 1 end).
35
36require_tests(Module) ->
37    {module, Module} = code:ensure_loaded(Module),
38    HasTests = lists:any(fun({Name, Arity}) ->
39        Arity =:= 0 andalso
40        (lists:suffix("_test", atom_to_list(Name)) orelse
41         lists:suffix("_test_", atom_to_list(Name)))
42    end, Module:module_info(exports)),
43    case HasTests of
44        true -> ok;
45        false -> error({no_tests_in_module, Module})
46    end.
47
48module(Path) ->
49    Name =
50        case filename:extension(Path) of
51            ".gleam" -> string:replace(filename:rootname(Path), "/", "@", all);
52            ".erl" -> filename:basename(Path, ".erl")
53        end,
54    list_to_atom(lists:flatten(Name)).