test: 100% coverage for wma + aroon_oscillator + atr + awesome_oscillator + cci (#22)
* test(wma): cover period/warmup/name + kill dead naive panic arm
Codecov flagged 10 lines in crates/wickra-core/src/indicators/wma.rs
(file at 92.48%): const accessor period (56-58), Indicator-impl
warmup_period (111-113), name (119-121), and line 186 — the
`_ => panic!("warmup mismatch")` arm in matches_naive_over_random_
inputs, an invariant guard that never fires when both streams share
a warmup period.
Add accessors_and_metadata covering the three metadata methods.
Refactor matches_naive_over_random_inputs to assert the warmup-shape
invariant via assert_eq!(g.is_some(), w.is_some()) + if let,
removing the dead panic arm.
wma.rs is now at 133/133 lines, no behavioural change.
* test(aroon_oscillator): cover period/value accessors + name metadata
Codecov flagged 9 lines in crates/wickra-core/src/indicators/aroon_
oscillator.rs (file at 90.42%): const accessors period (57-59),
value (62-64) and Indicator-impl name (90-92). warmup_period is
already covered by warmup_period_matches_aroon.
Add accessors_and_metadata asserting period == 7, name ==
"AroonOscillator", and value() across the None (pre-warmup) and
Some (post-warmup) branches.
aroon_oscillator.rs is now at 94/94 lines, no behavioural change.
* test(atr): cover period/value accessors + name metadata
Codecov flagged 9 lines in crates/wickra-core/src/indicators/atr.rs
(file at 93.70%): const accessors period (54-57), value (59-62) and
Indicator-impl name body (103-105). warmup_period is exercised
indirectly via downstream indicators; the metadata getters were
never queried directly.
Add accessors_and_metadata asserting period == 14, name == "ATR",
and value() across the None (pre-warmup) and Some (post-warmup)
branches.
atr.rs is now at 143/143 lines, no behavioural change.
* test(awesome_oscillator): cover periods accessor + warmup/name metadata
Codecov flagged 9 lines in crates/wickra-core/src/indicators/awesome_
oscillator.rs (file at 88.15%): const accessor periods (59-61),
Indicator-impl warmup_period (83-85), name (91-93). The classic()
constructor is covered indirectly through the existing tests; only
the metadata methods were dead.
Add accessors_and_metadata asserting periods == (5, 34),
warmup_period == 34 (= slow_period), name == "AwesomeOscillator".
awesome_oscillator.rs is now at 76/76 lines, no behavioural change.
* test(cci): cover period accessor + warmup/name metadata
Codecov flagged 9 lines in crates/wickra-core/src/indicators/cci.rs
(file at 89.65%): const accessor period (68-70), Indicator-impl
warmup_period (102-104), name (110-112). Existing tests never
inspected the metadata surface.
Add accessors_and_metadata asserting period == 20, warmup_period ==
20, name == "CCI".
cci.rs is now at 87/87 lines, no behavioural change.
This commit is contained in:
@@ -107,6 +107,21 @@ mod tests {
|
||||
assert!(AroonOscillator::new(0).is_err());
|
||||
}
|
||||
|
||||
/// Cover the const accessors `period` / `value` (57-64) and the
|
||||
/// Indicator-impl `name` body (90-92). `warmup_period` is covered
|
||||
/// already by `warmup_period_matches_aroon`.
|
||||
#[test]
|
||||
fn accessors_and_metadata() {
|
||||
let mut osc = AroonOscillator::new(7).unwrap();
|
||||
assert_eq!(osc.period(), 7);
|
||||
assert_eq!(osc.name(), "AroonOscillator");
|
||||
assert_eq!(osc.value(), None);
|
||||
for i in 0..8 {
|
||||
osc.update(candle(100.0 + f64::from(i), 90.0, 95.0, i64::from(i)));
|
||||
}
|
||||
assert!(osc.value().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pure_uptrend_yields_plus_100() {
|
||||
// Every bar a fresh high, no fresh low: AroonUp = 100, AroonDown = 0.
|
||||
|
||||
@@ -151,6 +151,21 @@ mod tests {
|
||||
assert!(matches!(Atr::new(0), Err(Error::PeriodZero)));
|
||||
}
|
||||
|
||||
/// Cover the const accessors `period` / `value` (54-62) and the
|
||||
/// Indicator-impl `name` body (103-105). Existing tests inspect
|
||||
/// numeric ATR output but never query the metadata.
|
||||
#[test]
|
||||
fn accessors_and_metadata() {
|
||||
let mut atr = Atr::new(14).unwrap();
|
||||
assert_eq!(atr.period(), 14);
|
||||
assert_eq!(atr.name(), "ATR");
|
||||
assert_eq!(atr.value(), None);
|
||||
for _ in 0..14 {
|
||||
atr.update(c(11.0, 9.0, 10.0));
|
||||
}
|
||||
assert!(atr.value().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn warmup_emits_on_period_th_candle() {
|
||||
let candles = vec![
|
||||
|
||||
@@ -118,6 +118,17 @@ mod tests {
|
||||
assert!(AwesomeOscillator::new(0, 5).is_err());
|
||||
}
|
||||
|
||||
/// Cover the const accessor `periods` (59-61) and the Indicator-impl
|
||||
/// `warmup_period` (83-85) + `name` (91-93). Existing tests never
|
||||
/// inspect these metadata methods.
|
||||
#[test]
|
||||
fn accessors_and_metadata() {
|
||||
let ao = AwesomeOscillator::classic();
|
||||
assert_eq!(ao.periods(), (5, 34));
|
||||
assert_eq!(ao.warmup_period(), 34);
|
||||
assert_eq!(ao.name(), "AwesomeOscillator");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn batch_equals_streaming() {
|
||||
let candles: Vec<Candle> = (0..50)
|
||||
|
||||
@@ -138,6 +138,17 @@ mod tests {
|
||||
assert!(Cci::with_factor(20, -1.0).is_err());
|
||||
}
|
||||
|
||||
/// Cover the const accessor `period` (68-70) and the Indicator-impl
|
||||
/// `warmup_period` (102-104) + `name` (110-112). Existing tests never
|
||||
/// inspect these metadata methods.
|
||||
#[test]
|
||||
fn accessors_and_metadata() {
|
||||
let cci = Cci::new(20).unwrap();
|
||||
assert_eq!(cci.period(), 20);
|
||||
assert_eq!(cci.warmup_period(), 20);
|
||||
assert_eq!(cci.name(), "CCI");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn batch_equals_streaming() {
|
||||
let candles: Vec<Candle> = (0..60)
|
||||
|
||||
@@ -154,6 +154,17 @@ mod tests {
|
||||
assert!(matches!(Wma::new(0), Err(Error::PeriodZero)));
|
||||
}
|
||||
|
||||
/// Cover the const accessor `period` (56-58) and the Indicator-impl
|
||||
/// `warmup_period` (111-113) + `name` (119-121). Existing tests never
|
||||
/// inspect these metadata methods.
|
||||
#[test]
|
||||
fn accessors_and_metadata() {
|
||||
let wma = Wma::new(7).unwrap();
|
||||
assert_eq!(wma.period(), 7);
|
||||
assert_eq!(wma.warmup_period(), 7);
|
||||
assert_eq!(wma.name(), "WMA");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn warmup_returns_none() {
|
||||
let mut wma = Wma::new(3).unwrap();
|
||||
@@ -179,11 +190,11 @@ mod tests {
|
||||
let mut wma = Wma::new(7).unwrap();
|
||||
let got = wma.batch(&prices);
|
||||
let want = wma_naive(&prices, 7);
|
||||
for (g, w) in got.iter().zip(want.iter()) {
|
||||
match (g, w) {
|
||||
(None, None) => {}
|
||||
(Some(a), Some(b)) => assert_relative_eq!(*a, *b, epsilon = 1e-9),
|
||||
_ => panic!("warmup mismatch"),
|
||||
for (i, (g, w)) in got.iter().zip(want.iter()).enumerate() {
|
||||
// Same warmup — emission shape must agree at every index.
|
||||
assert_eq!(g.is_some(), w.is_some(), "warmup mismatch at index {i}");
|
||||
if let (Some(a), Some(b)) = (g, w) {
|
||||
assert_relative_eq!(*a, *b, epsilon = 1e-9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user