Files
foxhunt/testing/test-common/src/assertions/custom_asserts.rs
jgrusewski 9c3d741a08 refactor: restructure repo — crates/, bin/, testing/ layout
Move 17 library crates into crates/, CLI binary into bin/fxt,
consolidate 10 test crates into testing/, split config crate
from deployment config files.

Root directory reduced from 38+ to ~17 directories.
All Cargo.toml paths and build.rs proto refs updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:56:00 +01:00

139 lines
3.4 KiB
Rust

//! Custom assertions for domain-specific testing
/// Assert that a value is within a percentage tolerance
#[macro_export]
macro_rules! assert_approx_eq {
($left:expr, $right:expr, $tolerance:expr) => {
let diff = ($left - $right).abs();
let threshold = $right.abs() * $tolerance;
assert!(
diff <= threshold,
"assertion failed: `{} ≈ {}` (tolerance: {}%)\n left: {}\n right: {}\n diff: {} > {}",
stringify!($left),
stringify!($right),
$tolerance * 100.0,
$left,
$right,
diff,
threshold
);
};
}
/// Assert that a value is within an absolute tolerance
#[macro_export]
macro_rules! assert_within {
($value:expr, $target:expr, $tolerance:expr) => {
let diff = ($value - $target).abs();
assert!(
diff <= $tolerance,
"assertion failed: `{} within {} of {}`\n value: {}\n target: {}\n diff: {}",
stringify!($value),
$tolerance,
stringify!($target),
$value,
$target,
diff
);
};
}
/// Assert that VaR exceedances are within expected range
pub fn assert_var_exceedances(
returns: &[f64],
var: f64,
confidence: f64,
max_deviation: f64,
) {
let exceedances = returns.iter().filter(|&&r| r.abs() > var).count();
let expected_exceedances = (returns.len() as f64 * (1.0 - confidence)) as usize;
let max_allowed = (expected_exceedances as f64 * (1.0 + max_deviation)) as usize;
assert!(
exceedances <= max_allowed,
"VaR exceedances {} exceed maximum {} (expected: {}, confidence: {}, tolerance: {}%)",
exceedances,
max_allowed,
expected_exceedances,
confidence,
max_deviation * 100.0
);
}
/// Assert that OHLC relationships are valid
pub fn assert_ohlc_valid(open: f64, high: f64, low: f64, close: f64) {
assert!(
high >= open,
"High {} must be >= Open {}",
high,
open
);
assert!(
high >= close,
"High {} must be >= Close {}",
high,
close
);
assert!(
low <= open,
"Low {} must be <= Open {}",
low,
open
);
assert!(
low <= close,
"Low {} must be <= Close {}",
low,
close
);
}
/// Assert that a position's PnL is correct
pub fn assert_pnl(
entry_price: f64,
current_price: f64,
quantity: f64,
expected_pnl: f64,
tolerance: f64,
) {
let actual_pnl = (current_price - entry_price) * quantity;
assert_within!(actual_pnl, expected_pnl, tolerance);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_assert_approx_eq() {
assert_approx_eq!(100.0, 101.0, 0.02); // 2% tolerance
}
#[test]
#[should_panic]
fn test_assert_approx_eq_fails() {
assert_approx_eq!(100.0, 105.0, 0.02); // Should fail
}
#[test]
fn test_assert_within() {
assert_within!(100.5, 100.0, 0.6);
}
#[test]
fn test_assert_ohlc_valid() {
assert_ohlc_valid(100.0, 102.0, 98.0, 101.0);
}
#[test]
#[should_panic]
fn test_assert_ohlc_invalid() {
assert_ohlc_valid(100.0, 98.0, 99.0, 101.0); // High < Open
}
#[test]
fn test_assert_pnl() {
assert_pnl(100.0, 110.0, 50.0, 500.0, 0.01);
}
}