ZUnit is a powerful unit testing framework for Zsh.
ZUnit includes observer-safe snapshots for testing the clean portable lifecycle defined by Zsh Plugin Standard 2. Prime the observer before the baseline, then name each snapshot with portable ASCII letters, digits, or underscores:
zunit_plugin_contract_prime
zunit_plugin_contract_snapshot before
source ./example.plugin.zsh
zunit_plugin_contract_snapshot loaded
assert before plugin_load_surface loaded \
function:example_refresh \
function:example_plugin_unload \
parameter:_example_state \
style::example:config:mode
source ./example.plugin.zsh
zunit_plugin_contract_snapshot repeated
assert loaded plugin_restored repeated
example_plugin_unload
zunit_plugin_contract_snapshot after
assert before plugin_restored afterThe load-surface allowlist accepts exact resource identities. Available
families are function, parameter, alias, option, trap, module,
path, fpath, hook, widget, binding, and style. A failure reports
resource identities only; captured parameter values are never printed.
For an ownership-aware unload test, take a snapshot after load, another after simulating post-load user changes, and one after unload:
assert before plugin_unloaded loaded user_changed afterFor each resource, this assertion restores the pre-load value when the user did not change the plugin-owned value, otherwise it requires unload to preserve the user's newer value. Use separate clean-shell tests for hostile initial state, partial initialization failure, and interactive behavior.
Repeated source does not prove that a plugin works after it was unloaded. In another clean shell, load, unload, and load again, then compare the second load with the first and observe that each restored handler, hook, widget or other resource still does its job; its presence or a zero status alone would accept an inert stub. Every restored resource with its own behavior needs its own check:
zunit_plugin_contract_prime
source ./example.plugin.zsh
zunit_plugin_contract_snapshot loaded
example_plugin_unload
source ./example.plugin.zsh
zunit_plugin_contract_snapshot reloaded
assert loaded plugin_restored reloaded
run example_refresh
assert $state equals 0
assert "$output" same_as 'refreshed'The repository's tests/_support/plugin-contract/scenario.zsh demonstrates
repeated source, partial failure, hostile state, post-load changes, reload
after unload, and both zsh -f and zsh -f -i execution. Its reload
scenario checks the fixture's one callback, which the fixture's hook and
widget both dispatch to.
The canonical documentation for ZUnit, including installation guides, test syntax, and CI integration, has moved to the Z-Shell Wiki:
👉 Z-Shell Wiki: ZUnit Documentation
This repository is maintained by the Z-Shell organization as the active workspace mirror used by the wider Zi/Z-Shell ecosystem. Historical upstream links are preserved where they still describe the original project, while runtime integrations continue to follow the currently published package coordinates used across the ecosystem.
Note: The
z-shell/zunitrepository is the active development mirror; runtime package coordinates (e.g. for Homebrew or zplug) may still referencez-shell/zunitto avoid breaking existing user configurations.
The Z-Shell mirror validates the project with GitHub Actions using native tests, Zsh syntax checks, and a scheduled Zsh compatibility matrix.
As a maintained Z-Shell repository, this mirror follows the organization's class-2 testing and CI strategy and repository settings baseline. Its fork status affects audit sampling, not the applicability of those policies.
Copyright (c) 2016 James Dinsdale hi@molovo.co (molovo.co) ZUnit is licensed under The MIT License (MIT)
