Use std.testing.tmpDir for Fast Filesystem Tests in Zig
How to create a temporary directory, populate it with test files, and run code against it.
This recipe was written using Zig version
0.15.2. If this recipe is outdated, please let me know on X (@sepyke) or Bluesky (@pyk.sh).
Recently, I was building a simple library for my own, and in my build.zig I
required to list all Zig files in an examples directory and build them as
binaries. When writing tests for code that interacts with the filesystem, it’s
super helpful to have a clean, isolated environment. This recipe shows you how
to use std.testing.tmpDir to create a temporary directory, populate it with
test files, and then run your filesystem-related code against it.
std.testing.tmpDir is a really neat feature in Zig that lets you create a
temporary directory that automatically gets cleaned up when your test or
function finishes. This means you don’t have to worry about leaving junk files
behind or having your tests interfere with each other.
Here’s how you can use it:
const std = @import("std");
const fs = std.fs;
const mem = std.mem;
pub fn main() !void {
// Create a temporary directory. It will be cleaned up automatically.
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup(); // This ensures cleanup happens even if errors occur.
const test_dir = tmp.dir;
// Now, populate this temporary directory with some files and subdirectories.
try test_dir.makeDir("my_project");
try test_dir.writeFile(.{ .sub_path = "my_project/file1.zig", .data = "const a = 1;" });
try test_dir.writeFile(.{ .sub_path = "my_project/file2.txt", .data = "hello" });
try test_dir.makeDir("my_project/sub_dir");
try test_dir.writeFile(.{ .sub_path = "my_project/sub_dir/file3.zig", .data = "const b = 2;" });
std.debug.print("Contents of the temporary directory:\n", .{});
// Now you can run your code that interacts with the filesystem against `test_dir`.
// For example, let's list the files in 'my_project'.
var project_dir = try test_dir.openDir("my_project", .{ .iterate = true });
defer project_dir.close();
var iter = project_dir.iterate();
while (try iter.next()) |entry| {
std.debug.print("- {s} ({s})\n", .{ entry.name, @tagName(entry.kind) });
}
}Make sure Zig is installed:
$ zig version
0.15.2Then run it:
$ zig run tmp_dir_test.zig
Contents of the temporary directory:
- file1.zig (file)
- file2.txt (file)
- sub_dir (directory)