Package tlib :: Package base :: Module AndroidHelper
[hide private]
[frames] | no frames]

Source Code for Module tlib.base.AndroidHelper

  1  # noinspection PyPackageRequirements 
  2  import requests 
  3  import time 
  4  # noinspection PyPackageRequirements 
  5  import pytest 
  6  import re 
  7  from _pytest import runner 
  8  from tlib.base import TestHelper 
  9  import logging 
 10   
 11  DEVICE_UNPLUGGED = "disconnected"    # Device is not connected 
 12  DEVICE_OFFLINE = "offline"           # Device is connected but offline 
 13  DEVICE_UNAUTHORIZED = "unauthorized" # Unauthorized 
 14  DEVICE_ONLINE = "online"             # Device is connected and accessible 
 15   
16 -def is_webdriver_running(tlib_logger, adb_logger, log=True):
17 """ 18 Function to validate if webdriver is running and a connection can be established 19 20 @param tlib_logger: TLib logger 21 @type tlib_logger: logging.logger 22 @param adb_logger: ADB logger 23 @type adb_logger: logging.logger 24 @param log: When true, log debugging information 25 @type log: bool 26 """ 27 try: 28 if log: tlib_logger.debug("Checking if Webdriver is running") 29 response = requests.get("http://localhost:8080/wd/hub/status", timeout=10) 30 except requests.ConnectionError as e: 31 if log: adb_logger.debug("Connection to Webdriver failed:\n%s" % e) 32 return False 33 34 return response.status_code == 200
35 36
37 -def get_device_status(tlib_logger, adb_logger, serial_id):
38 """ 39 Get status of a device using it's serial id\n 40 Serial id can be either a ID (for devices connected to USB) or an IP and port (For devices connected via IP) 41 42 @param tlib_logger: TLib logger 43 @type tlib_logger: logging.logger 44 @param adb_logger: ADB logger 45 @type adb_logger: logging.logger 46 @param serial_id: Device's serial number 47 @type serial_id: str 48 """ 49 50 out = TestHelper.run_command(adb_logger, ["adb", "devices"], fail_on_error=False) 51 if re.search(serial_id, out[0]) is None: 52 tlib_logger.debug("Device {serial_id} is not connected".format(serial_id=serial_id)) 53 return DEVICE_UNPLUGGED 54 elif re.search("{serial_id}\s+offline".format(serial_id=serial_id), out[0]) is not None: 55 tlib_logger.debug("Device {serial_id} is offline".format(serial_id=serial_id)) 56 return DEVICE_OFFLINE 57 elif re.search("{serial_id}\s+unauthorized".format(serial_id=serial_id), out[0]) is not None: 58 tlib_logger.debug("Device {serial_id} is offline".format(serial_id=serial_id)) 59 return DEVICE_UNAUTHORIZED 60 elif re.search("{serial_id}\s+device".format(serial_id=serial_id), out[0]) is not None: 61 tlib_logger.debug("Device {serial_id} is online".format(serial_id=serial_id)) 62 return DEVICE_ONLINE 63 else: 64 tlib_logger.error("Unknown device status\n%s" % out[0]) 65 pytest.fail("Unknown device status\n%s" % out[0])
66 67
68 -def setup_ip_connection(tlib_logger, adb_logger, serial_id):
69 """ 70 Connects to an android device via IP and waits for the connection to be established. 71 72 @param tlib_logger: TLib logger 73 @type tlib_logger: logging.logger 74 @param adb_logger: ADB logger 75 @type adb_logger: logging.logger 76 @param serial_id: Device's serial number 77 @type serial_id: str 78 """ 79 # Validate is device is already connected 80 tlib_logger.debug("Setting up IP connection to device {serial_id}".format(serial_id=serial_id)) 81 status = get_device_status(tlib_logger, adb_logger, serial_id) 82 83 if status == DEVICE_ONLINE: 84 tlib_logger.debug("Device is already online".format(serial_id=serial_id)) 85 return 86 87 # If device is offline or unauthorized, disconnect 88 if status == DEVICE_OFFLINE: 89 tlib_logger.warn("Device {serial_id} is offline, disconnecting and retrying".format(serial_id=serial_id)) 90 terminate_ip_connection(tlib_logger, adb_logger, serial_id) 91 elif status == DEVICE_UNAUTHORIZED: 92 terminate_ip_connection(tlib_logger, adb_logger, serial_id) 93 tlib_logger.error("Device {serial_id} is not authorized, aborting".format(serial_id=serial_id)) 94 pytest.fail("Device {serial_id} is not authorized, aborting".format(serial_id=serial_id)) 95 elif status == DEVICE_UNPLUGGED: 96 tlib_logger.warn("Device {serial_id} is disconecting, resetting connection".format(serial_id=serial_id)) 97 terminate_ip_connection(tlib_logger, adb_logger, serial_id) 98 99 timeout = 0.5 100 101 #We wait up to 3 seconds 102 for i in range(1, int(3 / timeout)): 103 out = TestHelper.run_command(adb_logger, ["adb", "connect", serial_id]) 104 log_adb_output(adb_logger, out) 105 106 if get_device_status(tlib_logger, adb_logger, serial_id) == DEVICE_ONLINE: 107 tlib_logger.debug("Connected to device") 108 return 109 else: 110 tlib_logger.debug("Not yet connected") 111 time.sleep(timeout) 112 113 #If we're here, it means connection failed 114 adb_logger.error(r"Timeout while connecting to device {serial_id}\nADB output:\n{out}".format(serial_id=serial_id, out=out)) 115 # noinspection PyUnresolvedReferences 116 pytest.fail(r"Timeout while connecting to device {serial_id}\nADB output:\n{out}".format(serial_id=serial_id, out=out))
117 118
119 -def terminate_ip_connection(tlib_logger, adb_logger, serial_id):
120 """ 121 Disconnects from device 122 123 @param tlib_logger: TLib logger 124 @type tlib_logger: logging.logger 125 @param adb_logger: ADB logger 126 @type adb_logger: logging.logger 127 @param serial_id: Device's serial number 128 @type serial_id: str 129 """ 130 tlib_logger.debug("Disconnecting from device {serial_id}".format(serial_id=serial_id)) 131 out = TestHelper.run_command(adb_logger, ["adb", "disconnect", serial_id]) 132 log_adb_output(adb_logger, out)
133 134
135 -def close_webdriver(tlib_logger, adb_logger, serial_id):
136 """ 137 Stops Webdriver app o the device 138 139 @param tlib_logger: TLib logger 140 @type tlib_logger: logging.logger 141 @param adb_logger: ADB logger 142 @type adb_logger: logging.logger 143 @param serial_id: Device's serial number 144 @type serial_id: str 145 """ 146 tlib_logger.debug("Closing Webdriver on {serial_id}".format(serial_id=serial_id)) 147 if serial_id is None or serial_id == "": 148 out = TestHelper.run_command(adb_logger, 149 ["adb", "shell", "am", "force-stop", "org.openqa.selenium.android.app"]) 150 else: 151 out = TestHelper.run_command(adb_logger, 152 ["adb", "-s", serial_id, "shell", "am", "force-stop", "org.openqa.selenium.android.app"]) 153 log_adb_output(adb_logger, out)
154 155
156 -def setup_port_forwarding(tlib_logger, adb_logger, serial_id):
157 """ 158 Setup port forwarding between computer and device. 159 160 @param tlib_logger: TLib logger 161 @type tlib_logger: logging.logger 162 @param adb_logger: ADB logger 163 @type adb_logger: logging.logger 164 @param serial_id: Device's serial number 165 @type serial_id: str 166 """ 167 tlib_logger.info("Setting up port forwarding") 168 if serial_id is None or serial_id == "": 169 out = TestHelper.run_command(adb_logger, ["adb", "forward", "tcp:8080", "tcp:8080"]) 170 else: 171 out = TestHelper.run_command(adb_logger, ["adb", "-s", serial_id, "forward", "tcp:8080", "tcp:8080"]) 172 log_adb_output(adb_logger, out)
173 174
175 -def teardown_port_forwarding(tlib_logger, adb_logger):
176 """ 177 Terminates all port forwarding connections 178 179 @param tlib_logger: TLib logger 180 @type tlib_logger: logging.logger 181 @param adb_logger: ADB logger 182 @type adb_logger: logging.logger 183 """ 184 tlib_logger.info("Tearing down port forwarding") 185 out = TestHelper.run_command(adb_logger, ["adb", "forward", "--remove-all"]) 186 log_adb_output(adb_logger, out)
187 188
189 -def stop_adb_server(tlib_logger, adb_logger):
190 """ 191 Stops adb on the machine\n 192 This can be required by TeamCity so some folders are not locked 193 194 @param tlib_logger: TLib logger 195 @type tlib_logger: logging.logger 196 @param adb_logger: ADB logger 197 @type adb_logger: logging.logger 198 """ 199 tlib_logger.info("Stopping ADB") 200 out = TestHelper.run_command(adb_logger, ["adb", "kill-server"], fail_on_error=False) 201 log_adb_output(adb_logger, out)
202 203
204 -def start_webdriver(tlib_logger, adb_logger, serial_id):
205 """ 206 Starts Webdriver app on the device 207 208 @param tlib_logger: TLib logger 209 @type tlib_logger: logging.logger 210 @param adb_logger: ADB logger 211 @type adb_logger: logging.logger 212 @param serial_id: Device's serial number 213 @type serial_id: str 214 """ 215 tlib_logger.info("Starting webdriver on the device") 216 if serial_id is None or serial_id == "": 217 out = TestHelper.run_command(adb_logger, ["adb", "shell", "am", "start", "-a", "android.intent.action.MAIN", 218 "-n", "org.openqa.selenium.android.app/.MainActivity", "-e", "debug", "true"]) 219 else: 220 out = TestHelper.run_command(adb_logger, 221 ["adb", "-s", serial_id, "shell", "am", "start", "-a", "android.intent.action.MAIN", 222 "-n", "org.openqa.selenium.android.app/.MainActivity", 223 "-e", "debug", "true"]) 224 log_adb_output(adb_logger, out)
225 226
227 -def wait_for_connection_to_webdriver(tlib_logger, adb_logger):
228 """ 229 Waits up to 3 seconds for a connection to Webdriver 230 231 @param tlib_logger: TLib logger 232 @type tlib_logger: logging.logger 233 @param adb_logger: ADB logger 234 @type adb_logger: logging.logger 235 """ 236 #Check connection to webdriver can be established. Retry 3 times 237 tlib_logger.debug("Waiting for connection to Webdriver") 238 timeout = 0.5 239 for i in range(1, int(3 / timeout)): 240 if is_webdriver_running(tlib_logger, adb_logger, False): 241 tlib_logger.debug("Webdriver started successfully") 242 break 243 tlib_logger.debug("Can't connect to Webdriver, retrying in {timeout} seconds".format(timeout=timeout)) 244 time.sleep(timeout) 245 246 if not is_webdriver_running(tlib_logger, adb_logger, False): 247 tlib_logger.error("Couldn't start Webdriver. Make sure it's installed and running\n" 248 "See https://code.google.com/p/selenium/wiki/AndroidDriver#Setup_the_Emulator for more details") 249 # noinspection PyUnresolvedReferences 250 pytest.fail("Couldn't start Webdriver. Make sure it's installed and running\n" 251 "See https://code.google.com/p/selenium/wiki/AndroidDriver#Setup_the_Emulator for more details")
252 253 254 # noinspection PyUnresolvedReferences
255 -def setup_webdriver(tlib_logger, adb_logger, serial_id):
256 """ 257 Connects to a device and starts webdriver 258 259 @param tlib_logger: TLib logger 260 @type tlib_logger: logging.logger 261 @param adb_logger: ADB logger 262 @type adb_logger: logging.logger 263 @param serial_id: Device's serial number 264 @type serial_id: str 265 """ 266 #Try to connect to Webdriver and exit if success 267 if is_webdriver_running(tlib_logger, adb_logger, log=False): 268 tlib_logger.debug("Already connected to device") 269 return 270 271 tlib_logger.info("Connecting to Webdriver") 272 273 #Connect to device and setup port forwarding. 274 if TestHelper.is_valid_ip(serial_id): 275 setup_ip_connection(tlib_logger, adb_logger, serial_id) 276 277 setup_port_forwarding(tlib_logger, adb_logger, serial_id) 278 279 #Try again to connect to Webdriver and exit if success 280 if is_webdriver_running(tlib_logger, adb_logger): 281 tlib_logger.debug("Connected to Webdriver") 282 return 283 284 # Webdriver not running, start it 285 start_webdriver(tlib_logger, adb_logger, serial_id) 286 287 #Ensure we're connected 288 wait_for_connection_to_webdriver(tlib_logger, adb_logger) 289 290 tlib_logger.info("Connection to Webdriver established")
291 292 293 # noinspection PyUnresolvedReferences
294 -def teardown_webdriver(tlib_logger, adb_logger, serial_id):
295 """ 296 Closes webdriver and disconnects from device 297 298 @param tlib_logger: TLib logger 299 @type tlib_logger: logging.logger 300 @param adb_logger: ADB logger 301 @type adb_logger: logging.logger 302 @param serial_id: Device's serial number 303 @type serial_id: str 304 """ 305 #close selenium WebDriver 306 tlib_logger.info("Disconnecting from Webdriver") 307 close_webdriver(tlib_logger, adb_logger, serial_id) 308 309 # Terminates IP connection if an IP was given 310 if TestHelper.is_valid_ip(serial_id): 311 terminate_ip_connection(tlib_logger, adb_logger, serial_id) 312 313 #Stop adb service so it won't lock files required by TeamCity 314 try: 315 stop_adb_server(tlib_logger, adb_logger) 316 except runner.Failed: 317 #If ADB fails to stop, don't abort test 318 adb_logger.warn("Error stopping ADB server") 319 320 tlib_logger.info("Disconnected from Webdriver")
321 322
323 -def log_adb_output(logger, out):
324 """ 325 Logs ADB output 326 327 @param logger: ADB logger 328 @type logger: logging.logger 329 """ 330 if out[0] is not None and out[0] != '': 331 logger.debug("\n" + out[0]) 332 333 if out[1] is not None and out[1] != '': 334 logger.debug("\n" + out[1])
335