casebench
test cases straight onto the board.
git clone https://owenrusk.dev/casebench.git
commit 0bbf945299c6283c0b5d2187f3b63d4eab8a62dd parent 578e4ea04fdffc20cf4401bad7aa09da682ac011 author Owen Rusk <owen@papermothgames.com> date 2025-07-17 13:18:52 -0500
tests: lock, rest and unlock
| tests/test_lock.py | +105 | -0 |
diff --git a/tests/test_lock.py b/tests/test_lock.py
new file mode 100644
index 0000000..f316d13
--- /dev/null
+++ b/tests/test_lock.py
@@ -0,0 +1,105 @@
+import unittest
+from datetime import UTC, datetime, timedelta
+
+from casebench import lock
+from casebench.memstore import MemStore
+
+from .helpers import UMBRELLA, run
+
+T0 = datetime(2025, 7, 17, 14, 0, tzinfo=UTC)
+
+
+class AttemptTest(unittest.TestCase):
+ def setUp(self):
+ self.lock = lock.make(["Tuesday", "114"], lock.Rest(3, 60))
+
+ def test_opens_on_both_lines(self):
+ result, after = lock.attempt(self.lock, ["tuesday", " 114 "], T0)
+ self.assertEqual(result, "open")
+ self.assertEqual(after.opened_at, T0)
+
+ def test_one_line_right_is_still_wrong(self):
+ result, after = lock.attempt(self.lock, ["tuesday", "115"], T0)
+ self.assertEqual(result, "wrong")
+ self.assertEqual(after.wrong, 1)
+
+ def test_wrong_number_of_lines(self):
+ result, _ = lock.attempt(self.lock, ["tuesday"], T0)
+ self.assertEqual(result, "wrong")
+
+ def test_rests_after_three_wrong(self):
+ state = self.lock
+ for _ in range(3):
+ result, state = lock.attempt(state, ["no", "no"], T0)
+ self.assertEqual(result, "wrong")
+ self.assertEqual(state.resting_until, T0 + timedelta(minutes=60))
+
+ def test_takes_nothing_while_resting(self):
+ state = self.lock
+ for _ in range(3):
+ _, state = lock.attempt(state, ["no", "no"], T0)
+ result, held = lock.attempt(state, ["tuesday", "114"], T0 + timedelta(minutes=59))
+ self.assertEqual(result, "resting")
+ self.assertIs(held, state)
+ result, _ = lock.attempt(state, ["tuesday", "114"], T0 + timedelta(minutes=60))
+ self.assertEqual(result, "open")
+
+ def test_count_starts_over_after_a_rest(self):
+ state = self.lock
+ for _ in range(3):
+ _, state = lock.attempt(state, ["no", "no"], T0)
+ result, state = lock.attempt(state, ["no", "no"], T0 + timedelta(minutes=61))
+ self.assertEqual(result, "wrong")
+ self.assertEqual(state.wrong, 1)
+
+ def test_right_answer_clears_the_count(self):
+ _, state = lock.attempt(self.lock, ["no", "no"], T0)
+ _, state = lock.attempt(state, ["tuesday", "114"], T0)
+ self.assertEqual(state.wrong, 0)
+
+ def test_answers_are_not_stored(self):
+ self.assertNotIn("tuesday", repr(self.lock).casefold())
+
+ def test_parse_rest(self):
+ self.assertEqual(lock.parse_rest("3/60"), lock.Rest(3, 60))
+ for bad in ("3", "0/60", "a/b", "3/-1"):
+ with self.assertRaises(ValueError):
+ lock.parse_rest(bad)
+
+
+class LockCommandTest(unittest.TestCase):
+ def setUp(self):
+ self.store = MemStore(("owen",))
+ self.owen = self.store.player("owen")
+ run(self.store, "put", str(UMBRELLA), "--player", "owen")
+
+ def test_lock_and_unlock(self):
+ code, _, _ = run(
+ self.store, "lock", "test-lost-umbrella", "--answer", "tuesday", "--rest", "5/10", "--player", "owen"
+ )
+ self.assertEqual(code, 0)
+ held = self.store.get_lock(self.owen, "test-lost-umbrella")
+ self.assertEqual((held.text, held.lines, held.rest), ("locked.", 1, lock.Rest(5, 10)))
+ code, out, _ = run(self.store, "unlock", "test-lost-umbrella", "--player", "owen")
+ self.assertEqual((code, out), (0, "owen: unlocked test-lost-umbrella\n"))
+ self.assertIsNone(self.store.get_lock(self.owen, "test-lost-umbrella"))
+
+ def test_unlock_when_not_locked(self):
+ code, _, err = run(self.store, "unlock", "test-lost-umbrella", "--player", "owen")
+ self.assertEqual(code, 1)
+ self.assertIn("isn't locked", err)
+
+ def test_locks_a_runtime_case(self):
+ self.store.runtime_case(self.owen, "case-x", "A real case")
+ code, _, _ = run(self.store, "lock", "case-x", "--answer", "a", "--player", "owen")
+ self.assertEqual(code, 0)
+ self.assertIsNotNone(self.store.get_lock(self.owen, "case-x"))
+
+ def test_bad_rest(self):
+ code, _, err = run(self.store, "lock", "test-lost-umbrella", "--answer", "a", "--rest", "three", "--player", "owen")
+ self.assertEqual(code, 1)
+ self.assertIn("tries/minutes", err)
+
+
+if __name__ == "__main__":
+ unittest.main()