def test_uninstall_base(self) -> None: if self._package_name not in self._device.list_installed_packages(): return app = Application(self._device, {'package_name': self._package_name}) app.uninstall() if self._package_name in self._device.list_installed_packages(): raise UpgradeTestException( f"Uninstall base package {self._package_name} failed")
def test_install_uninstall_app(self, device: Device, support_app: str): app = Application.from_apk(support_app, device) app.uninstall() assert app.package_name not in device.list_installed_packages() app = Application.from_apk(support_app, device) assert app.package_name in device.list_installed_packages() app.uninstall() assert app.package_name not in device.list_installed_packages()
def test_app_uninstall_logs_error(self, device: Device): with patch("androidtestorchestrator.application.log") as mock_logger: app = Application(manifest={ 'package_name': "com.android.providers.calendar", 'permissions': ["android.permission.WRITE_EXTERNAL_STORAGE"] }, device=device) app.uninstall() assert mock_logger.error.called
def test_upgrade_to_target(self, upgrade_apk: str, startup_sec_timeout: int = 5) -> None: _name = _get_func_name() try: app = Application.from_apk(apk_path=upgrade_apk, device=self._device, as_upgrade=True) if app.package_name != self._package_name: raise UpgradeTestException( f"Target APK package does not match base APK package: " f"{app.package_name}/{self._package_name}") app.start(activity=".MainActivity") if not self._ensure_activity_in_foreground( package_name=app.package_name, timeout=startup_sec_timeout): raise UpgradeTestException( f"Unable to start up package within {startup_sec_timeout}s timeout threshold" ) time.sleep( 1 ) # Give the application activity an extra second to actually get to foreground completely if not self._take_screenshot(test_case=_name): log.warning(f"Unable to take screenshot for test: {_name}") except Exception as e: raise UpgradeTestException(str(e))
def test_grant_permissions(self, device: Device, support_test_app: str): app = Application.from_apk(support_test_app, device) assert app.package_name.endswith(".test") try: permission = "android.permission.WRITE_EXTERNAL_STORAGE" app.grant_permissions([permission]) output = device.execute_remote_cmd("shell", "dumpsys", "package", app.package_name, capture_stdout=True, timeout=10) perms = [] look_for_perms = False for line in output.splitlines(): if "granted=true" in line: perms.append(line.strip().split(':', 1)[0]) if "grantedPermissions" in line: # older reporting style . Ugh. Yeah for inconsistencies look_for_perms = True if look_for_perms: if "permission" in line: perms.append(line.strip()) assert permission in perms finally: app.uninstall()
def test_get_set_locale(self, device: Device, local_changer_apk): # noqa app = Application.from_apk(local_changer_apk, device) app.grant_permissions([" android.permission.CHANGE_CONFIGURATION"]) device.set_locale("en_US") assert device.get_locale() == "en_US" device.set_locale("fr_FR") assert device.get_locale() == "fr_FR"
def test_monkey(self, device: Device, support_app): # noqa app = asyncio.get_event_loop().run_until_complete( Application.from_apk_async(support_app, device)) app.monkey() time.sleep(3) assert self.pidof(app), "Failed to start app" app.stop(force=True) assert not self.pidof(app), "Failed to stop app"
def test_oneshot_cpu_mem(self, device: Device, support_app: str): app = Application.from_apk(support_app, device) app.monkey() time.sleep(1) cpu, mem = device.oneshot_cpu_mem(app.package_name) app.stop(force=True) assert cpu is not None assert mem is not None
def test_grant_permissions(self, device: Device, support_app: str): app = Application.from_apk(support_app, device) try: app.grant_permissions( ["android.permission.WRITE_EXTERNAL_STORAGE"]) finally: app.uninstall()
def uninstall_apk(apk, device): """ A little of a misnomer, as we don't actually uninstall an apk, however we can get the name of the package from the apk and ensure the app is not installed on the device (ensure "cleanliness" for testing) :param apk: apk to get package name from :param device: device to uninstall package from """ with suppress(Exception): Application(AXMLParser.parse(apk).package_name, device).uninstall()
def android_test_app(device, support_app: str, support_test_app: str): uninstall_apk(support_app, device) uninstall_apk(support_test_app, device) app_for_test = TestApplication.from_apk(support_test_app, device) support_app = Application.from_apk(support_app, device) try: yield app_for_test finally: app_for_test.uninstall() support_app.uninstall()
def setup_foreign_apps(self, paths_to_foreign_apks: List[str], timeout: Optional[int] = Device.TIMEOUT_LONG_ADB_CMD) -> None: """ Install other apps (outside of test app and app under test) in support of testing :param paths_to_foreign_apks: string list of paths to the apks to be installed :param timeout: if specified, raise TimeoutError if install takes too long :raises TimeoutError: if timeout specified and install takes more than specified time """ for path in paths_to_foreign_apks: self._installed.append(Application.from_apk(apk_path=path, device=self._device, timeout=timeout))
def test_start_stop(self, device: Device, support_app: str): # noqa app = Application.from_apk(support_app, device) try: app.start(".MainActivity") time.sleep(3) # Have to give time to "come up" :-( assert self.pidof( app), "No pid found for app; app not started as expected" app.stop() assert not self.pidof(app) finally: app.uninstall()
def test_start_stop_app(self, device: Device, test_butler_service: str, support_app: str): # noqa app = Application.from_apk(support_app, device) butler_app = ServiceApplication.from_apk(test_butler_service, device) try: app.start(activity=".MainActivity") butler_app.start(activity=".ButlerService", foreground=True) app.clear_data() app.stop() butler_app.stop() finally: app.uninstall() butler_app.uninstall()
def test_uninstall_upgrade(self, upgrade_apk: str) -> None: package = AXMLParser.parse(upgrade_apk).package_name if package not in self._device.list_installed_packages(): return app = Application(self._device, {'package_name': package}) app.stop() app.uninstall() if package in self._device.list_installed_packages(): raise UpgradeTestException( f"Uninstall upgrade package {package} failed")
def test_install_uninstall(self, device: Device, support_app: str): app = Application.from_apk(support_app, device) try: assert app.package_name == "com.linkedin.mdctest" output = device.execute_remote_cmd("shell", "dumpsys", "package", app.package_name, capture_stdout=True, timeout=10) for line in output.splitlines(): if "versionName" in line: assert app.version == line.strip().split('=', 1)[1] finally: app.uninstall() assert app.package_name not in device.list_installed_packages()
def test_app(device, request, support_app, support_test_app, test_butler_service): butler_app = Application.from_apk(support_app, device) test_app = TestApplication.from_apk(support_test_app, device) service = ServiceApplication.from_apk(test_butler_service, device) def fin(): """ cleanup after test """ butler_app.uninstall() test_app.uninstall() service.uninstall() request.addfinalizer(fin) return test_app
def test_install_base(self) -> None: _name = _get_func_name() try: app = Application.from_apk(apk_path=self._apk_under_test, device=self._device, as_upgrade=False) app.start(activity=".MainActivity") if not self._ensure_activity_in_foreground(app.package_name): raise UpgradeTestException( "Unable to start up package within timeout threshold") time.sleep( 1 ) # Give the application activity an extra second to actually get to foreground completely if not self._take_screenshot(test_case=_name): log.warning(f"Unable to take screenshot for test: {_name}") except Exception as e: raise UpgradeTestException(str(e))
def test_install_uninstall(self, device: Device, support_app: str): uninstall_apk(support_app, device) app = Application.from_apk(support_app, device) try: assert app.package_name == "com.linkedin.mtotestapp" completed = device.execute_remote_cmd("shell", "dumpsys", "package", app.package_name, timeout=10, stdout=subprocess.PIPE) for line in completed.stdout.splitlines(): if "versionName" in line: assert app.version == line.strip().split('=', 1)[1] finally: app.uninstall() assert app.package_name not in device.list_installed_packages()
def __init__(self, device: Device, path_to_apk: str, path_to_test_apk: str, timeout: Optional[int] = Device.TIMEOUT_LONG_ADB_CMD, grant_all_user_permissions: bool = True): """ :param device: device to install and run test app on :param path_to_apk: Path to apk bundle for target app :param path_to_test_apk: Path to apk bundle for test app :param timeout: if specified, raise TimeoutError if install takes too long :param grant_all_user_permissions: If True, grant all user permissions defined in the manifest of the app and test app (prevents pop-ups from occurring on first request for a user permission that can interfere with tests) :raises TimeoutError: if timeout specified and install does not complete wihtin this time """ self._app = Application.from_apk(path_to_apk, device=device, timeout=timeout) self._test_app: TestApplication = TestApplication.from_apk(apk_path=path_to_test_apk, device=device, timeout=timeout) self._installed = [self._app, self._test_app] self._storage = DeviceStorage(device) self._data_files: List[str] = [] self._device = device if grant_all_user_permissions: self._test_app.grant_permissions() self._app.grant_permissions()
def do_install(app_cls: Application, package_name: str): uninstall_apk(package_name, device) app = app_cls.from_apk(package_name, device) apps.append(app) return app
def test_list_packages(self, device: Device, support_app: str): app = Application.from_apk(support_app, device) pkgs = device.list_installed_packages() assert app.package_name in pkgs
def test_clear_data(self, device, support_app): # noqa app = Application.from_apk(support_app, device) app.clear_data() # should not raise exception
def test_version_invalid_package(self, device): with pytest.raises(Exception): Application.from_apk("no.such.package", device)
def test_add_background_task(self, device: Device, support_app: str, support_test_app: str, tmpdir: str): # ensure applications are not already installed as precursor to running tests with suppress(Exception): Application(device, {'package_name': support_app}).uninstall() with suppress(Exception): Application(device, {'package_name': support_test_app}).uninstall() def test_generator(): yield (TestSuite( name='test_suite1', arguments=[ "-e", "class", "com.linkedin.mtotestapp.InstrumentedTestAllSuccess#useAppContext" ])) # noinspection PyMissingOrEmptyDocstring class EmptyListener(TestRunListener): _call_count = {} def test_run_started(self, test_run_name: str, count: int = 0): EmptyListener._call_count.setdefault(test_run_name, 0) EmptyListener._call_count[test_run_name] += 1 def test_run_ended(self, duration: float, **kwargs): pass def test_run_failed(self, error_message: str): pass def test_failed(self, class_name: str, test_name: str, stack_trace: str): pass def test_ignored(self, class_name: str, test_name: str): pass def test_assumption_failure(self, class_name: str, test_name: str, stack_trace: str): pass def test_started(self, class_name: str, test_name: str): pass def test_ended(self, class_name: str, test_name: str, **kwargs): pass was_called = False async def some_task(orchestrator: AndroidTestOrchestrator): """ For testing that user-defined background task was indeed executed """ nonlocal was_called was_called = True with pytest.raises(Exception): orchestrator.add_logcat_monitor("BogusTag", None) test_vectors = os.path.join(str(tmpdir), "test_vectors") os.makedirs(test_vectors) with open(os.path.join(test_vectors, "file"), 'w') as f: f.write("TEST VECTOR DATA") with AndroidTestOrchestrator(artifact_dir=str(tmpdir)) as orchestrator, \ EspressoTestPreparation(device=device, path_to_apk=support_app, path_to_test_apk=support_test_app, grant_all_user_permissions=True) as test_prep, \ DevicePreparation(device) as device_prep: device_prep.verify_network_connection("localhost", 4) device_prep.port_forward(5748, 5749) completed = device.execute_remote_cmd("forward", "--list", stdout=subprocess.PIPE) forwarded_ports = completed.stdout assert "5748" in forwarded_ports and "5749" in forwarded_ports device_prep.reverse_port_forward(5432, 5431) completed = device.execute_remote_cmd("reverse", "--list", stdout=subprocess.PIPE) reverse_forwarded_ports = completed.stdout assert "5432" in reverse_forwarded_ports and "5431" in reverse_forwarded_ports test_prep.upload_test_vectors(test_vectors) orchestrator.add_test_suite_listeners( [EmptyListener(), EmptyListener()]) orchestrator.add_background_task(some_task(orchestrator)) orchestrator.execute_test_plan(test_plan=test_generator(), test_application=test_prep.test_app) assert was_called, "Failed to call user-define background task" # listener was added a second time, so expect call counts of 2 assert all([v == 2 for v in EmptyListener._call_count.values()]) completed = device.execute_remote_cmd("forward", "--list", stdout=subprocess.PIPE) forwarded_ports = completed.stdout assert forwarded_ports.strip() == "" completed = device.execute_remote_cmd("reverse", "--list", stdout=subprocess.PIPE) reverse_forwarded_ports = completed.stdout assert reverse_forwarded_ports.strip() == ""