# ๐งช Test Runner Justfile
# Run `just` or `just help` to see this help.
set shell := ["bash", "-cu"]
set dotenv-load := true
set export := true
# set quiet := true # optional: hide all command echoing
# ---- Tunables ---------------------------------------------------------------
FEATURES := 'test-mode,dataframe' # cargo features for tests
TEST_THREADS := '1' # default for live/record (override: just TEST_THREADS=4 live)
FIXDIR := '' # default when YF_FIXDIR isn't set in the env
# ---- Helpers ----------------------------------------------------------------
banner MESSAGE:
@printf "\n\033[1mโถ %s\033[0m\n\n" "{{MESSAGE}}"
vars:
@echo "FEATURES = {{FEATURES}}"
@echo "TEST_THREADS = {{TEST_THREADS}}"
@echo "YF_FIXDIR = ${YF_FIXDIR:-{{FIXDIR}}}"
@echo "YF_LIVE = ${YF_LIVE:-}"
@echo "YF_RECORD = ${YF_RECORD:-}"
# ---- Recipes ----------------------------------------------------------------
default: help
help:
@just --list --unsorted
# NOTE on arg parsing:
# - If the first token looks like a test binary name (no leading `--`, no `::`),
# it's passed as `--test <name>` BEFORE `--`.
# - Everything else goes AFTER `--` to the harness.
# Offline (replay cached fixtures)
test-offline +args='':
@just banner "Offline tests (cached fixtures)"
@set -euo pipefail; \
TARGET_OPT=(); TEST_ARGS=(); \
if [ -n "{{args}}" ]; then \
set -- {{args}}; \
first="${1:-}"; shift || true; \
if [ -n "$first" ] && [[ "$first" != --* ]] && [[ "$first" != *::* ]]; then \
TARGET_OPT=(--test "$first"); \
TEST_ARGS=("$@"); \
else \
TEST_ARGS=("$first" "$@"); \
fi; \
fi; \
cargo test --features {{FEATURES}} "${TARGET_OPT[@]+"${TARGET_OPT[@]}"}" -- "${TEST_ARGS[@]+"${TEST_ARGS[@]}"}"
# Full live sweep (no writes; runs all tests including ignored)
test-live +args='':
@just banner "Live sweep (no writes, includes ignored)"
@set -euo pipefail; \
TARGET_OPT=(); TEST_ARGS=(); \
if [ -n "{{args}}" ]; then \
set -- {{args}}; \
first="${1:-}"; shift || true; \
if [ -n "$first" ] && [[ "$first" != --* ]] && [[ "$first" != *::* ]]; then \
TARGET_OPT=(--test "$first"); \
TEST_ARGS=("$@"); \
else \
TEST_ARGS=("$first" "$@"); \
fi; \
fi; \
YF_LIVE=1 cargo test --features {{FEATURES}} "${TARGET_OPT[@]+"${TARGET_OPT[@]}"}" -- --include-ignored --test-threads={{TEST_THREADS}} "${TEST_ARGS[@]+"${TEST_ARGS[@]}"}"
# Record fixtures (live โ cache)
test-record +args='':
@just banner "Recording fixtures (runs ignored tests)"
@set -euo pipefail; \
TARGET_OPT=(); TEST_ARGS=(); \
if [ -n "{{args}}" ]; then \
set -- {{args}}; \
first="${1:-}"; shift || true; \
if [ -n "$first" ] && [[ "$first" != --* ]] && [[ "$first" != *::* ]]; then \
TARGET_OPT=(--test "$first"); \
TEST_ARGS=("$@"); \
else \
TEST_ARGS=("$first" "$@"); \
fi; \
fi; \
YF_RECORD=1 cargo test --features {{FEATURES}} "${TARGET_OPT[@]+"${TARGET_OPT[@]}"}" -- --ignored --test-threads={{TEST_THREADS}} "${TEST_ARGS[@]+"${TEST_ARGS[@]}"}"
# Use a different fixture directory, then replay
test-with-fixdir dir='/tmp/yf-fixtures' +args='':
@just banner "Recording to {{dir}} then replaying offline"
@set -euo pipefail; \
TARGET_OPT=(); TEST_ARGS=(); \
if [ -n "{{args}}" ]; then \
set -- {{args}}; \
first="${1:-}"; shift || true; \
if [ -n "$first" ] && [[ "$first" != --* ]] && [[ "$first" != *::* ]]; then \
TARGET_OPT=(--test "$first"); \
TEST_ARGS=("$@"); \
else \
TEST_ARGS=("$first" "$@"); \
fi; \
fi; \
export YF_FIXDIR="{{dir}}"; \
YF_RECORD=1 cargo test --features {{FEATURES}} "${TARGET_OPT[@]+"${TARGET_OPT[@]}"}" -- --ignored --test-threads={{TEST_THREADS}} "${TEST_ARGS[@]+"${TEST_ARGS[@]}"}"; \
cargo test --features {{FEATURES}} "${TARGET_OPT[@]+"${TARGET_OPT[@]}"}" -- "${TEST_ARGS[@]+"${TEST_ARGS[@]}"}"
# Full test: clear phase markers; only run offline if live/record passes
test-full +args='':
@just banner "Full test (Phase 1: live/record โ Phase 2: offline)"
@set -euo pipefail; \
ts() { date '+%Y-%m-%d %H:%M:%S'; }; \
TARGET_OPT=(); TEST_ARGS=(); \
if [ -n "{{args}}" ]; then \
set -- {{args}}; \
first="${1:-}"; shift || true; \
if [ -n "$first" ] && [[ "$first" != --* ]] && [[ "$first" != *::* ]]; then \
TARGET_OPT=(--test "$first"); \
TEST_ARGS=("$@"); \
else \
TEST_ARGS=("$first" "$@"); \
fi; \
fi; \
echo "[$(ts)] ๐ฆ Phase 1/2 START โ Live/Record (runs ignored, writes fixtures)"; \
if YF_RECORD=1 cargo test --features {{FEATURES}} "${TARGET_OPT[@]+"${TARGET_OPT[@]}"}" -- --ignored --test-threads={{TEST_THREADS}} "${TEST_ARGS[@]+"${TEST_ARGS[@]}"}"; then \
echo "[$(ts)] โ
Phase 1/2 PASS โ Live/Record passed"; \
echo "[$(ts)] ๐ฉ Phase 2/2 START โ Offline replay (cached fixtures)"; \
if cargo test --features {{FEATURES}} "${TARGET_OPT[@]+"${TARGET_OPT[@]}"}" -- "${TEST_ARGS[@]+"${TEST_ARGS[@]}"}"; then \
echo "[$(ts)] โ
Phase 2/2 PASS โ Offline replay passed"; \
echo "[$(ts)] ๐ Full test complete: BOTH phases passed"; \
else \
status=$?; \
echo "[$(ts)] โ Phase 2/2 FAIL โ Offline replay failed (exit $status)"; \
echo "Tip: re-run only the offline pass with:"; \
echo " just test-offline {{args}}"; \
exit $status; \
fi; \
else \
status=$?; \
echo "[$(ts)] โ Phase 1/2 FAIL โ Live/Record failed (exit $status)"; \
echo "Skipping offline. Tip: re-run only the live/record pass with:"; \
echo " just test-record {{args}}"; \
exit $status; \
fi
test-full-debug +args='':
@just banner "Full test DEBUG (Phase 1: live/record โ Phase 2: offline)"
@set -euo pipefail; \
ts() { date '+%Y-%m-%d %H:%M:%S'; }; \
TARGET_OPT=(); TEST_ARGS=(); \
if [ -n "{{args}}" ]; then \
set -- {{args}}; \
first="${1:-}"; shift || true; \
if [ -n "$first" ] && [[ "$first" != --* ]] && [[ "$first" != *::* ]]; then \
TARGET_OPT=(--test "$first"); \
TEST_ARGS=("$@"); \
else \
TEST_ARGS=("$first" "$@"); \
fi; \
fi; \
echo "[$(ts)] ๐ฆ Phase 1/2 START โ Live/Record DEBUG (runs ignored, writes fixtures)"; \
if YF_DEBUG=1 YF_RECORD=1 cargo test --features {{FEATURES}} "${TARGET_OPT[@]+"${TARGET_OPT[@]}"}" -- --ignored --test-threads={{TEST_THREADS}} "${TEST_ARGS[@]+"${TEST_ARGS[@]}"}"; then \
echo "[$(ts)] โ
Phase 1/2 PASS โ Live/Record passed"; \
echo "[$(ts)] ๐ฉ Phase 2/2 START โ Offline replay DEBUG (cached fixtures)"; \
if YF_DEBUG=1 cargo test --features {{FEATURES}} "${TARGET_OPT[@]+"${TARGET_OPT[@]}"}" -- "${TEST_ARGS[@]+"${TEST_ARGS[@]}"}"; then \
echo "[$(ts)] โ
Phase 2/2 PASS โ Offline replay passed"; \
echo "[$(ts)] ๐ Full debug test complete: BOTH phases passed"; \
else \
status=$?; \
echo "[$(ts)] โ Phase 2/2 FAIL โ Offline replay failed (exit $status)"; \
echo "Tip: re-run only the offline pass with:"; \
echo " just test-offline {{args}}"; \
exit $status; \
fi; \
else \
status=$?; \
echo "[$(ts)] โ Phase 1/2 FAIL โ Live/Record failed (exit $status)"; \
echo "Skipping offline. Tip: re-run only the live/record pass with:"; \
echo " just test-record {{args}}"; \
exit $status; \
fi
test +args='':
@just banner "Alias: test โ test-full"
just test-full {{args}}
lint:
cargo clippy --workspace --all-targets --all-features -- \
-W clippy::all -W clippy::cargo -W clippy::pedantic -W clippy::nursery -A clippy::multiple-crate-versions -D warnings
# just lint-fix [optional flags...]
# Example: just lint-fix --allow-dirty
# just lint-fix --allow-dirty --allow-staged
lint-fix *FLAGS:
cargo clippy --workspace --all-targets --all-features --fix {{FLAGS}} -- \
-W clippy::all -W clippy::cargo -W clippy::pedantic -W clippy::nursery -A clippy::multiple-crate-versions -D warnings
fmt:
cargo fmt --all