forked from kivy/python-for-android
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_checkdependencies.py
More file actions
195 lines (157 loc) · 7.67 KB
/
test_checkdependencies.py
File metadata and controls
195 lines (157 loc) · 7.67 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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
import sys
from unittest import mock
from pythonforandroid import checkdependencies
class TestCheckPythonDependencies:
"""Test check_python_dependencies function."""
@mock.patch('pythonforandroid.checkdependencies.import_module')
def test_all_modules_present(self, mock_import):
"""Test that check_python_dependencies completes when all modules are present."""
# Mock all required modules
mock_colorama = mock.Mock()
mock_colorama.__version__ = '0.4.0'
mock_sh = mock.Mock()
mock_sh.__version__ = '1.12'
mock_appdirs = mock.Mock()
mock_jinja2 = mock.Mock()
def import_side_effect(name):
if name == 'colorama':
return mock_colorama
elif name == 'sh':
return mock_sh
elif name == 'appdirs':
return mock_appdirs
elif name == 'jinja2':
return mock_jinja2
raise ImportError(f"No module named '{name}'")
mock_import.side_effect = import_side_effect
with mock.patch.object(sys, 'modules', {
'colorama': mock_colorama,
'sh': mock_sh,
'appdirs': mock_appdirs,
'jinja2': mock_jinja2
}):
checkdependencies.check_python_dependencies()
@mock.patch('builtins.exit')
@mock.patch('builtins.print')
@mock.patch('pythonforandroid.checkdependencies.import_module')
def test_missing_module_without_version(self, mock_import, mock_print, mock_exit):
"""Test error message when module without version requirement is missing."""
modules_dict = {}
def import_side_effect(name):
if name == 'appdirs':
raise ImportError(f"No module named '{name}'")
mock_mod = mock.Mock()
mock_mod.__version__ = '1.0'
modules_dict[name] = mock_mod
return mock_mod
mock_import.side_effect = import_side_effect
with mock.patch.object(sys, 'modules', modules_dict):
checkdependencies.check_python_dependencies()
# Verify error message was printed
error_calls = [str(call) for call in mock_print.call_args_list]
assert any('appdirs' in call and 'ERROR' in call for call in error_calls)
mock_exit.assert_called_once_with(1)
@mock.patch('builtins.exit')
@mock.patch('builtins.print')
@mock.patch('pythonforandroid.checkdependencies.import_module')
def test_missing_module_with_version(self, mock_import, mock_print, mock_exit):
"""Test error message when module with version requirement is missing."""
modules_dict = {}
def import_side_effect(name):
if name == 'colorama':
raise ImportError(f"No module named '{name}'")
mock_mod = mock.Mock()
mock_mod.__version__ = '1.0'
modules_dict[name] = mock_mod
return mock_mod
mock_import.side_effect = import_side_effect
with mock.patch.object(sys, 'modules', modules_dict):
checkdependencies.check_python_dependencies()
# Verify error message includes version requirement
error_calls = [str(call) for call in mock_print.call_args_list]
assert any('colorama' in call and '0.3.3' in call for call in error_calls)
mock_exit.assert_called_once_with(1)
@mock.patch('builtins.exit')
@mock.patch('builtins.print')
@mock.patch('pythonforandroid.checkdependencies.import_module')
def test_module_version_too_old(self, mock_import, mock_print, mock_exit):
"""Test error when module version is too old."""
mock_colorama = mock.Mock()
mock_colorama.__version__ = '0.2.0' # Too old, needs 0.3.3
modules_dict = {'colorama': mock_colorama}
def import_side_effect(name):
if name == 'colorama':
return mock_colorama
mock_mod = mock.Mock()
mock_mod.__version__ = '1.0'
modules_dict[name] = mock_mod
return mock_mod
mock_import.side_effect = import_side_effect
with mock.patch.object(sys, 'modules', modules_dict):
checkdependencies.check_python_dependencies()
# Verify error message about version
error_calls = [str(call) for call in mock_print.call_args_list]
assert any('version' in call.lower() and 'colorama' in call for call in error_calls)
mock_exit.assert_called_once_with(1)
@mock.patch('pythonforandroid.checkdependencies.import_module')
def test_module_version_acceptable(self, mock_import):
"""Test that acceptable versions pass."""
mock_colorama = mock.Mock()
mock_colorama.__version__ = '0.4.0' # Newer than 0.3.3
mock_sh = mock.Mock()
mock_sh.__version__ = '1.12' # Newer than 1.10
def import_side_effect(name):
if name == 'colorama':
return mock_colorama
elif name == 'sh':
return mock_sh
mock_mod = mock.Mock()
return mock_mod
mock_import.side_effect = import_side_effect
with mock.patch.object(sys, 'modules', {
'colorama': mock_colorama,
'sh': mock_sh
}):
# Should complete without error
checkdependencies.check_python_dependencies()
@mock.patch('pythonforandroid.checkdependencies.import_module')
def test_module_without_version_attribute(self, mock_import):
"""Test handling of modules that don't have __version__."""
mock_colorama = mock.Mock(spec=[]) # No __version__ attribute
modules_dict = {'colorama': mock_colorama}
def import_side_effect(name):
if name == 'colorama':
return mock_colorama
mock_mod = mock.Mock()
modules_dict[name] = mock_mod
return mock_mod
mock_import.side_effect = import_side_effect
with mock.patch.object(sys, 'modules', modules_dict):
# Should complete without error (version check is skipped)
checkdependencies.check_python_dependencies()
class TestCheck:
"""Test the main check() function."""
@mock.patch('pythonforandroid.checkdependencies.check_python_dependencies')
@mock.patch('pythonforandroid.checkdependencies.check_and_install_default_prerequisites')
def test_check_with_skip_prerequisites(self, mock_prereqs, mock_python_deps):
"""Test check() skips prerequisites when SKIP_PREREQUISITES_CHECK=1."""
with mock.patch.dict('os.environ', {'SKIP_PREREQUISITES_CHECK': '1'}):
checkdependencies.check()
mock_prereqs.assert_not_called()
mock_python_deps.assert_called_once()
@mock.patch('pythonforandroid.checkdependencies.check_python_dependencies')
@mock.patch('pythonforandroid.checkdependencies.check_and_install_default_prerequisites')
def test_check_without_skip(self, mock_prereqs, mock_python_deps):
"""Test check() runs prerequisites when SKIP_PREREQUISITES_CHECK is not set."""
with mock.patch.dict('os.environ', {}, clear=True):
checkdependencies.check()
mock_prereqs.assert_called_once()
mock_python_deps.assert_called_once()
@mock.patch('pythonforandroid.checkdependencies.check_python_dependencies')
@mock.patch('pythonforandroid.checkdependencies.check_and_install_default_prerequisites')
def test_check_with_skip_set_to_zero(self, mock_prereqs, mock_python_deps):
"""Test check() runs prerequisites when SKIP_PREREQUISITES_CHECK=0."""
with mock.patch.dict('os.environ', {'SKIP_PREREQUISITES_CHECK': '0'}):
checkdependencies.check()
mock_prereqs.assert_called_once()
mock_python_deps.assert_called_once()