예제 #1
0
 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
예제 #4
0
 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()
예제 #10
0
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()
예제 #11
0
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()
예제 #12
0
 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()
예제 #15
0
 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
예제 #18
0
 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()
예제 #20
0
    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()
예제 #21
0
 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() == ""