Skip to content

Commit

Permalink
Basic toolchain.py unit tests
Browse files Browse the repository at this point in the history
First simple set of tests for toolchain.py
Also refactors `Context.prepare_build_environment()` slightly. Splits
concerns to improve readability and ease unit testing.
  • Loading branch information
AndreMiras committed Jul 23, 2019
1 parent f6f6f19 commit f00fa53
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 14 deletions.
37 changes: 23 additions & 14 deletions pythonforandroid/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@
RECOMMENDED_NDK_API, RECOMMENDED_TARGET_API)


def get_targets(sdk_dir):
if exists(join(sdk_dir, 'tools', 'bin', 'avdmanager')):
avdmanager = sh.Command(join(sdk_dir, 'tools', 'bin', 'avdmanager'))
targets = avdmanager('list', 'target').stdout.decode('utf-8').split('\n')
elif exists(join(sdk_dir, 'tools', 'android')):
android = sh.Command(join(sdk_dir, 'tools', 'android'))
targets = android('list').stdout.decode('utf-8').split('\n')
else:
raise BuildInterruptingException(
'Could not find `android` or `sdkmanager` binaries in Android SDK',
instructions='Make sure the path to the Android SDK is correct')
return targets


def get_available_apis(sdk_dir):
targets = get_targets(sdk_dir)
apis = [s for s in targets if re.match(r'^ *API level: ', s)]
apis = [re.findall(r'[0-9]+', s) for s in apis]
apis = [int(s[0]) for s in apis if s]
return apis


class Context(object):
'''A build context. If anything will be built, an instance this class
will be instantiated and used to hold all the build state.'''
Expand Down Expand Up @@ -238,20 +260,7 @@ def prepare_build_environment(self,
self.android_api = android_api

check_target_api(android_api, self.archs[0].arch)

if exists(join(sdk_dir, 'tools', 'bin', 'avdmanager')):
avdmanager = sh.Command(join(sdk_dir, 'tools', 'bin', 'avdmanager'))
targets = avdmanager('list', 'target').stdout.decode('utf-8').split('\n')
elif exists(join(sdk_dir, 'tools', 'android')):
android = sh.Command(join(sdk_dir, 'tools', 'android'))
targets = android('list').stdout.decode('utf-8').split('\n')
else:
raise BuildInterruptingException(
'Could not find `android` or `sdkmanager` binaries in Android SDK',
instructions='Make sure the path to the Android SDK is correct')
apis = [s for s in targets if re.match(r'^ *API level: ', s)]
apis = [re.findall(r'[0-9]+', s) for s in apis]
apis = [int(s[0]) for s in apis if s]
apis = get_available_apis(self.sdk_dir)
info('Available Android APIs are ({})'.format(
', '.join(map(str, apis))))
if android_api in apis:
Expand Down
53 changes: 53 additions & 0 deletions tests/test_toolchain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import sys
import pytest
import mock
from pythonforandroid.toolchain import ToolchainCL
from pythonforandroid.util import BuildInterruptingException


class TestToolchainCL:

def test_help(self):
"""
Calling with `--help` should print help and exit 0.
"""
argv = ['toolchain.py', '--help', '--storage-dir=/tmp']
with mock.patch('sys.argv', argv), pytest.raises(SystemExit) as ex_info, \
mock.patch('argparse.ArgumentParser.print_help') as m_print_help:
ToolchainCL()
assert m_print_help.call_args_list == [mock.call()]
assert ex_info.value.code == 0

@pytest.mark.skipif(sys.version_info < (3, 0), reason="requires python3")
def test_unknown(self):
"""
Calling with unknown args should print help and exit 1.
"""
argv = ['toolchain.py', '--unknown']
with mock.patch('sys.argv', argv), pytest.raises(SystemExit) as ex_info, \
mock.patch('argparse.ArgumentParser.print_help') as m_print_help:
ToolchainCL()
assert m_print_help.call_args_list == [mock.call()]
assert ex_info.value.code == 1

def test_create(self):
"""
Basic `create` distribution test.
"""
argv = ['toolchain.py', 'create', '--sdk-dir=/tmp/android-sdk']
with mock.patch('sys.argv', argv), \
mock.patch('pythonforandroid.build.get_available_apis') as m_get_available_apis, \
mock.patch('pythonforandroid.toolchain.build_dist_from_args') as m_build_dist_from_args:
m_get_available_apis.return_value = [27]
ToolchainCL()
assert m_get_available_apis.call_args_list == [mock.call('/tmp/android-sdk')]
assert m_build_dist_from_args.call_count == 1

def test_create_no_sdk_dir(self):
"""
The `--sdk-dir` is mandatory to `create` a distribution.
"""
argv = ['toolchain.py', 'create']
with mock.patch('sys.argv', argv), pytest.raises(BuildInterruptingException) as ex_info:
ToolchainCL()
assert ex_info.value.message == 'Android SDK dir was not specified, exiting.'

0 comments on commit f00fa53

Please sign in to comment.