"""Checks for the statistics, using tiny hand-made data with known answers.""" import sys from pathlib import Path import pytest sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) import itemstats # noqa: E402 QUIZ = { "title": "tiny", "items": [ {"id": "I1", "stem": "", "options": {"A": "", "B": ""}, "key": "A"}, {"id": "I2", "stem": "", "options": {"A": "", "B": ""}, "key": "A"}, {"id": "I3", "stem": "", "options": {"A": "", "B": ""}, "key": "B"}, ], } def learners(rows): return [{"learner_id": f"L{n}", "I1": a, "I2": b, "I3": c} for n, (a, b, c) in enumerate(rows)] def test_difficulty_is_share_correct(): stats = itemstats.analyze(QUIZ, learners([("A", "A", "B"), ("A", "B", "A"), ("B", "B", "A"), ("A", "A", "A")])) assert stats.items[0].difficulty == pytest.approx(0.75) assert stats.items[1].difficulty == pytest.approx(0.50) assert stats.items[2].difficulty == pytest.approx(0.25) def test_pearson_known_values(): assert itemstats.pearson([1, 2, 3], [2, 4, 6]) == pytest.approx(1.0) assert itemstats.pearson([1, 2, 3], [3, 2, 1]) == pytest.approx(-1.0) assert itemstats.pearson([1, 1, 1], [1, 2, 3]) is None def test_kr20_perfectly_consistent_test(): # Every learner either gets everything right or everything wrong. matrix = [[1, 1, 1], [1, 1, 1], [0, 0, 0], [0, 0, 0]] assert itemstats.kr20(matrix) == pytest.approx(1.0) def test_miskeyed_item_gets_flagged(): # Strong learners (right on I1 and I2) all pick A on I3, but the key says B. rows = [("A", "A", "A")] * 6 + [("B", "B", "B")] * 6 stats = itemstats.analyze(QUIZ, learners(rows)) flags = " ".join(stats.items[2].flags) assert "negative discrimination" in flags assert "option A attracts stronger learners" in flags def test_easy_item_gets_flagged(): rows = [("A", "A", "B")] * 19 + [("A", "B", "A")] stats = itemstats.analyze(QUIZ, learners(rows)) assert any("very easy" in f for f in stats.items[0].flags)