forked from TaskBeacon/psyflow
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_SubInfo.py
More file actions
67 lines (51 loc) · 1.81 KB
/
test_SubInfo.py
File metadata and controls
67 lines (51 loc) · 1.81 KB
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
"""Tests for psyflow.SubInfo."""
import unittest
from unittest.mock import MagicMock, patch
try:
from psychopy import gui # noqa: F401
_HAS_PSYCHOPY = True
except ImportError:
_HAS_PSYCHOPY = False
if _HAS_PSYCHOPY:
import psyflow.SubInfo as _subinfo_mod
from psyflow.SubInfo import SubInfo
_gui = _subinfo_mod.gui
def _make_subinfo(**field_map_overrides):
"""Build a SubInfo without calling __init__."""
info = SubInfo.__new__(SubInfo)
info.fields = [
{"name": "subject_id", "type": "int",
"constraints": {"min": 101, "max": 999, "digits": 3}}
]
info.field_map = {
"Participant Information": "Info",
"registration_failed": "Failed",
"invalid_input": "Bad: {field}",
}
info.field_map.update(field_map_overrides)
info.subject_data = None
return info
@unittest.skipUnless(_HAS_PSYCHOPY, "requires psychopy")
class TestCollect(unittest.TestCase):
"""SubInfo.collect() control-flow edge cases."""
def test_cancel_returns_none(self):
info = _make_subinfo()
mock_dlg = MagicMock()
mock_dlg.show.return_value = None
with patch.object(_gui, "Dlg", return_value=mock_dlg):
result = info.collect(exit_on_cancel=False)
self.assertIsNone(result)
@unittest.skipUnless(_HAS_PSYCHOPY, "requires psychopy")
class TestValidate(unittest.TestCase):
"""SubInfo.validate() error handling."""
def test_keyboard_interrupt_propagates(self):
info = _make_subinfo()
class ExplodingStr:
def __int__(self):
raise KeyboardInterrupt("simulated Ctrl+C")
def __str__(self):
return "boom"
with self.assertRaises(KeyboardInterrupt):
info.validate([ExplodingStr()])
if __name__ == "__main__":
unittest.main()