Skip to content

Commit 6c49b1c

Browse files
committed
Basic toolchain.py unit tests
First simple set of tests for toolchain.py Also refactors `Context.prepare_build_environment()` slightly. Splits concerns to improve readability and ease unit testing.
1 parent f6f6f19 commit 6c49b1c

File tree

2 files changed

+76
-14
lines changed

2 files changed

+76
-14
lines changed

pythonforandroid/build.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,28 @@
2727
RECOMMENDED_NDK_API, RECOMMENDED_TARGET_API)
2828

2929

30+
def get_targets(sdk_dir):
31+
if exists(join(sdk_dir, 'tools', 'bin', 'avdmanager')):
32+
avdmanager = sh.Command(join(sdk_dir, 'tools', 'bin', 'avdmanager'))
33+
targets = avdmanager('list', 'target').stdout.decode('utf-8').split('\n')
34+
elif exists(join(sdk_dir, 'tools', 'android')):
35+
android = sh.Command(join(sdk_dir, 'tools', 'android'))
36+
targets = android('list').stdout.decode('utf-8').split('\n')
37+
else:
38+
raise BuildInterruptingException(
39+
'Could not find `android` or `sdkmanager` binaries in Android SDK',
40+
instructions='Make sure the path to the Android SDK is correct')
41+
return targets
42+
43+
44+
def get_available_apis(sdk_dir):
45+
targets = get_targets(sdk_dir)
46+
apis = [s for s in targets if re.match(r'^ *API level: ', s)]
47+
apis = [re.findall(r'[0-9]+', s) for s in apis]
48+
apis = [int(s[0]) for s in apis if s]
49+
return apis
50+
51+
3052
class Context(object):
3153
'''A build context. If anything will be built, an instance this class
3254
will be instantiated and used to hold all the build state.'''
@@ -238,20 +260,7 @@ def prepare_build_environment(self,
238260
self.android_api = android_api
239261

240262
check_target_api(android_api, self.archs[0].arch)
241-
242-
if exists(join(sdk_dir, 'tools', 'bin', 'avdmanager')):
243-
avdmanager = sh.Command(join(sdk_dir, 'tools', 'bin', 'avdmanager'))
244-
targets = avdmanager('list', 'target').stdout.decode('utf-8').split('\n')
245-
elif exists(join(sdk_dir, 'tools', 'android')):
246-
android = sh.Command(join(sdk_dir, 'tools', 'android'))
247-
targets = android('list').stdout.decode('utf-8').split('\n')
248-
else:
249-
raise BuildInterruptingException(
250-
'Could not find `android` or `sdkmanager` binaries in Android SDK',
251-
instructions='Make sure the path to the Android SDK is correct')
252-
apis = [s for s in targets if re.match(r'^ *API level: ', s)]
253-
apis = [re.findall(r'[0-9]+', s) for s in apis]
254-
apis = [int(s[0]) for s in apis if s]
263+
apis = get_available_apis(self.sdk_dir)
255264
info('Available Android APIs are ({})'.format(
256265
', '.join(map(str, apis))))
257266
if android_api in apis:

tests/test_toolchain.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import sys
2+
import pytest
3+
import mock
4+
from pythonforandroid.toolchain import ToolchainCL
5+
from pythonforandroid.util import BuildInterruptingException
6+
7+
8+
class TestToolchainCL:
9+
10+
def test_help(self):
11+
"""
12+
Calling with `--help` should print help and exit 0.
13+
"""
14+
argv = ['toolchain.py', '--help', '--storage-dir=/tmp']
15+
with mock.patch('sys.argv', argv), pytest.raises(SystemExit) as ex_info, \
16+
mock.patch('argparse.ArgumentParser.print_help') as m_print_help:
17+
ToolchainCL()
18+
assert ex_info.value.code == 0
19+
assert m_print_help.call_args_list == [mock.call()]
20+
21+
@pytest.mark.skipif(sys.version_info < (3, 0), reason="requires python3")
22+
def test_unknown(self):
23+
"""
24+
Calling with unknown args should print help and exit 1.
25+
"""
26+
argv = ['toolchain.py', '--unknown']
27+
with mock.patch('sys.argv', argv), pytest.raises(SystemExit) as ex_info, \
28+
mock.patch('argparse.ArgumentParser.print_help') as m_print_help:
29+
ToolchainCL()
30+
assert ex_info.value.code == 1
31+
assert m_print_help.call_args_list == [mock.call()]
32+
33+
def test_create(self):
34+
"""
35+
Basic `create` distribution test.
36+
"""
37+
argv = ['toolchain.py', 'create', '--sdk-dir=/tmp/android-sdk']
38+
with mock.patch('sys.argv', argv), \
39+
mock.patch('pythonforandroid.build.get_available_apis') as m_get_available_apis, \
40+
mock.patch('pythonforandroid.toolchain.build_dist_from_args') as m_build_dist_from_args:
41+
m_get_available_apis.return_value = [27]
42+
ToolchainCL()
43+
assert m_get_available_apis.call_args_list == [mock.call('/tmp/android-sdk')]
44+
assert m_build_dist_from_args.call_count == 1
45+
46+
def test_create_no_sdk_dir(self):
47+
"""
48+
The `--sdk-dir` is mandatory to `create` a distribution.
49+
"""
50+
argv = ['toolchain.py', 'create']
51+
with mock.patch('sys.argv', argv), pytest.raises(BuildInterruptingException) as ex_info:
52+
ToolchainCL()
53+
assert ex_info.value.message == 'Android SDK dir was not specified, exiting.'

0 commit comments

Comments
 (0)