Repository navigation
v0.0.1
Full Changelog: https://github.com/dylibso/xtp-test-zig/commits/v0.0.1
xtp-test
A Zig test framework for xtp /
Extism plugins.
Example
const std = @import("std");
const Test = @import("xtp-test").Test;
const CountVowel = struct {
total: u32,
count: u32,
vowels: []const u8,
};
// you _must_ export a single `test` function (in Zig, "test" is a keyword, so use this raw literal syntax)
export fn @"test"() i32 {
// initialize your test to run functions in a target plugin
const xtp_test = Test.init(std.heap.wasm_allocator);
xtp_test.assert("this is a test", true);
// run the "count_vowels" function in the target plugin and assert the output is as expected
const output = xtp_test.call("count_vowels", "this is a test") catch unreachable;
const cv = fromJson(output);
xtp_test.assertEq("count_vowels returns expected count", cv.count, 4);
// create a group of tests inside a new scope, use defer to close the group at the end of the scope
// NOTE: creating a group will reset the target plugin, before the group starts and after it's closed
{
const maintain_state_group = xtp_test.newGroup("plugin should maintain state");
defer maintain_state_group.close();
var accumTotal: u32 = 0;
for (0..10) |_| {
const loop_output = xtp_test.call("count_vowels", "this is a test") catch unreachable;
const loop_cv = fromJson(loop_output);
accumTotal += cv.count;
const msg = std.fmt.allocPrint(std.heap.wasm_allocator, "count_vowels returns expected incremented total: {}", .{accumTotal}) catch unreachable;
xtp_test.assertEq(msg, loop_cv.total, accumTotal);
}
}
// create a group without a scope, and close it manually at the end of your tests
const simple_group = xtp_test.newGroup("simple timing tests");
// get the number of seconds elapsed in the "count_vowels" function using some input
const sec = xtp_test.timeSec("count_vowels", "this is a test");
xtp_test.assert("it should be fast", sec < 0.5);
// get the number of nanoseconds elapsed in the "count_vowels" function using some input
const ns = xtp_test.timeNs("count_vowels", "this is a test");
xtp_test.assert("it should be really fast", ns < 1e5);
simple_group.close();
return 0;
}
fn fromJson(json: []const u8) CountVowel {
const cv = std.json.parseFromSlice(CountVowel, std.heap.wasm_allocator, json, .{}) catch unreachable;
return cv.value;
}API Docs
See the main.zig file for the public API of this library.
Usage
1. Create a Zig project using the XTP Test library
mkdir zig-xtp-test
cd zig-xtp-test
zig init
zig fetch --save https://github.com/dylibso/xtp-test-zig/archive/v0.0.1.tar.gz
# see the `build.zig` in this repo for examples on how to configure it2. Write your test in Zig
const std = @import("std");
const Test = @import("xtp-test").Test;
const CountVowel = struct {
total: u32,
count: u32,
vowels: []const u8,
};
// you _must_ export a single `test` function (in Zig, "test" is a keyword, so use this raw literal syntax)
export fn @"test"() i32 {
// initialize your test to run functions in a target plugin
const xtp_test = Test.init(std.heap.wasm_allocator);
xtp_test.assert("this is a test", true);
// run the "count_vowels" function in the target plugin and assert the output is as expected
const output = xtp_test.call("count_vowels", "this is a test") catch unreachable;
const cv = fromJson(output);
xtp_test.assertEq("count_vowels returns expected count", cv.count, 4);
...3. Compile your test to .wasm:
Ensure your build.zig is set up properly to compile to wasm32 freestanding
or wasi. See the
Extism zig-pdk examples or the
build.zig in this repository for more details.
zig build
# which should output a .wasm into zig-out/bin/4. Run the test against your plugin: Once you have your test code as a
.wasm module, you can run the test against your plugin using the xtp CLI:
Install xtp
curl https://static.dylibso.com/cli/install.sh | sudo shRun the test suite
xtp plugin test ./plugin-*.wasm --with test.wasm --host host.wasm
# ^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^
# your plugin(s) test to run optional mock host functionsNote: The optional mock host functions must be implemented as Extism
plugins, whose exported functions match the host function signature imported by
the plugins being tested.
Need Help?
Please reach out via the
#xtp channel on Discord.