Skip to content

Commit 37cd47b

Browse files
committed
docs: add README
1 parent 2466f19 commit 37cd47b

1 file changed

Lines changed: 152 additions & 0 deletions

File tree

README.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
### exetest
2+
3+
CLI testing for Zig.
4+
5+
### Installation
6+
7+
1. Fetch the latest release:
8+
9+
```shell
10+
zig fetch --save=exetest https://github.com/pyk/exetest/archive/v0.1.0.tar.gz
11+
```
12+
13+
This updates `build.zig.zon`.
14+
15+
2. Write your test file. Example: `test/echo.zig`.
16+
17+
```zig
18+
const std = @import("std");
19+
const exetest = @import("exetest");
20+
const testing = std.testing;
21+
22+
test "echo" {
23+
const argv = &[_][]const u8{"echo", "hello"};
24+
var result = try exetest.run(.{ .argv = argv });
25+
defer result.deinit();
26+
27+
try testing.expectEqualStrings("hello\n", result.stdout);
28+
}
29+
```
30+
31+
3. Register the test in `build.zig`:
32+
33+
```zig
34+
const std = @import("std");
35+
const exetest = @import("exetest");
36+
37+
pub fn build(b: *std.Build) void {
38+
// ...
39+
const echo_test = exetest.add(b, .{
40+
.name = "echo",
41+
.test_file = b.path("test/echo.zig"),
42+
});
43+
44+
const test_step = b.step("test", "Run tests");
45+
test_step.dependOn(&echo_test.step);
46+
}
47+
```
48+
49+
4. Run the tests:
50+
51+
```shell
52+
zig build test --summary all
53+
```
54+
55+
See minimal Zig project
56+
[exetest-example](https://github.com/pyk/exetest-example).
57+
58+
### Usage
59+
60+
There are only 2 functions:
61+
62+
- `add(b, options)` registers a CLI test step in `build.zig`. `zig build test`
63+
will run the tests.
64+
- `run(options)` spawns a child process, captures stdout and stderr (up to a
65+
limit), waits for the child to finish, and returns a `RunResult`.
66+
67+
Basic run and stdout assertion:
68+
69+
```zig
70+
const std = @import("std");
71+
const exetest = @import("exetest");
72+
const testing = std.testing;
73+
74+
test "echo" {
75+
const argv = &[_][]const u8{"echo", "hello"};
76+
var result = try exetest.run(.{ .argv = argv });
77+
defer result.deinit();
78+
79+
try testing.expectEqualStrings("hello\n", result.stdout);
80+
}
81+
```
82+
83+
Write to stdin and capture stdout:
84+
85+
```zig
86+
const std = @import("std");
87+
const exetest = @import("exetest");
88+
const testing = std.testing;
89+
90+
test "cat" {
91+
const argv = &[_][]const u8{"cat"};
92+
const input = "a\nb\n";
93+
var r = try exetest.run(.{ .argv = argv, .stdin = input });
94+
defer r.deinit();
95+
96+
try testing.expectEqualStrings(input, r.stdout);
97+
}
98+
```
99+
100+
Limit how many stdin bytes are sent:
101+
102+
```zig
103+
const payload = large_slice; // some []const u8
104+
var res = try exetest.run(.{
105+
.argv = argv,
106+
.stdin = payload,
107+
.max_stdin_bytes = 1024, // truncate to 1 KiB
108+
});
109+
defer res.deinit();
110+
```
111+
112+
And you can do much more:
113+
114+
- Capture `stderr` output.
115+
- Limit how much output is captured.
116+
- Run with a custom working directory.
117+
- Run with a custom environment map.
118+
- Handle exit status and signals.
119+
- Detect spawn errors.
120+
121+
See [src/test_exe.zig](./src/test_exe.zig).
122+
123+
Some additional notes about the usage of `allocator`:
124+
125+
- `run` uses `testing.allocator` by default.
126+
- You can pass a different allocator in `RunOptions.allocator` to control where
127+
captured buffers are allocated.
128+
129+
### Development
130+
131+
Install the Zig toolchain via mise (optional):
132+
133+
```shell
134+
mise trust
135+
mise install
136+
```
137+
138+
Run tests:
139+
140+
```bash
141+
zig build test --summary all
142+
```
143+
144+
Build library:
145+
146+
```bash
147+
zig build
148+
```
149+
150+
### License
151+
152+
See [LICENSE](./LICENSE).

0 commit comments

Comments
 (0)