ReviewOS

also looking at this

zig-utils/zig-test-framework

Define stable JSON event protocol

#27
Merged glennmichael123 wants to merge codex/issue-10-json-events into main
11 files +442 -177
src/test_loader.zigmodified+35-19
Changes to src/test_loader.zig
@@ -7,6 +7,7 @@ const suite = ;
77const coverage = ;
88const ui_server = ;
99const compat = ;
10const protocol = ;
1011
1112/// Options for running discovered tests
1213pub const LoaderOptions = struct {
@@ -41,12 +42,6 @@ pub const LoaderOptions = struct {
4142 ui_server: ?*ui_server.UIServer = null,
4243};
4344
44fn broadcastJson(server: *ui_server.UIServer, allocator: std.mem.Allocator, event: []const u8, value: anytype) !void {
45 const json = try std.json.Stringify.valueAlloc(allocator, value, .{});
46 defer allocator.free(json);
47 try server.broadcast(event, json);
48}
49
5045/// Run all discovered test files
5146pub fn runDiscoveredTests(
5247 allocator: std.mem.Allocator,
@@ -107,7 +102,7 @@ pub fn runDiscoveredTests(
107102
108103 // Notify UI of run start
109104 if (options.ui_server) |server| {
110 try broadcastJson(server, allocator, "run_start", .{ .total = selected_files });
105 try server.broadcastEvent(allocator, .{ .run_start = .{ .total = selected_files } });
111106 }
112107
113108 var files_run: usize = 0;
@@ -129,8 +124,8 @@ pub fn runDiscoveredTests(
129124
130125 // Notify UI of test file start
131126 if (options.ui_server) |server| {
132 try broadcastJson(server, allocator, "suite_start", .{ .name = file.name });
133 try broadcastJson(server, allocator, "test_start", .{ .name = file.name });
127 try server.broadcastEvent(allocator, .{ .suite_start = .{ .name = file.name } });
128 try server.broadcastEvent(allocator, .{ .test_start = .{ .name = file.name, .suite = file.name } });
134129 }
135130
136131 files_run += 1;
@@ -182,14 +177,24 @@ pub fn runDiscoveredTests(
182177
183178 // Notify UI of test file end
184179 if (options.ui_server) |server| {
185 try broadcastJson(server, allocator, "test_end", .{
180 for (test_case.attempts.items) |attempt| {
181 try server.broadcastEvent(allocator, .{ .retry = .{
182 .name = file.name,
183 .attempt = attempt.number,
184 .repetition = attempt.repetition,
185 .status = protocol.status(attempt.status),
186 .duration_ns = attempt.duration_ns,
187 .error_message = attempt.error_message,
188 } });
189 }
190 try server.broadcastEvent(allocator, .{ .test_end = .{
186191 .name = file.name,
187 .status = @tagName(test_case.status),
188 .execution_time_ns = test_case.execution_time_ns,
189 .attempts = test_case.attempts.items.len,
190 .error_message = "",
191 });
192 try broadcastJson(server, allocator, "suite_end", .{ .name = file.name });
192 .suite = file.name,
193 .status = protocol.status(test_case.status),
194 .duration_ns = test_case.execution_time_ns,
195 .error_message = test_case.error_message,
196 } });
197 try server.broadcastEvent(allocator, .{ .suite_end = .{ .name = file.name } });
193198 }
194199
195200 if (test_case.status == .passed) {
@@ -213,19 +218,30 @@ pub fn runDiscoveredTests(
213218 std.debug.print("Warning: Could not parse coverage report: {any}\n", .{err});
214219 break :result null;
215220 };
216 if (cov_result) |summary| coverage.printCoverageSummary(summary);
221 if (cov_result) |summary| {
222 coverage.printCoverageSummary(summary);
223 if (options.ui_server) |server| {
224 try server.broadcastEvent(allocator, .{ .coverage = .{
225 .line_percent = summary.linePercentage(),
226 .function_percent = summary.functionPercentage(),
227 .branch_percent = summary.branchPercentage(),
228 .report_path = summary.report_dir,
229 } });
230 }
231 }
217232 }
218233 }
219234
220235 // Notify UI of run end
221236 if (options.ui_server) |server| {
222 try broadcastJson(server, allocator, "run_end", .{
237 try server.broadcastEvent(allocator, .{ .run_end = .{
223238 .total = results.total,
224239 .passed = results.passed,
225240 .flaky = results.flaky,
226241 .failed = results.failed,
227242 .skipped = results.skipped,
228 });
243 .duration_ns = results.total_time_ns,
244 } });
229245 }
230246
231247 if (options.shard) |shard| {