Files
k-mood/crates/domain/tests/correlation/adjustment_test.rs
Gabriel Kaszewski 23d052278a
All checks were successful
CI / ci (push) Successful in 19m38s
changes
2026-08-26 20:58:14 +02:00

181 lines
5.0 KiB
Rust

use domain::correlation::{Adjustment, PValue};
fn p_values(values: &[f64]) -> Vec<PValue> {
values
.iter()
.map(|value| PValue::new(*value).unwrap())
.collect()
}
#[test]
fn the_step_up_procedure_keeps_everything_below_the_largest_passing_rank() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
let held = adjustment.holds_up(&p_values(&[0.001, 0.008, 0.039, 0.041, 0.42]));
assert_eq!(held, [true, true, true, true, false]);
}
#[test]
fn a_result_below_its_own_threshold_is_carried_by_a_stronger_one() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
let held = adjustment.holds_up(&p_values(&[0.001, 0.079]));
assert_eq!(
held,
[true, true],
"0.079 exceeds rank 1's threshold but rank 2 passes, so both hold"
);
}
#[test]
fn order_of_the_set_does_not_change_who_holds_up() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
let held = adjustment.holds_up(&p_values(&[0.42, 0.041, 0.001, 0.039, 0.008]));
assert_eq!(held, [false, true, true, true, true]);
}
#[test]
fn nothing_holds_up_when_nothing_is_small_enough() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
let held = adjustment.holds_up(&p_values(&[0.4, 0.5, 0.6]));
assert_eq!(held, [false, false, false]);
}
#[test]
fn a_larger_set_makes_each_result_work_harder() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
let alone = adjustment.holds_up(&p_values(&[0.04]));
let among_ten = adjustment.holds_up(&p_values(&[
0.04, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
]));
assert_eq!(alone, [true]);
assert!(!among_ten[0], "0.04 needs to beat 0.01 once ten are tested");
}
#[test]
fn the_threshold_is_whatever_it_is_configured_to_be() {
let strict = Adjustment::controlling_false_discovery_at(0.01);
let loose = Adjustment::controlling_false_discovery_at(0.20);
let borderline = p_values(&[0.03, 0.5]);
assert_eq!(strict.holds_up(&borderline), [false, false]);
assert_eq!(loose.holds_up(&borderline), [true, false]);
}
#[test]
fn an_empty_set_holds_nothing_up_and_does_not_panic() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
assert!(adjustment.holds_up(&[]).is_empty());
}
use domain::correlation::{CorrelationStrategy, Family, Tested};
fn tested(family: Family, strategy: CorrelationStrategy, p: f64) -> Tested {
Tested {
family,
strategy,
p_value: PValue::new(p).unwrap(),
}
}
fn measurement(p: f64) -> Tested {
tested(Family::Measurements, CorrelationStrategy::Spearman, p)
}
#[test]
fn a_result_is_corrected_against_the_others_in_its_own_group() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
let held = adjustment.holds_up_across(&[measurement(0.04), measurement(0.5)]);
assert_eq!(held, [true, false]);
}
#[test]
fn how_many_activities_are_kept_does_not_change_a_measurement_result() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
let mut entries = vec![measurement(0.04), measurement(0.5)];
for _ in 0..20 {
entries.push(tested(
Family::Activities,
CorrelationStrategy::MeanDifference,
0.5,
));
}
let held = adjustment.holds_up_across(&entries);
assert!(
held[0],
"a measurement must not be corrected against activities"
);
}
#[test]
fn measuring_the_same_thing_several_ways_is_not_several_hypotheses() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
let mut entries = vec![measurement(0.04), measurement(0.5)];
for other in [CorrelationStrategy::Pearson, CorrelationStrategy::Kendall] {
for _ in 0..10 {
entries.push(tested(Family::Measurements, other, 0.5));
}
}
let held = adjustment.holds_up_across(&entries);
assert!(
held[0],
"correcting across strategies would penalise measuring carefully"
);
}
#[test]
fn more_of_the_same_question_does_make_a_result_work_harder() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
let mut entries = vec![measurement(0.04)];
for _ in 0..20 {
entries.push(measurement(0.5));
}
let held = adjustment.holds_up_across(&entries);
assert!(
!held[0],
"twenty more measurements under the same strategy is twenty more comparisons"
);
}
#[test]
fn two_families_are_corrected_apart_even_under_one_strategy() {
let adjustment = Adjustment::controlling_false_discovery_at(0.10);
let mut entries = vec![measurement(0.04), measurement(0.5)];
for _ in 0..20 {
entries.push(tested(
Family::Activities,
CorrelationStrategy::Spearman,
0.5,
));
}
let held = adjustment.holds_up_across(&entries);
assert!(
held[0],
"a Family is a question: activities never dilute a measurement, whichever strategy scored them"
);
}