Funny output of zig test

Here is simple test:

const std = @import("std");
test "a test" {
    try std.testing.expect(1 == 1);
}

Let’s run it:

$ zig test t1.zig 
All 1 tests passed.

Everything seems Ok, but actually it’s not.

Here is another test, which actually tests nothing, just prints something:

const std = @import("std");

test "dummy test" {
    std.debug.print("{s}", .{"a"});
}

Running this test gives us this:

$ zig test t2.zig 
TAll 1 tests passed.
^ // what is it?!?!?

Ok, let’s add one letter:

$ cat t2.zig

const std = @import("std");

test "dummy test" {
    std.debug.print("{s}", .{"ab"});
}

And

$ zig test t2.zig 
TeAll 1 tests passed.
^^ // What the ... is going on?!?

Ok, one more letter, “abc”, result:

$ zig test t2.zig 
TesAll 1 tests passed.

Aha! “Tes” is probably the beginning of the word “Test”. Okaay, let’s output long string in the test, “abcdddddddddddddddddddddddddddddddddddd”:

$ zig test t2.zig 
Test [1/1] test.dummy test... abcddddddAll 1 tests passed.

Now take a look at tests examples in the documentation:

$ zig test test_comptime_variables.zig
1/1 test_comptime_variables.test.comptime vars... OK
All 1 tests passed.

It looks like there was "OK\n" after each test in a file, but then it has disappeared
and the final phrase is being output on the same line (probably after writing some backspaces or so). Was that intended? It’s very confusing actually.

I believe it is intended.
“Test [#/n] …” is printed by progress. “All tests passed.” is printed by test_runner.

Progress does not print a newline, it replaces the current line with [1/n], [2/n], etc
Specifically it clears a line in clearWithHeldLock.

2 Likes

The test runner and the build process use stdin/stdout to communicate. Because of this anything that you write to either in tests will not behave as expected.

3 Likes

Exactly - and after all tests are processed, I do not see which ones were successful and which ones failed, it is not convenient imo.

It does not matter, in real tests we are unlikely to print something (maybe test debug?..), I used this as an “instrument” to find out what is going on with the output.

If you don’t use the zig build test and you always run zig test, there are two ways to solve it.

  1. Redirect both stdout and stderr to avoid terminal code.
zig test t1.zig 2>&1 | /bin/cat -
  1. Copy and change lib/test_runner.zig (from your zig installation) and then run:
zig test t1.zig --test-runner /path/to/test_runner.zig

But you can do this very well by simply inserting a line feed after the output:

std.debug.print("{s}\n", .{"a"});
» zig test test1.zig
Test [1/1] test.dummy test... a
All 1 tests passed.
2 Likes

Yeah, of course.

test "test-A" {
    std.debug.print("{s}", .{"\nA1 begin \n"});
    try std.testing.expect(1 == 1);
    std.debug.print("{s}", .{"A1 end\n"});

    std.debug.print("{s}", .{"\nA2 begin \n"});
    try std.testing.expect(2 == 2);
    std.debug.print("{s}", .{"A2 end\n"});
}

test "test-B" {
    std.debug.print("{s}", .{"\n B begin"});
    try std.testing.expect(1 == 2);
    std.debug.print("{s}", .{"B end\n"});
}

Output:

$ zig test t1.zig 
Test [1/2] test.test-A... 
A1 begin 
A1 end

A2 begin 
A2 end
Test [2/2] test.test-B... 
Test [2/2] test.test-B... FAIL (TestUnexpectedResult)