def test_pull(self, device: Device, mp_tmp_dir): storage = DeviceStorage(device) local_path = os.path.join(mp_tmp_dir, "somefile") remote_path = "/".join([storage.external_storage_location, "touchedfile"]) device.execute_remote_cmd("shell", "touch", remote_path) storage.pull(remote_path=remote_path, local_path=local_path) assert os.path.exists(local_path)
def test_push_remove(self, device: Device): storage = DeviceStorage(device) remote_location = "/".join( [storage.external_storage_location, "some_file"]) with suppress(Exception): storage.remove(remote_location) output = device.execute_remote_cmd("shell", "ls", device.external_storage_location, capture_stdout=True) if os.path.basename(remote_location) in output: raise Exception("Error: did not expect file %s on remote device" % remote_location) storage.push(local_path=(os.path.abspath(__file__)), remote_path=remote_location) output = device.execute_remote_cmd("shell", "ls", device.external_storage_location, capture_stdout=True) assert os.path.basename(remote_location) in output storage.remove(remote_location) output = device.execute_remote_cmd("shell", "ls", device.external_storage_location, capture_stdout=True) assert not os.path.basename(remote_location) in output
def test_make_dir(self, device: Device): storage = DeviceStorage(device) new_remote_dir = "/".join( [storage.external_storage_location, "a", "b", "c", "d"]) # assure dir does not already exist: with suppress(Exception): storage.remove(new_remote_dir, recursive=True) try: output = device.execute_remote_cmd("shell", "ls", "-d", new_remote_dir, capture_stdout=True) # expect "no such directory" error leading to exception, but just in case: assert new_remote_dir not in output except Device.CommandExecutionFailureException as e: assert "no such" in str(e).lower() storage.make_dir(new_remote_dir) output = device.execute_remote_cmd("shell", "ls", "-d", new_remote_dir, capture_stdout=True) assert new_remote_dir in output
def test_restore(self, device: Device, monkeypatch, fake_sdk: str): def mock_set_device_setting(self_, *args, **kargs): assert args[0] == "ns" assert args[1] == "key" assert args[2] == "old_value" def mock_set_device_property(self_, *args, **kargs): assert args[0] == "key2" assert args[1] == "old_value2" monkeypatch.setattr( "androidtestorchestrator.device.Device.set_device_setting", mock_set_device_setting) monkeypatch.setattr( "androidtestorchestrator.device.Device.set_system_property", mock_set_device_property) device = Device("fake_serial_id", os.path.join(fake_sdk, "platform-tools", "adb")) device_restoration = AndroidTestOrchestrator._DeviceRestoration(device) device_restoration.device_setting_changed("ns", "key", "old_value", "new_value") device_restoration.device_property_changed("key2", "old_value2", "new_value") device_restoration.restore() assert not device_restoration._restoration_properties assert not device_restoration._restoration_settings
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_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_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 test_return_home_fails(self, install_app, device: Device, support_app: str): app = install_app(Application, support_app) app.start(activity=".MainActivity") assert device.foreground_activity() == app.package_name with pytest.raises(expected_exception=Exception) as excinfo: # Nobody would ever really pass a negative number, but our test app has only one activity screen. So # need to pass -1 to force the function to reach its back button key-press limit DeviceInteraction(device).return_home(keycode_back_limit=-1) assert "Max number of back button presses" in str(excinfo.value)
def test_device_property_changed(self, device: Device, fake_sdk): device = Device("fake_serial_id", os.path.join(fake_sdk, "platform-tools", "adb")) device_restoration = AndroidTestOrchestrator._DeviceRestoration(device) device_restoration.device_property_changed("key", "old_value", "new_value") assert device_restoration._restoration_properties["key"] == "old_value" device_restoration.device_property_changed("key", "new_value", "newer_value") assert device_restoration._restoration_properties["key"] == "old_value" device_restoration.device_property_changed("key", "newer_value", "old_value") assert "key" not in device_restoration._restoration_properties
def test_return_home_succeeds(self, install_app, device: Device, support_app: str): app = install_app(Application, support_app) with patch( 'androidtestorchestrator.device.DeviceInteraction.home_screen_active', new_callable=Mock) as mock_home_screen_active: # Have to mock out call since inputting the KEYCODE_BACK event doesn't work for all devices/emulators mock_home_screen_active.return_value = True app.start(activity=".MainActivity") assert device.foreground_activity() == app.package_name device_nav = DeviceInteraction(device) device_nav.return_home() assert device_nav.home_screen_active()
def test_clean_kill_throws_exception_when_home_screen_not_active( self, install_app, device: Device, support_app: str): app = install_app(Application, support_app) with patch('androidtestorchestrator.device.DeviceInteraction.home_screen_active', new_callable=Mock) as mock_home_screen_active, \ patch('androidtestorchestrator.application.Application.pid', new_callable=PropertyMock) as mock_pid: mock_pid.return_value = "21445" # Force home_screen_active to be false to indicate clean_kill failed mock_home_screen_active.return_value = False app.start(".MainActivity") time.sleep(3) # Give app time to come up assert device.foreground_activity() == app.package_name with pytest.raises(Exception) as exc_info: app.clean_kill() assert "Failed to background current foreground app" in str( exc_info.value)
def test_device_setting_changed(self, fake_sdk): device = Device("fake_serial_id", os.path.join(fake_sdk, "platform-tools", "adb")) device_restoration = AndroidTestOrchestrator._DeviceRestoration(device) device_restoration.device_setting_changed("ns", "key", "old_value", "new_value") assert device_restoration._restoration_settings[("ns", "key")] == "old_value" device_restoration.device_setting_changed("ns", "key", "new_value", "newer_value") # only first change should stick assert device_restoration._restoration_settings[("ns", "key")] == "old_value" device_restoration.device_setting_changed("ns", "key", "newer_value", "old_value") # back to where we started, so should not longer be in restoration values: assert ("ns", "key") not in device_restoration._restoration_settings
def test_clean_kill_succeeds(self, install_app, device: Device, support_app: str): app = install_app(Application, support_app) with patch( 'androidtestorchestrator.device.DeviceInteraction.home_screen_active', new_callable=Mock) as mock_home_screen_active: with patch('androidtestorchestrator.application.Application.pid', new_callable=PropertyMock) as mock_pid: # Force home_screen_active to be True to indicate clean_kill made it to the home screen mock_home_screen_active.return_value = True # Force pid to return None to make it seem like the process was actually killed mock_pid.return_value = None app.start(".MainActivity") time.sleep(3) # Give app time to come up assert device.foreground_activity() == app.package_name # clean_kill doesn't return anything, so just make sure no exception is raised app.clean_kill()
def test_clean_kill_throws_exception_when_pid_still_existing( self, install_app, device: Device, support_app: str): app = install_app(Application, support_app) with patch( 'androidtestorchestrator.device.DeviceInteraction.home_screen_active', new_callable=Mock) as mock_home_screen_active: with patch('androidtestorchestrator.application.Application.pid', new_callable=PropertyMock) as mock_pid: # Force home_screen_active to be True to indicate clean_kill made it to the home screen mock_home_screen_active.return_value = True # Force pid to return a fake process id to indicate clean_kill failed mock_pid.return_value = 1234 app.start(".MainActivity") time.sleep(3) # Give app time to come up assert device.foreground_activity() == app.package_name with pytest.raises(Exception) as exc_info: app.clean_kill() assert "Detected app process is still running" in str( exc_info.value)
def test_grant_permissions(self, device: Device, install_app, support_test_app): test_app = install_app(TestApplication, support_test_app) assert test_app.package_name.endswith(".test") permission = "android.permission.WRITE_EXTERNAL_STORAGE" test_app.grant_permissions([permission]) completed = device.execute_remote_cmd("shell", "dumpsys", "package", test_app.package_name, timeout=10, stdout=subprocess.PIPE) perms = [] look_for_perms = False for line in completed.stdout.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