File size: 3,441 Bytes
271e6aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import contextlib
import io
import json
import runpy
import shutil
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
TEMPLATE = ROOT / "classroom_data/templates/week21"


class Lesson21TemplateTests(unittest.TestCase):
    def setUp(self):
        self.lesson = runpy.run_path(str(TEMPLATE / "main.py"))
        self.rows = self.lesson["load_rows"](TEMPLATE / "data/students_by_county.csv")

    def run_starter(self, county="新北市", completed=False):
        with tempfile.TemporaryDirectory() as directory:
            project = Path(directory) / "project"
            shutil.copytree(TEMPLATE, project, ignore=shutil.ignore_patterns("__pycache__"))
            source = (project / "main.py").read_text(encoding="utf-8")
            source = source.replace('COUNTY = "新北市"', f'COUNTY = "{county}"')
            if completed:
                source = source.replace("change = None", "change = after - before")
            (project / "main.py").write_text(source, encoding="utf-8")
            result = subprocess.run([sys.executable, "-B", "main.py"], cwd=project,
                                    capture_output=True, text=True, timeout=10)
        self.assertEqual(result.returncode, 0, result.stderr)
        return result.stdout

    def test_lesson_is_enabled_without_changing_existing_workspace(self):
        course = json.loads((ROOT / "classroom_data/course.json").read_text(encoding="utf-8"))
        lessons = {item["id"]: item for item in course["weeks"]}
        self.assertTrue(lessons["week21"]["template"])
        self.assertEqual(lessons["week21"]["workspace_id"], "week19")
        self.assertEqual(lessons["week20"]["workspace_id"], "week19")
        self.assertTrue((TEMPLATE / "REPORT.md").is_file())
        self.assertTrue((TEMPLATE / "DATA_SOURCE.md").is_file())

    def test_starter_runs_before_student_fills_in_the_calculation(self):
        output = self.run_starter()
        self.assertIn("讀入 242 列資料", output)
        self.assertIn("201,970 人", output)
        self.assertIn("194,670 人", output)
        self.assertIn("請完成 change", output)
        self.assertNotIn("增減人數:", output)

    def test_completed_examples_match_the_lesson_slides(self):
        self.assertIn("增減人數:-7,300 人", self.run_starter(completed=True))
        self.assertIn("增減人數:+4,060 人", self.run_starter("臺中市", completed=True))

    def test_rankings_use_the_supplied_dataset(self):
        results = self.lesson["count_by_county"](self.rows, "114", "國小[人]")
        self.assertEqual(results[:3], [("新北市", 194670), ("臺中市", 161332), ("桃園市", 132964)])

    def test_unknown_counts_are_not_zero_and_zero_chart_does_not_divide(self):
        for value in ("", "-", "未知", None):
            self.assertIsNone(self.lesson["parse_count"](value))
        self.assertEqual(self.lesson["parse_count"]("0"), 0)
        self.assertEqual(self.lesson["parse_count"](" 1,234 "), 1234)
        self.assertIsNone(self.lesson["get_count"](self.rows, "999", "新北市", "國小[人]"))
        with contextlib.redirect_stdout(io.StringIO()):
            self.lesson["print_text_chart"]([("甲", 0), ("乙", 0)])
        self.assertIn("找不到完整的兩筆人數", self.run_starter("不存在的縣市", completed=True))


if __name__ == "__main__":
    unittest.main()