Merge pull request #1168 from AndreMiras/feature/test_ios
✅ Unit test ios target
This commit is contained in:
commit
3f851ec924
4 changed files with 228 additions and 138 deletions
|
@ -3,9 +3,6 @@ iOS target, based on kivy-ios project
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
if sys.platform != 'darwin':
|
|
||||||
raise NotImplementedError('Windows platform not yet working for Android')
|
|
||||||
|
|
||||||
import plistlib
|
import plistlib
|
||||||
from buildozer import BuildozerCommandException
|
from buildozer import BuildozerCommandException
|
||||||
from buildozer.target import Target, no_config
|
from buildozer.target import Target, no_config
|
||||||
|
@ -64,6 +61,8 @@ class TargetIos(Target):
|
||||||
targetname = "ios"
|
targetname = "ios"
|
||||||
|
|
||||||
def check_requirements(self):
|
def check_requirements(self):
|
||||||
|
if sys.platform != "darwin":
|
||||||
|
raise NotImplementedError("Only macOS is supported for iOS target")
|
||||||
checkbin = self.buildozer.checkbin
|
checkbin = self.buildozer.checkbin
|
||||||
cmd = self.buildozer.cmd
|
cmd = self.buildozer.cmd
|
||||||
executable = sys.executable or 'python'
|
executable = sys.executable or 'python'
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import tempfile
|
import tempfile
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import buildozer as buildozer_module
|
|
||||||
from buildozer import Buildozer
|
|
||||||
from buildozer.targets.android import TargetAndroid
|
from buildozer.targets.android import TargetAndroid
|
||||||
|
from tests.targets.utils import (
|
||||||
|
init_buildozer,
|
||||||
def patch_buildozer(method):
|
patch_buildozer,
|
||||||
return mock.patch("buildozer.Buildozer.{method}".format(method=method))
|
patch_buildozer_checkbin,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def patch_buildozer_cmd():
|
def patch_buildozer_cmd():
|
||||||
|
@ -38,10 +36,6 @@ def patch_os_isfile():
|
||||||
return mock.patch("os.path.isfile")
|
return mock.patch("os.path.isfile")
|
||||||
|
|
||||||
|
|
||||||
def patch_buildozer_checkbin():
|
|
||||||
return patch_buildozer("checkbin")
|
|
||||||
|
|
||||||
|
|
||||||
def patch_target_android(method):
|
def patch_target_android(method):
|
||||||
return mock.patch(
|
return mock.patch(
|
||||||
"buildozer.targets.android.TargetAndroid.{method}".format(method=method)
|
"buildozer.targets.android.TargetAndroid.{method}".format(method=method)
|
||||||
|
@ -52,11 +46,51 @@ def patch_platform(platform):
|
||||||
return mock.patch("buildozer.targets.android.platform", platform)
|
return mock.patch("buildozer.targets.android.platform", platform)
|
||||||
|
|
||||||
|
|
||||||
class TestTargetAndroid:
|
def init_target(temp_dir, options=None):
|
||||||
|
buildozer = init_buildozer(temp_dir, "android", options)
|
||||||
|
return TargetAndroid(buildozer)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def default_specfile_path():
|
def call_build_package(target_android):
|
||||||
return os.path.join(os.path.dirname(buildozer_module.__file__), "default.spec")
|
"""
|
||||||
|
Call the build_package() method of the tested TargetAndroid instance,
|
||||||
|
patching the functions that would otherwise produce side-effects.
|
||||||
|
|
||||||
|
Return the mocked execute_build_package() method of the TargetAndroid
|
||||||
|
instance so that tests can easily check which command-line arguments
|
||||||
|
would be passed on to python-for-android's toolchain.
|
||||||
|
"""
|
||||||
|
buildozer = target_android.buildozer
|
||||||
|
expected_dist_dir = (
|
||||||
|
'{buildozer_dir}/android/platform/build-armeabi-v7a/dists/myapp__armeabi-v7a'.format(
|
||||||
|
buildozer_dir=buildozer.buildozer_dir)
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch_target_android('_update_libraries_references') as m_update_libraries_references, \
|
||||||
|
patch_target_android('_generate_whitelist') as m_generate_whitelist, \
|
||||||
|
mock.patch('buildozer.targets.android.TargetAndroid.execute_build_package') as m_execute_build_package, \
|
||||||
|
mock.patch('buildozer.targets.android.copyfile') as m_copyfile, \
|
||||||
|
mock.patch('buildozer.targets.android.os.listdir') as m_listdir:
|
||||||
|
m_listdir.return_value = ['30.0.0-rc2']
|
||||||
|
target_android.build_package()
|
||||||
|
|
||||||
|
assert m_listdir.call_count == 1
|
||||||
|
assert m_update_libraries_references.call_args_list == [
|
||||||
|
mock.call(expected_dist_dir)
|
||||||
|
]
|
||||||
|
assert m_generate_whitelist.call_args_list == [mock.call(expected_dist_dir)]
|
||||||
|
assert m_copyfile.call_args_list == [
|
||||||
|
mock.call(
|
||||||
|
'{expected_dist_dir}/bin/MyApplication-0.1-debug.apk'.format(
|
||||||
|
expected_dist_dir=expected_dist_dir
|
||||||
|
),
|
||||||
|
'{bin_dir}/myapp-0.1-armeabi-v7a-debug.apk'.format(bin_dir=buildozer.bin_dir),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
return m_execute_build_package
|
||||||
|
|
||||||
|
|
||||||
|
class TestTargetAndroid:
|
||||||
|
|
||||||
def setup_method(self):
|
def setup_method(self):
|
||||||
"""
|
"""
|
||||||
|
@ -71,108 +105,28 @@ class TestTargetAndroid:
|
||||||
"""
|
"""
|
||||||
self.temp_dir.cleanup()
|
self.temp_dir.cleanup()
|
||||||
|
|
||||||
def init_target(self, options=None):
|
|
||||||
"""
|
|
||||||
Create a buildozer.spec file in the temporary directory and init the
|
|
||||||
Buildozer and TargetAndroid instances.
|
|
||||||
|
|
||||||
The optional argument can be used to overwrite the config options in
|
|
||||||
the buildozer.spec file, e.g.:
|
|
||||||
|
|
||||||
self.init_target({'title': 'Test App'})
|
|
||||||
|
|
||||||
will replace line 4 of the default spec file.
|
|
||||||
"""
|
|
||||||
if options is None:
|
|
||||||
options = {}
|
|
||||||
|
|
||||||
spec_path = os.path.join(self.temp_dir.name, 'buildozer.spec')
|
|
||||||
|
|
||||||
with open(TestTargetAndroid.default_specfile_path()) as f:
|
|
||||||
default_spec = f.readlines()
|
|
||||||
|
|
||||||
spec = []
|
|
||||||
for line in default_spec:
|
|
||||||
if line.strip():
|
|
||||||
match = re.search(r'[#\s]?([a-z_\.]+)', line)
|
|
||||||
key = match and match.group(1)
|
|
||||||
if key in options:
|
|
||||||
line = '{} = {}\n'.format(key, options[key])
|
|
||||||
|
|
||||||
spec.append(line)
|
|
||||||
|
|
||||||
with open(spec_path, 'w') as f:
|
|
||||||
f.writelines(spec)
|
|
||||||
|
|
||||||
self.buildozer = Buildozer(filename=spec_path, target='android')
|
|
||||||
self.target_android = TargetAndroid(self.buildozer)
|
|
||||||
|
|
||||||
def call_build_package(self):
|
|
||||||
"""
|
|
||||||
Call the build_package() method of the tested TargetAndroid instance,
|
|
||||||
patching the functions that would otherwise produce side-effects.
|
|
||||||
|
|
||||||
Return the mocked execute_build_package() method of the TargetAndroid
|
|
||||||
instance so that tests can easily check which command-line arguments
|
|
||||||
would be passed on to python-for-android's toolchain.
|
|
||||||
"""
|
|
||||||
expected_dist_dir = (
|
|
||||||
'{buildozer_dir}/android/platform/build-armeabi-v7a/dists/myapp__armeabi-v7a'.format(
|
|
||||||
buildozer_dir=self.buildozer.buildozer_dir)
|
|
||||||
)
|
|
||||||
|
|
||||||
with patch_target_android(
|
|
||||||
'_update_libraries_references'
|
|
||||||
) as m_update_libraries_references, patch_target_android(
|
|
||||||
'_generate_whitelist'
|
|
||||||
) as m_generate_whitelist, mock.patch(
|
|
||||||
'buildozer.targets.android.TargetAndroid.execute_build_package'
|
|
||||||
) as m_execute_build_package, mock.patch(
|
|
||||||
'buildozer.targets.android.copyfile'
|
|
||||||
) as m_copyfile, mock.patch(
|
|
||||||
'buildozer.targets.android.os.listdir'
|
|
||||||
) as m_listdir:
|
|
||||||
m_listdir.return_value = ['30.0.0-rc2']
|
|
||||||
self.target_android.build_package()
|
|
||||||
|
|
||||||
assert m_listdir.call_count == 1
|
|
||||||
assert m_update_libraries_references.call_args_list == [
|
|
||||||
mock.call(expected_dist_dir)
|
|
||||||
]
|
|
||||||
assert m_generate_whitelist.call_args_list == [mock.call(expected_dist_dir)]
|
|
||||||
assert m_copyfile.call_args_list == [
|
|
||||||
mock.call(
|
|
||||||
'{expected_dist_dir}/bin/MyApplication-0.1-debug.apk'.format(
|
|
||||||
expected_dist_dir=expected_dist_dir
|
|
||||||
),
|
|
||||||
'{bin_dir}/myapp-0.1-armeabi-v7a-debug.apk'.format(bin_dir=self.buildozer.bin_dir),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
return m_execute_build_package
|
|
||||||
|
|
||||||
def test_init(self):
|
def test_init(self):
|
||||||
"""Tests init defaults."""
|
"""Tests init defaults."""
|
||||||
self.init_target()
|
target_android = init_target(self.temp_dir)
|
||||||
assert self.target_android._arch == "armeabi-v7a"
|
buildozer = target_android.buildozer
|
||||||
assert self.target_android._build_dir.endswith(
|
assert target_android._arch == "armeabi-v7a"
|
||||||
|
assert target_android._build_dir.endswith(
|
||||||
".buildozer/android/platform/build-armeabi-v7a"
|
".buildozer/android/platform/build-armeabi-v7a"
|
||||||
)
|
)
|
||||||
assert self.target_android._p4a_bootstrap == "sdl2"
|
assert target_android._p4a_bootstrap == "sdl2"
|
||||||
assert self.target_android._p4a_cmd.endswith(
|
assert target_android._p4a_cmd.endswith(
|
||||||
"python -m pythonforandroid.toolchain "
|
"python -m pythonforandroid.toolchain "
|
||||||
)
|
)
|
||||||
assert self.target_android.build_mode == "debug"
|
assert target_android.build_mode == "debug"
|
||||||
assert self.target_android.buildozer == self.buildozer
|
|
||||||
assert (
|
assert (
|
||||||
self.target_android.extra_p4a_args == (
|
target_android.extra_p4a_args == (
|
||||||
' --color=always'
|
' --color=always'
|
||||||
' --storage-dir="{buildozer_dir}/android/platform/build-armeabi-v7a" --ndk-api=21'.format(
|
' --storage-dir="{buildozer_dir}/android/platform/build-armeabi-v7a" --ndk-api=21'.format(
|
||||||
buildozer_dir=self.buildozer.buildozer_dir)
|
buildozer_dir=buildozer.buildozer_dir)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert self.target_android.p4a_apk_cmd == "apk --debug --bootstrap=sdl2"
|
assert target_android.p4a_apk_cmd == "apk --debug --bootstrap=sdl2"
|
||||||
assert self.target_android.platform_update is False
|
assert target_android.platform_update is False
|
||||||
|
|
||||||
def test_init_positional_buildozer(self):
|
def test_init_positional_buildozer(self):
|
||||||
"""Positional `buildozer` argument is required."""
|
"""Positional `buildozer` argument is required."""
|
||||||
|
@ -184,18 +138,18 @@ class TestTargetAndroid:
|
||||||
|
|
||||||
def test_sdkmanager(self):
|
def test_sdkmanager(self):
|
||||||
"""Tests the _sdkmanager() method."""
|
"""Tests the _sdkmanager() method."""
|
||||||
self.init_target()
|
target_android = init_target(self.temp_dir)
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
with patch_buildozer_cmd() as m_cmd, patch_buildozer_cmd_expect() as m_cmd_expect, patch_os_isfile() as m_isfile:
|
with patch_buildozer_cmd() as m_cmd, patch_buildozer_cmd_expect() as m_cmd_expect, patch_os_isfile() as m_isfile:
|
||||||
m_isfile.return_value = True
|
m_isfile.return_value = True
|
||||||
assert m_cmd.return_value == self.target_android._sdkmanager(**kwargs)
|
assert m_cmd.return_value == target_android._sdkmanager(**kwargs)
|
||||||
assert m_cmd.call_count == 1
|
assert m_cmd.call_count == 1
|
||||||
assert m_cmd_expect.call_count == 0
|
assert m_cmd_expect.call_count == 0
|
||||||
assert m_isfile.call_count == 1
|
assert m_isfile.call_count == 1
|
||||||
kwargs = {"return_child": True}
|
kwargs = {"return_child": True}
|
||||||
with patch_buildozer_cmd() as m_cmd, patch_buildozer_cmd_expect() as m_cmd_expect, patch_os_isfile() as m_isfile:
|
with patch_buildozer_cmd() as m_cmd, patch_buildozer_cmd_expect() as m_cmd_expect, patch_os_isfile() as m_isfile:
|
||||||
m_isfile.return_value = True
|
m_isfile.return_value = True
|
||||||
assert m_cmd_expect.return_value == self.target_android._sdkmanager(
|
assert m_cmd_expect.return_value == target_android._sdkmanager(
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
assert m_cmd.call_count == 0
|
assert m_cmd.call_count == 0
|
||||||
|
@ -204,43 +158,44 @@ class TestTargetAndroid:
|
||||||
|
|
||||||
def test_check_requirements(self):
|
def test_check_requirements(self):
|
||||||
"""Basic tests for the check_requirements() method."""
|
"""Basic tests for the check_requirements() method."""
|
||||||
self.init_target()
|
target_android = init_target(self.temp_dir)
|
||||||
assert not hasattr(self.target_android, "adb_cmd")
|
buildozer = target_android.buildozer
|
||||||
assert not hasattr(self.target_android, "javac_cmd")
|
assert not hasattr(target_android, "adb_cmd")
|
||||||
assert "PATH" not in self.buildozer.environ
|
assert not hasattr(target_android, "javac_cmd")
|
||||||
|
assert "PATH" not in buildozer.environ
|
||||||
with patch_buildozer_checkbin() as m_checkbin:
|
with patch_buildozer_checkbin() as m_checkbin:
|
||||||
self.target_android.check_requirements()
|
target_android.check_requirements()
|
||||||
assert m_checkbin.call_args_list == [
|
assert m_checkbin.call_args_list == [
|
||||||
mock.call("Git (git)", "git"),
|
mock.call("Git (git)", "git"),
|
||||||
mock.call("Cython (cython)", "cython"),
|
mock.call("Cython (cython)", "cython"),
|
||||||
mock.call("Java compiler (javac)", "javac"),
|
mock.call("Java compiler (javac)", "javac"),
|
||||||
mock.call("Java keytool (keytool)", "keytool"),
|
mock.call("Java keytool (keytool)", "keytool"),
|
||||||
]
|
]
|
||||||
assert self.target_android.adb_cmd.endswith(
|
assert target_android.adb_cmd.endswith(
|
||||||
".buildozer/android/platform/android-sdk/platform-tools/adb"
|
".buildozer/android/platform/android-sdk/platform-tools/adb"
|
||||||
)
|
)
|
||||||
assert self.target_android.javac_cmd == "javac"
|
assert target_android.javac_cmd == "javac"
|
||||||
assert self.target_android.keytool_cmd == "keytool"
|
assert target_android.keytool_cmd == "keytool"
|
||||||
assert "PATH" in self.buildozer.environ
|
assert "PATH" in buildozer.environ
|
||||||
|
|
||||||
def test_check_configuration_tokens(self):
|
def test_check_configuration_tokens(self):
|
||||||
"""Basic tests for the check_configuration_tokens() method."""
|
"""Basic tests for the check_configuration_tokens() method."""
|
||||||
self.init_target()
|
target_android = init_target(self.temp_dir)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
"buildozer.targets.android.Target.check_configuration_tokens"
|
"buildozer.targets.android.Target.check_configuration_tokens"
|
||||||
) as m_check_configuration_tokens:
|
) as m_check_configuration_tokens:
|
||||||
self.target_android.check_configuration_tokens()
|
target_android.check_configuration_tokens()
|
||||||
assert m_check_configuration_tokens.call_args_list == [mock.call([])]
|
assert m_check_configuration_tokens.call_args_list == [mock.call([])]
|
||||||
|
|
||||||
@pytest.mark.parametrize("platform", ["linux", "darwin"])
|
@pytest.mark.parametrize("platform", ["linux", "darwin"])
|
||||||
def test_install_android_sdk(self, platform):
|
def test_install_android_sdk(self, platform):
|
||||||
"""Basic tests for the _install_android_sdk() method."""
|
"""Basic tests for the _install_android_sdk() method."""
|
||||||
self.init_target()
|
target_android = init_target(self.temp_dir)
|
||||||
with patch_buildozer_file_exists() as m_file_exists, patch_buildozer_download() as m_download:
|
with patch_buildozer_file_exists() as m_file_exists, patch_buildozer_download() as m_download:
|
||||||
m_file_exists.return_value = True
|
m_file_exists.return_value = True
|
||||||
sdk_dir = self.target_android._install_android_sdk()
|
sdk_dir = target_android._install_android_sdk()
|
||||||
assert m_file_exists.call_args_list == [
|
assert m_file_exists.call_args_list == [
|
||||||
mock.call(self.target_android.android_sdk_dir)
|
mock.call(target_android.android_sdk_dir)
|
||||||
]
|
]
|
||||||
assert m_download.call_args_list == []
|
assert m_download.call_args_list == []
|
||||||
assert sdk_dir.endswith(".buildozer/android/platform/android-sdk")
|
assert sdk_dir.endswith(".buildozer/android/platform/android-sdk")
|
||||||
|
@ -249,9 +204,9 @@ class TestTargetAndroid:
|
||||||
patch_buildozer_file_extract() as m_file_extract, \
|
patch_buildozer_file_extract() as m_file_extract, \
|
||||||
patch_platform(platform):
|
patch_platform(platform):
|
||||||
m_file_exists.return_value = False
|
m_file_exists.return_value = False
|
||||||
sdk_dir = self.target_android._install_android_sdk()
|
sdk_dir = target_android._install_android_sdk()
|
||||||
assert m_file_exists.call_args_list == [
|
assert m_file_exists.call_args_list == [
|
||||||
mock.call(self.target_android.android_sdk_dir)
|
mock.call(target_android.android_sdk_dir)
|
||||||
]
|
]
|
||||||
platform_map = {"linux": "linux", "darwin": "mac"}
|
platform_map = {"linux": "linux", "darwin": "mac"}
|
||||||
platform = platform_map[platform]
|
platform = platform_map[platform]
|
||||||
|
@ -268,8 +223,9 @@ class TestTargetAndroid:
|
||||||
|
|
||||||
def test_build_package(self):
|
def test_build_package(self):
|
||||||
"""Basic tests for the build_package() method."""
|
"""Basic tests for the build_package() method."""
|
||||||
self.init_target()
|
target_android = init_target(self.temp_dir)
|
||||||
m_execute_build_package = self.call_build_package()
|
buildozer = target_android.buildozer
|
||||||
|
m_execute_build_package = call_build_package(target_android)
|
||||||
assert m_execute_build_package.call_args_list == [
|
assert m_execute_build_package.call_args_list == [
|
||||||
mock.call(
|
mock.call(
|
||||||
[
|
[
|
||||||
|
@ -278,7 +234,7 @@ class TestTargetAndroid:
|
||||||
("--package", "org.test.myapp"),
|
("--package", "org.test.myapp"),
|
||||||
("--minsdk", "21"),
|
("--minsdk", "21"),
|
||||||
("--ndk-api", "21"),
|
("--ndk-api", "21"),
|
||||||
("--private", "{buildozer_dir}/android/app".format(buildozer_dir=self.buildozer.buildozer_dir)),
|
("--private", "{buildozer_dir}/android/app".format(buildozer_dir=buildozer.buildozer_dir)),
|
||||||
("--android-entrypoint", "org.kivy.android.PythonActivity"),
|
("--android-entrypoint", "org.kivy.android.PythonActivity"),
|
||||||
("--android-apptheme", "@android:style/Theme.NoTitleBar"),
|
("--android-apptheme", "@android:style/Theme.NoTitleBar"),
|
||||||
("--orientation", "portrait"),
|
("--orientation", "portrait"),
|
||||||
|
@ -290,10 +246,11 @@ class TestTargetAndroid:
|
||||||
|
|
||||||
def test_numeric_version(self):
|
def test_numeric_version(self):
|
||||||
"""The `android.numeric_version` config should be passed to `build_package()`."""
|
"""The `android.numeric_version` config should be passed to `build_package()`."""
|
||||||
self.init_target({
|
target_android = init_target(self.temp_dir, {
|
||||||
"android.numeric_version": "1234"
|
"android.numeric_version": "1234"
|
||||||
})
|
})
|
||||||
m_execute_build_package = self.call_build_package()
|
buildozer = target_android.buildozer
|
||||||
|
m_execute_build_package = call_build_package(target_android)
|
||||||
assert m_execute_build_package.call_args_list == [
|
assert m_execute_build_package.call_args_list == [
|
||||||
mock.call(
|
mock.call(
|
||||||
[
|
[
|
||||||
|
@ -302,7 +259,7 @@ class TestTargetAndroid:
|
||||||
("--package", "org.test.myapp"),
|
("--package", "org.test.myapp"),
|
||||||
("--minsdk", "21"),
|
("--minsdk", "21"),
|
||||||
("--ndk-api", "21"),
|
("--ndk-api", "21"),
|
||||||
("--private", "{buildozer_dir}/android/app".format(buildozer_dir=self.buildozer.buildozer_dir)),
|
("--private", "{buildozer_dir}/android/app".format(buildozer_dir=buildozer.buildozer_dir)),
|
||||||
("--android-entrypoint", "org.kivy.android.PythonActivity"),
|
("--android-entrypoint", "org.kivy.android.PythonActivity"),
|
||||||
("--android-apptheme", "@android:style/Theme.NoTitleBar"),
|
("--android-apptheme", "@android:style/Theme.NoTitleBar"),
|
||||||
("--orientation", "portrait"),
|
("--orientation", "portrait"),
|
||||||
|
@ -323,11 +280,11 @@ class TestTargetAndroid:
|
||||||
with open(filters_path, 'w') as f:
|
with open(filters_path, 'w') as f:
|
||||||
f.write('<?xml version="1.0" encoding="utf-8"?>')
|
f.write('<?xml version="1.0" encoding="utf-8"?>')
|
||||||
|
|
||||||
self.init_target({
|
target_android = init_target(self.temp_dir, {
|
||||||
'android.manifest.intent_filters': 'filters.xml'
|
'android.manifest.intent_filters': 'filters.xml'
|
||||||
})
|
})
|
||||||
|
buildozer = target_android.buildozer
|
||||||
m_execute_build_package = self.call_build_package()
|
m_execute_build_package = call_build_package(target_android)
|
||||||
|
|
||||||
assert m_execute_build_package.call_args_list == [
|
assert m_execute_build_package.call_args_list == [
|
||||||
mock.call(
|
mock.call(
|
||||||
|
@ -337,7 +294,7 @@ class TestTargetAndroid:
|
||||||
('--package', 'org.test.myapp'),
|
('--package', 'org.test.myapp'),
|
||||||
('--minsdk', '21'),
|
('--minsdk', '21'),
|
||||||
('--ndk-api', '21'),
|
('--ndk-api', '21'),
|
||||||
('--private', '{buildozer_dir}/android/app'.format(buildozer_dir=self.buildozer.buildozer_dir)),
|
('--private', '{buildozer_dir}/android/app'.format(buildozer_dir=buildozer.buildozer_dir)),
|
||||||
('--android-entrypoint', 'org.kivy.android.PythonActivity'),
|
('--android-entrypoint', 'org.kivy.android.PythonActivity'),
|
||||||
('--android-apptheme', '@android:style/Theme.NoTitleBar'),
|
('--android-apptheme', '@android:style/Theme.NoTitleBar'),
|
||||||
('--orientation', 'portrait'),
|
('--orientation', 'portrait'),
|
||||||
|
|
80
tests/targets/test_ios.py
Normal file
80
tests/targets/test_ios.py
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from buildozer.targets.ios import TargetIos
|
||||||
|
from tests.targets.utils import init_buildozer, patch_buildozer_checkbin
|
||||||
|
|
||||||
|
|
||||||
|
def init_target(temp_dir, options=None):
|
||||||
|
buildozer = init_buildozer(temp_dir, "ios", options)
|
||||||
|
return TargetIos(buildozer)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
sys.platform != "darwin", reason="Only macOS is supported for target iOS"
|
||||||
|
)
|
||||||
|
class TestTargetIos:
|
||||||
|
def setup_method(self):
|
||||||
|
"""
|
||||||
|
Create a temporary directory that will contain the spec file and will
|
||||||
|
serve as the root_dir.
|
||||||
|
"""
|
||||||
|
self.temp_dir = tempfile.TemporaryDirectory()
|
||||||
|
|
||||||
|
def tear_method(self):
|
||||||
|
"""
|
||||||
|
Remove the temporary directory created in self.setup_method.
|
||||||
|
"""
|
||||||
|
self.temp_dir.cleanup()
|
||||||
|
|
||||||
|
def test_init(self):
|
||||||
|
"""Tests init defaults."""
|
||||||
|
target = init_target(self.temp_dir)
|
||||||
|
assert target.targetname == "ios"
|
||||||
|
assert target.code_signing_allowed == "CODE_SIGNING_ALLOWED=NO"
|
||||||
|
assert target.build_mode == "debug"
|
||||||
|
assert target.platform_update is False
|
||||||
|
|
||||||
|
def test_check_requirements(self):
|
||||||
|
"""Basic tests for the check_requirements() method."""
|
||||||
|
target = init_target(self.temp_dir)
|
||||||
|
buildozer = target.buildozer
|
||||||
|
assert not hasattr(target, "adb_cmd")
|
||||||
|
assert not hasattr(target, "javac_cmd")
|
||||||
|
assert "PATH" not in buildozer.environ
|
||||||
|
with patch_buildozer_checkbin() as m_checkbin:
|
||||||
|
target.check_requirements()
|
||||||
|
assert m_checkbin.call_args_list == [
|
||||||
|
mock.call("Xcode xcodebuild", "xcodebuild"),
|
||||||
|
mock.call("Xcode xcode-select", "xcode-select"),
|
||||||
|
mock.call("Git git", "git"),
|
||||||
|
mock.call("Cython cython", "cython"),
|
||||||
|
mock.call("pkg-config", "pkg-config"),
|
||||||
|
mock.call("autoconf", "autoconf"),
|
||||||
|
mock.call("automake", "automake"),
|
||||||
|
mock.call("libtool", "libtool"),
|
||||||
|
]
|
||||||
|
assert target._toolchain_cmd.endswith("toolchain.py ")
|
||||||
|
assert target._xcodebuild_cmd == "xcodebuild "
|
||||||
|
|
||||||
|
def test_check_configuration_tokens(self):
|
||||||
|
"""Basic tests for the check_configuration_tokens() method."""
|
||||||
|
target = init_target(self.temp_dir, {"ios.codesign.allowed": "yes"})
|
||||||
|
with mock.patch(
|
||||||
|
"buildozer.targets.android.Target.check_configuration_tokens"
|
||||||
|
) as m_check_configuration_tokens, mock.patch(
|
||||||
|
"buildozer.targets.ios.TargetIos._get_available_identities"
|
||||||
|
) as m_get_available_identities:
|
||||||
|
target.check_configuration_tokens()
|
||||||
|
assert m_get_available_identities.call_args_list == [mock.call()]
|
||||||
|
assert m_check_configuration_tokens.call_args_list == [
|
||||||
|
mock.call(
|
||||||
|
[
|
||||||
|
'[app] "ios.codesign.debug" key missing, you must give a certificate name to use.',
|
||||||
|
'[app] "ios.codesign.release" key missing, you must give a certificate name to use.',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
54
tests/targets/utils.py
Normal file
54
tests/targets/utils.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
import buildozer as buildozer_module
|
||||||
|
from buildozer import Buildozer
|
||||||
|
|
||||||
|
|
||||||
|
def patch_buildozer(method):
|
||||||
|
return mock.patch("buildozer.Buildozer.{method}".format(method=method))
|
||||||
|
|
||||||
|
|
||||||
|
def patch_buildozer_checkbin():
|
||||||
|
return patch_buildozer("checkbin")
|
||||||
|
|
||||||
|
|
||||||
|
def default_specfile_path():
|
||||||
|
return os.path.join(os.path.dirname(buildozer_module.__file__), "default.spec")
|
||||||
|
|
||||||
|
|
||||||
|
def init_buildozer(temp_dir, target, options=None):
|
||||||
|
"""
|
||||||
|
Create a buildozer.spec file in the temporary directory and init the
|
||||||
|
Buildozer instance.
|
||||||
|
|
||||||
|
The optional argument can be used to overwrite the config options in
|
||||||
|
the buildozer.spec file, e.g.:
|
||||||
|
|
||||||
|
init_buildozer({'title': 'Test App'})
|
||||||
|
|
||||||
|
will replace line 4 of the default spec file.
|
||||||
|
"""
|
||||||
|
if options is None:
|
||||||
|
options = {}
|
||||||
|
|
||||||
|
spec_path = os.path.join(temp_dir.name, "buildozer.spec")
|
||||||
|
|
||||||
|
with open(default_specfile_path()) as f:
|
||||||
|
default_spec = f.readlines()
|
||||||
|
|
||||||
|
spec = []
|
||||||
|
for line in default_spec:
|
||||||
|
if line.strip():
|
||||||
|
match = re.search(r"[#\s]?([a-z_\.]+)", line)
|
||||||
|
key = match and match.group(1)
|
||||||
|
if key in options:
|
||||||
|
line = "{} = {}\n".format(key, options[key])
|
||||||
|
|
||||||
|
spec.append(line)
|
||||||
|
|
||||||
|
with open(spec_path, "w") as f:
|
||||||
|
f.writelines(spec)
|
||||||
|
|
||||||
|
return Buildozer(filename=spec_path, target=target)
|
Loading…
Reference in a new issue