Merge pull request #1171 from AndreMiras/feature/test_ios_follow_up
✅ Increases ios target test coverage
This commit is contained in:
commit
459807465a
4 changed files with 169 additions and 14 deletions
|
@ -60,14 +60,20 @@ li { padding: 1em; }
|
|||
class TargetIos(Target):
|
||||
targetname = "ios"
|
||||
|
||||
def __init__(self, buildozer):
|
||||
super().__init__(buildozer)
|
||||
executable = sys.executable or 'python'
|
||||
self._toolchain_cmd = f"{executable} toolchain.py "
|
||||
self._xcodebuild_cmd = "xcodebuild "
|
||||
# set via install_platform()
|
||||
self.ios_dir = None
|
||||
self.ios_deploy_dir = None
|
||||
|
||||
def check_requirements(self):
|
||||
if sys.platform != "darwin":
|
||||
raise NotImplementedError("Only macOS is supported for iOS target")
|
||||
checkbin = self.buildozer.checkbin
|
||||
cmd = self.buildozer.cmd
|
||||
executable = sys.executable or 'python'
|
||||
self._toolchain_cmd = f"{executable} toolchain.py "
|
||||
self._xcodebuild_cmd = "xcodebuild "
|
||||
|
||||
checkbin('Xcode xcodebuild', 'xcodebuild')
|
||||
checkbin('Xcode xcode-select', 'xcode-select')
|
||||
|
@ -95,6 +101,10 @@ class TargetIos(Target):
|
|||
self.buildozer.debug(' -> found {0}'.format(xcode))
|
||||
|
||||
def install_platform(self):
|
||||
"""
|
||||
Clones `kivy/kivy-ios` and `phonegap/ios-deploy` then sets `ios_dir`
|
||||
and `ios_deploy_dir` accordingly.
|
||||
"""
|
||||
self.ios_dir = self.install_or_update_repo('kivy-ios', platform='ios')
|
||||
self.ios_deploy_dir = self.install_or_update_repo('ios-deploy',
|
||||
platform='ios',
|
||||
|
@ -385,10 +395,10 @@ class TargetIos(Target):
|
|||
if not error:
|
||||
correct = True
|
||||
break
|
||||
self.error('Invalid keychain password')
|
||||
self.buildozer.error('Invalid keychain password')
|
||||
|
||||
if not correct:
|
||||
self.error('Unable to unlock the keychain, exiting.')
|
||||
self.buildozer.error('Unable to unlock the keychain, exiting.')
|
||||
raise BuildozerCommandException()
|
||||
|
||||
# maybe user want to save it for further reuse?
|
||||
|
|
|
@ -9,21 +9,15 @@ from tests.targets.utils import (
|
|||
init_buildozer,
|
||||
patch_buildozer,
|
||||
patch_buildozer_checkbin,
|
||||
patch_buildozer_cmd,
|
||||
patch_buildozer_file_exists,
|
||||
)
|
||||
|
||||
|
||||
def patch_buildozer_cmd():
|
||||
return patch_buildozer("cmd")
|
||||
|
||||
|
||||
def patch_buildozer_cmd_expect():
|
||||
return patch_buildozer("cmd_expect")
|
||||
|
||||
|
||||
def patch_buildozer_file_exists():
|
||||
return patch_buildozer("file_exists")
|
||||
|
||||
|
||||
def patch_buildozer_download():
|
||||
return patch_buildozer("download")
|
||||
|
||||
|
|
|
@ -4,8 +4,19 @@ from unittest import mock
|
|||
|
||||
import pytest
|
||||
|
||||
from buildozer import BuildozerCommandException
|
||||
from buildozer.targets.ios import TargetIos
|
||||
from tests.targets.utils import init_buildozer, patch_buildozer_checkbin
|
||||
from tests.targets.utils import (
|
||||
init_buildozer,
|
||||
patch_buildozer_checkbin,
|
||||
patch_buildozer_cmd,
|
||||
patch_buildozer_error,
|
||||
patch_buildozer_file_exists,
|
||||
)
|
||||
|
||||
|
||||
def patch_target_ios(method):
|
||||
return mock.patch("buildozer.targets.ios.TargetIos.{method}".format(method=method))
|
||||
|
||||
|
||||
def init_target(temp_dir, options=None):
|
||||
|
@ -78,3 +89,131 @@ class TestTargetIos:
|
|||
]
|
||||
)
|
||||
]
|
||||
|
||||
def test_get_available_packages(self):
|
||||
"""Checks the toolchain `recipes --compact` output is parsed correctly to return recipe list."""
|
||||
target = init_target(self.temp_dir)
|
||||
with patch_target_ios("toolchain") as m_toolchain:
|
||||
m_toolchain.return_value = ("hostpython3 kivy pillow python3 sdl2", None, 0)
|
||||
available_packages = target.get_available_packages()
|
||||
assert m_toolchain.call_args_list == [
|
||||
mock.call("recipes --compact", get_stdout=True)
|
||||
]
|
||||
assert available_packages == [
|
||||
"hostpython3",
|
||||
"kivy",
|
||||
"pillow",
|
||||
"python3",
|
||||
"sdl2",
|
||||
]
|
||||
|
||||
def test_install_platform(self):
|
||||
"""Checks `install_platform()` calls clone commands and sets `ios_dir` and `ios_deploy_dir` attributes."""
|
||||
target = init_target(self.temp_dir)
|
||||
assert target.ios_dir is None
|
||||
assert target.ios_deploy_dir is None
|
||||
with patch_buildozer_cmd() as m_cmd:
|
||||
target.install_platform()
|
||||
assert m_cmd.call_args_list == [
|
||||
mock.call("git clone https://github.com/kivy/kivy-ios", cwd=mock.ANY),
|
||||
mock.call(
|
||||
"git clone --branch 1.10.0 https://github.com/phonegap/ios-deploy",
|
||||
cwd=mock.ANY,
|
||||
),
|
||||
]
|
||||
assert target.ios_dir.endswith(".buildozer/ios/platform/kivy-ios")
|
||||
assert target.ios_deploy_dir.endswith(".buildozer/ios/platform/ios-deploy")
|
||||
|
||||
def test_compile_platform(self):
|
||||
"""Checks the `toolchain build` command is called on the ios requirements."""
|
||||
target = init_target(self.temp_dir)
|
||||
target.ios_deploy_dir = "/ios/deploy/dir"
|
||||
# fmt: off
|
||||
with patch_target_ios("get_available_packages") as m_get_available_packages, \
|
||||
patch_target_ios("toolchain") as m_toolchain, \
|
||||
patch_buildozer_file_exists() as m_file_exists:
|
||||
m_get_available_packages.return_value = ["hostpython3", "python3"]
|
||||
m_file_exists.return_value = True
|
||||
target.compile_platform()
|
||||
# fmt: on
|
||||
assert m_get_available_packages.call_args_list == [mock.call()]
|
||||
assert m_toolchain.call_args_list == [mock.call("build python3")]
|
||||
assert m_file_exists.call_args_list == [
|
||||
mock.call(target.ios_deploy_dir, "ios-deploy")
|
||||
]
|
||||
|
||||
def test_get_package(self):
|
||||
"""Checks default package values and checks it can be overridden."""
|
||||
# default value
|
||||
target = init_target(self.temp_dir)
|
||||
package = target._get_package()
|
||||
assert package == "org.test.myapp"
|
||||
# override
|
||||
target = init_target(
|
||||
self.temp_dir,
|
||||
{"package.domain": "com.github.kivy", "package.name": "buildozer"},
|
||||
)
|
||||
package = target._get_package()
|
||||
assert package == "com.github.kivy.buildozer"
|
||||
|
||||
def test_unlock_keychain_wrong_password(self):
|
||||
"""A `BuildozerCommandException` should be raised on wrong password 3 times."""
|
||||
target = init_target(self.temp_dir)
|
||||
# fmt: off
|
||||
with mock.patch("buildozer.targets.ios.getpass") as m_getpass, \
|
||||
patch_buildozer_cmd() as m_cmd, \
|
||||
pytest.raises(BuildozerCommandException):
|
||||
m_getpass.return_value = "password"
|
||||
# the `security unlock-keychain` command returned an error
|
||||
# hence we'll get prompted to enter the password
|
||||
m_cmd.return_value = (None, None, 123)
|
||||
target._unlock_keychain()
|
||||
# fmt: on
|
||||
assert m_getpass.call_args_list == [
|
||||
mock.call("Password to unlock the default keychain:"),
|
||||
mock.call("Password to unlock the default keychain:"),
|
||||
mock.call("Password to unlock the default keychain:"),
|
||||
]
|
||||
|
||||
def test_build_package_no_signature(self):
|
||||
"""Code signing is currently required to go through final `xcodebuild` steps."""
|
||||
target = init_target(self.temp_dir)
|
||||
target.ios_dir = "/ios/dir"
|
||||
# fmt: off
|
||||
with patch_target_ios("_unlock_keychain") as m_unlock_keychain, \
|
||||
patch_buildozer_error() as m_error, \
|
||||
patch_target_ios("xcodebuild") as m_xcodebuild, \
|
||||
mock.patch("buildozer.targets.ios.plistlib.readPlist") as m_readplist, \
|
||||
mock.patch("buildozer.targets.ios.plistlib.writePlist") as m_writeplist, \
|
||||
patch_buildozer_cmd() as m_cmd:
|
||||
m_readplist.return_value = {}
|
||||
target.build_package()
|
||||
# fmt: on
|
||||
assert m_unlock_keychain.call_args_list == [mock.call()]
|
||||
assert m_error.call_args_list == [
|
||||
mock.call(
|
||||
"Cannot create the IPA package without signature. "
|
||||
'You must fill the "ios.codesign.debug" token.'
|
||||
)
|
||||
]
|
||||
assert m_xcodebuild.call_args_list == [
|
||||
mock.call(
|
||||
"-configuration Debug ENABLE_BITCODE=NO "
|
||||
"CODE_SIGNING_ALLOWED=NO clean build",
|
||||
cwd="/ios/dir/myapp-ios",
|
||||
)
|
||||
]
|
||||
assert m_readplist.call_args_list == [
|
||||
mock.call("/ios/dir/myapp-ios/myapp-Info.plist")
|
||||
]
|
||||
assert m_writeplist.call_args_list == [
|
||||
mock.call(
|
||||
{
|
||||
"CFBundleIdentifier": "org.test.myapp",
|
||||
"CFBundleShortVersionString": "0.1",
|
||||
"CFBundleVersion": "0.1.None",
|
||||
},
|
||||
"/ios/dir/myapp-ios/myapp-Info.plist",
|
||||
)
|
||||
]
|
||||
assert m_cmd.call_args_list == [mock.call(mock.ANY, cwd=target.ios_dir)]
|
||||
|
|
|
@ -10,10 +10,22 @@ def patch_buildozer(method):
|
|||
return mock.patch("buildozer.Buildozer.{method}".format(method=method))
|
||||
|
||||
|
||||
def patch_buildozer_cmd():
|
||||
return patch_buildozer("cmd")
|
||||
|
||||
|
||||
def patch_buildozer_checkbin():
|
||||
return patch_buildozer("checkbin")
|
||||
|
||||
|
||||
def patch_buildozer_file_exists():
|
||||
return patch_buildozer("file_exists")
|
||||
|
||||
|
||||
def patch_buildozer_error():
|
||||
return patch_buildozer("error")
|
||||
|
||||
|
||||
def default_specfile_path():
|
||||
return os.path.join(os.path.dirname(buildozer_module.__file__), "default.spec")
|
||||
|
||||
|
|
Loading…
Reference in a new issue