Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added tests/__init__.py
Empty file.
23 changes: 23 additions & 0 deletions tests/test_ch13_fitness.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import statsmodels.formula.api as smf
from scripts import sim_fitness_2x2 as sim

SEED = 2025

def test_fitness_mixed_model_signals():
subjects, long_df = sim.simulate(n_per_group=5, seed=SEED)

# Mixed model with random intercept for id, categorical time/group + covariates
md = smf.mixedlm(
"strength ~ C(time) * C(group) + age + sex + bmi",
long_df,
groups=long_df["id"],
)
res = md.fit(reml=True)

# main pre->post should be positive and clearly significant
assert res.params["C(time)[T.post]"] > 5
assert res.pvalues["C(time)[T.post]"] < 1e-6

# interaction should be positive (ProgramB a bit more improvement); allow modest p
assert res.params["C(time)[T.post]:C(group)[T.ProgramB]"] > 0
assert res.pvalues["C(time)[T.post]:C(group)[T.ProgramB]"] < 0.2
35 changes: 35 additions & 0 deletions tests/test_ch13_stroop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import numpy as np
import pandas as pd
from scipy import stats
import statsmodels.formula.api as smf

from scripts import sim_stroop

SEED = 2025

def test_stroop_effect_and_mixed_model():
subjects, trials = sim_stroop.simulate(n_subjects=6, n_trials=10, seed=SEED)

# subject-level means by condition (ms)
means = (
trials[trials["correct"]]
.query("rt_ms.between(200, 2000)")
.groupby(["subject", "condition"], as_index=False)["rt_ms"]
.mean()
.pivot(index="subject", columns="condition", values="rt_ms")
.dropna()
)
diff = (means["incongruent"] - means["congruent"])
# expect a solid Stroop effect around ~100ms on this seed; allow wide but positive range
assert diff.mean() > 60 and diff.mean() < 140

# mixed model on log RT with random intercept for subject
df = trials[trials["correct"] & trials["rt_ms"].between(200, 2000)].copy()
df["log_rt"] = np.log(df["rt_ms"])
# Use categorical for condition
md = smf.mixedlm("log_rt ~ C(condition)", df, groups=df["subject"])
res = md.fit(reml=False)
coef = res.params.get("C(condition)[T.incongruent]")
pval = res.pvalues.get("C(condition)[T.incongruent]")
assert 0.12 < coef < 0.22
assert pval < 1e-6
Loading