ReviewOS

also looking at this

zig-utils/zig-test-framework

Add reproducible randomized test order

#29
Merged glennmichael123 wants to merge codex/issue-14-random-order into main
18 files +487 -42
src/test_history.zigmodified+17-2
Changes to src/test_history.zig
@@ -13,6 +13,7 @@ pub const HistoryEntry = struct {
1313 failed: usize,
1414 skipped: usize,
1515 duration_ns: u64,
16 random_seed: ?u64 = null,
1617 tests: std.ArrayList(TestRecord),
1718
1819 pub fn deinit(self: *HistoryEntry, allocator: std.mem.Allocator) void {
@@ -65,6 +66,11 @@ pub const TestHistory = struct {
6566
6667 /// Start recording a new test run
6768 pub fn startRun(self: *Self, total: usize) !void {
69 try self.startRunWithSeed(total, null);
70 }
71
72 /// Start recording a run with optional randomized-order metadata.
73 pub fn startRunWithSeed(self: *Self, total: usize, random_seed: ?u64) !void {
6874 self.start_time = compat.milliTimestamp();
6975
7076 self.current_entry = HistoryEntry{
@@ -75,6 +81,7 @@ pub const TestHistory = struct {
7581 .failed = 0,
7682 .skipped = 0,
7783 .duration_ns = 0,
84 .random_seed = random_seed,
7885 .tests = std.ArrayList(TestRecord).empty,
7986 };
8087 }
@@ -117,6 +124,7 @@ pub const TestHistory = struct {
117124 self.current_entry.?.flaky = results.flaky;
118125 self.current_entry.?.failed = results.failed;
119126 self.current_entry.?.skipped = results.skipped;
127 self.current_entry.?.random_seed = results.random_seed orelse self.current_entry.?.random_seed;
120128
121129 try self.saveToFile();
122130 }
@@ -139,7 +147,10 @@ pub const TestHistory = struct {
139147 errdefer buffer = allocating.toArrayList();
140148 const writer = &allocating.writer;
141149 try writer.writeAll("[\n");
142 try std.json.Stringify.value(protocol.Event{ .run_start = .{ .total = self.current_entry.?.total } }, .{}, writer);
150 try std.json.Stringify.value(protocol.Event{ .run_start = .{
151 .total = self.current_entry.?.total,
152 .random_seed = self.current_entry.?.random_seed,
153 } }, .{}, writer);
143154 for (self.current_entry.?.tests.items) |test_record| {
144155 try writer.writeAll(",\n");
145156 try std.json.Stringify.value(protocol.Event{ .test_end = .{
@@ -158,6 +169,7 @@ pub const TestHistory = struct {
158169 .failed = self.current_entry.?.failed,
159170 .skipped = self.current_entry.?.skipped,
160171 .duration_ns = self.current_entry.?.duration_ns,
172 .random_seed = self.current_entry.?.random_seed,
161173 } }, .{}, writer);
162174 try writer.writeAll("\n]\n");
163175 try writer.flush();
@@ -192,6 +204,7 @@ pub const TestHistory = struct {
192204 .failed = 0,
193205 .skipped = 0,
194206 .duration_ns = 0,
207 .random_seed = null,
195208 .tests = std.ArrayList(TestRecord).empty,
196209 };
197210 }
@@ -258,7 +271,7 @@ test "TestHistory saves versioned protocol events" {
258271
259272 var history = TestHistory.init(allocator, history_dir);
260273 defer history.deinit();
261 try history.startRun(1);
274 try history.startRunWithSeed(1, 9876);
262275 try history.recordTest("quoted \"test\"", "suite\nname", .passed, 42, null);
263276 var results = reporter_mod.TestResults.init(allocator);
264277 defer results.deinit();
@@ -277,9 +290,11 @@ test "TestHistory saves versioned protocol events" {
277290 const events = parsed.value.array.items;
278291 try std.testing.expectEqual(@as(usize, 3), events.len);
279292 try std.testing.expectEqualStrings("run_start", events[0].object.get("type").?.string);
293 try std.testing.expectEqual(@as(i64, 9876), events[0].object.get("data").?.object.get("random_seed").?.integer);
280294 try std.testing.expectEqualStrings("test_end", events[1].object.get("type").?.string);
281295 try std.testing.expectEqualStrings("quoted \"test\"", events[1].object.get("data").?.object.get("name").?.string);
282296 try std.testing.expectEqualStrings("run_end", events[2].object.get("type").?.string);
297 try std.testing.expectEqual(@as(i64, 9876), events[2].object.get("data").?.object.get("random_seed").?.integer);
283298 for (events) |event| {
284299 try std.testing.expectEqual(@as(i64, protocol.version), event.object.get("protocol_version").?.integer);
285300 }