def run(): AudioFunction.init() Logger.init(Logger.Mode.STDOUT) Adb.init() package = "com.htc.audiofunctionsdemo" activity = ".activities.MainActivity" component = package + "/" + activity device, serialno = ViewClient.connectToDeviceOrExit() vc = ViewClient(device, serialno, autodump=False) if not device.isScreenOn(): device.wake() vc.dump() import StringIO as sio so = sio.StringIO() vc.traverse(stream=so) if "lockscreen" in so.getvalue(): device.unlock() # keymap reference: # https://github.com/dtmilano/AndroidViewClient/blob/master/src/com/dtmilano/android/adb/androidkeymap.py device.press("HOME") time.sleep(1) device.startActivity(component=component) time.sleep(1) playback_task_run(device) record_task_run(device, serialno) AudioFunction.finalize() Logger.finalize()
def run_ui_traversal(scenario, scenarios, emulator_id, smart_input_results, smart_input_assignment): smart_input_for_activity = smart_input_results.get(scenario.static_analysis_result.activity_name) start_app(emulator_id, scenarios.package) start_activity(emulator_id, scenarios.package, scenario.static_analysis_result.activity_name) device, serialno = ViewClient.connectToDeviceOrExit(serialno=emulator_id) vc = ViewClient(device, serialno, autodump=False) # try dumping 5 times, before timing out dump_tries = 0 dump_error = True while dump_error and dump_tries < 5: dump_error = False dump_tries += 1 try: vc.dump(sleep=5) except Exception: dump_error = True if dump_error: raise SoftTimeLimitExceeded() edittexts = vc.findViewsWithAttribute("class", "android.widget.EditText") logger.info("EditText views: %s" % str(edittexts)) clickable_views = vc.findViewsWithAttribute("clickable", "true") logger.info("Clickable views: %s" % str(clickable_views)) listviews = vc.findViewsWithAttribute("class", "android.widget.ListView") logger.info("ListViews: %s" % str(listviews)) fill_edit_texts(edittexts, smart_input_for_activity, smart_input_assignment, vc, emulator_id) click_clickable_views(clickable_views, vc, device, emulator_id)
def check(): print("check") os.system("adb shell cmd statusbar expand-notifications") from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) Icon=vc.findViewsWithAttribute("resource-id","com.android.systemui:id/mobile_combo_card") time.sleep(1) vc.dump() Mode=(Icon[0].getContentDescription()) List=list(Mode) L1=List[0] L2=List[1] global String String= L1+ L2 print(String) Split=Mode.split(' ') L3=Split[1] L4=Split[2] combine=L3+" " + L4 print(combine) sets=String+" " + combine print(sets) global gets gets=String+" "+ L3 print(gets)
class NineGameEmulate(): def __init__(self): self.device = None self.serialno = None self.vc = None self.accountfilename = '360mobile_imei_list.'+time.strftime('%Y-%m-%d',time.localtime(time.time())) def openapp(self): self.device,self.serialno = ViewClient.connectToDeviceOrExit(serialno=None) FLAG_ACTIVITY_NEW_TASK = 0x10000000 componentName = 'com.qihoo.browser/.activity.SplashActivity' self.device.startActivity(component=componentName,flags=FLAG_ACTIVITY_NEW_TASK) ViewClient.sleep(3) self.vc = ViewClient(self.device,self.serialno,forceviewserveruse=True) def doSomeClick(self,imei,imsi=None): if self.device == None : self.openapp() #self.device.dragDip((400,400),(10,400),800,5) #ViewClient.sleep(3) #self.device.dragDip((400,400),(10,400),800,5) #ViewClient.sleep(3) #waitViewByTx('立即修复',self.vc) #self.vc.findViewWithText('立即修复').touch() ViewClient.sleep(1) self.device.drag((600,400),(10,400),2000) ViewClient.sleep(1) self.device.drag((600,400),(10,400),2000) self.vc.dump() waitViewById('id/ensure',self.vc) #self.vc.findViewById('id/ensure').touch() self.device.touch(345,1070,2) ViewClient.sleep(2) waitViewById('id/first_nav',self.vc) self.vc.findViewById('id/first_nav').touch() ViewClient.sleep(5) f = open(self.accountfilename,'a') try: f.writelines(imei+"\t"+imsi+"\r\n") finally: f.flush() f.close() def reactiveMobile(self): if self.device == None : self.openapp() waitViewById('id/rgBottomNav',self.vc) self.device.touch(675,95,2) ViewClient.sleep(3) self.vc.findViewById('id/game_name').touch()
def resetWhatsApp(): device.press('KEYCODE_HOME') global vc app_log.info('Starting whatsapp...') device.shell('am force-stop '+package) vc = ViewClient(device, serialno) vc.dump(window=-1) device.startActivity(component=component);
def action_open_stats(device, serialno): print("open stats tab") device.press('KEYCODE_TAB') for i in range(5): device.press('KEYCODE_DPAD_LEFT') viewclient = ViewClient(device, serialno) viewclient.dump() view = viewclient.findViewById("org.wordpress.android:id/row_stats") view.touch() time.sleep(5)
def test_LaunchBrowser(self): print("Back to home") self.device.press('KEYCODE_BACK') self.device.press('KEYCODE_HOME') self.device.press('KEYCODE_HOME') self.device.press('KEYCODE_BACK') VPS = "javascript:alert(document.getElementsByTagName('html')[0].innerHTML);" USE_BROWSER = False if USE_BROWSER: package = 'com.android.browser' activity = '.BrowserActivity' _id = 'id/no_id/12' else: package = 'com.android.chrome' activity = 'com.google.android.apps.chrome.Main' _id = 'id/no_id/28' component = package + "/" + activity uri = 'http://dtmilano.blogspot.com' print("Open Browser") self.device.startActivity(component=component, uri=uri) print("Waite for 5 sec") ViewClient.sleep(5) vc = ViewClient(device=self.device, serialno=self.serialno) sdkVersion = vc.getSdkVersion() print("Get SDK Version:"+str(sdkVersion)) if sdkVersion > 10: print("Show search bar") self.device.drag((240, 180), (240, 420), 1, 20) else: for i in range(10): self.device.press('KEYCODE_DPAD_UP') ViewClient.sleep(1) print("Delete search bar") self.device.press('KEYCODE_DEL') ViewClient.sleep(1) print("Input JS and go") self.device.type(VPS) ViewClient.sleep(1) self.device.press('KEYCODE_ENTER') ViewClient.sleep(3) print("dump ViewClient data") vc.dump() print vc.findViewByIdOrRaise('com.android.chrome:id/js_modal_dialog_message' if sdkVersion >= 16 else 'id/message').getText().replace('\\n', "\n") self.device.press('KEYCODE_BACK' if sdkVersion > 10 else 'KEYCODE_ENTER') ViewClient.sleep(1)
def test(): # 连接手机 device, serialno = ViewClient.connectToDeviceOrExit() vc = ViewClient(device, serialno) # 按HOME键 device.press('KEYCODE_HOME') time.sleep(3) # 找到微信图标 vc.dump() weixin_button = vc.findViewWithTextOrRaise(u'微信') # 点击微信图标 weixin_button.touch() time.sleep(10) # 找到第一个联系人/群 # 可以使用UI Automator Viewer查看到对应第一个联系人/群的resource-id为"com.tencent.mm:id/auj" vc.dump() group_button = vc.findViewByIdOrRaise("com.tencent.mm:id/auj") # 点击进群 group_button.touch() time.sleep(5) # 找到输入框并输入当前时间 vc.dump() vc.findViewByIdOrRaise("com.tencent.mm:id/aep").setText('Now:{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'))) time.sleep(3) # 点击发送按钮 vc.dump() vc.findViewWithTextOrRaise(u'发送').touch()
def wake_device(device, serialno): if device.isScreenOn(): return device.wake() vc = ViewClient(device, serialno, autodump=False) try: vc.dump(sleep=0) so = sio.StringIO() vc.traverse(stream=so) if "lockscreen" in so.getvalue(): device.unlock() except: pass
def init(device): print 'init the test environment..ing.' #get Device connection #device = UtilTool.connectToDevice() #lanuch Contacts app device.startActivity(component='com.android.contacts/.activities.PeopleActivity') MonkeyRunner.sleep(15) #print device #get a ViewClient instance vc = ViewClient(device,'emulator-5554') MonkeyRunner.sleep(10) #get Window content of current page vc.dump() MonkeyRunner.sleep(5) return vc
class ViewClientWrapper: def __init__(self, serialno): device, serialno = ViewClient.connectToDeviceOrExit(serialno=serialno) self.vc = ViewClient(device, serialno) self.device = device if DEBUG: print >> sys.stderr, "ViewClientWrapper: connected to", device, serialno def dump(self): """Dumps window hierarchy.""" return self.vc.dump() def touch(self, x, y): """Touches a point. :param x: x :param y: y :return: """ return self.vc.touch(x, y) @staticmethod def long_touch_view(view): """Long-touches the view.""" return view.longTouch() @staticmethod def touch_view(view): """Touches the View""" return view.touch() @staticmethod def get_view_position_and_size(view): """ Gets the View position and size :param view: the View :return: the position and size """ return view.getPositionAndSize() def find_view_with_text(self, text): return self.vc.findViewWithText(text) def find_view_by_id(self, id): return self.vc.findViewById(id) def start_activity(self, component): """Starts Activity.""" return self.vc.device.startActivity(component) def get_top_activity_name(self): return self.device.getTopActivityName() def force_stop_package(self, package): self.device.shell('am force-stop %s' % package) def get_windows(self): return self.device.getWindows() def is_keyboard_show(self): return self.device.isKeyboardShown()
def action_open_editor_and_type_text(device, serialno): print("open editor") # Open My Sites for i in range(5): device.press('KEYCODE_DPAD_LEFT') viewclient = ViewClient(device, serialno) viewclient.dump() view = viewclient.findViewById("org.wordpress.android:id/fab_button") view.touch() time.sleep(2) viewclient.dump() view = viewclient.findViewById("org.wordpress.android:id/post_content") # Type a sample text (spaces can't be entered via device.type()) view.type(settings.example_post_content) time.sleep(2)
def toStart(vc): isFBMHomeTop = False vc.dump() while not isFBMHomeTop: searchBox = vc.findViewsWithAttribute('class', 'android.view.ViewGroup') for item in searchBox[0].children: print item.getText(), item.getContentDescription(), item.getTag() if item.getText() == 'Online': isFBMHomeTop = True if not isFBMHomeTop: print "swipe up" device, serialno = ViewClient.connectToDeviceOrExit() vc = ViewClient(device, serialno) device.dragDip((169.0, 197.0), (173.0, 557.0), 1000, 20, 0) vc.dump()
def action_open_editor_and_type_text(device, serialno): print("open editor") # Open My Sites for i in range(5): device.press('KEYCODE_DPAD_LEFT') viewclient = ViewClient(device, serialno) viewclient.dump() view = viewclient.findViewById("org.wordpress.android:id/fab_button") view.touch() time.sleep(2) # Type a sample title device.type(settings.example_post_title) # Switch to the content field device.press('KEYCODE_TAB') # Type a sample content device.type(settings.example_post_content) # Wait for the Webview :/ time.sleep(5)
class DeviceModify(): def __init__(self): self.device = None self.serialno = None self.vc = None self.openapp() def openapp(self): self.device,self.serialno = ViewClient.connectToDeviceOrExit() FLAG_ACTIVITY_NEW_TASK = 0x10000000 componentName = 'com.example.myxposed/.ParamActivity' self.device.startActivity(component=componentName,flags=FLAG_ACTIVITY_NEW_TASK) ViewClient.sleep(2) self.vc = ViewClient(self.device,self.serialno,forceviewserveruse=True) def modifyRandom(self): waitViewById('id/imei',self.vc) self.vc.findViewById('id/button2').touch() self.vc.dump() deviceIMEI = self.vc.findViewById('id/imei').getText() deviceIMSI = self.vc.findViewById('id/subscriberId').getText() f = open('device_imei.txt','w+') try: print 'save imei %s to file device_imei.txt'%(deviceIMEI) f.writelines(deviceIMEI +"\t"+deviceIMSI) finally: if(f != None): f.close() def modify2IMEI(self,imei,imsi=None): waitViewById('id/imei',self.vc) self.vc.dump() #print 'imei is ',imei self.vc.findViewById('id/imei').setText(imei[0:15]) #if imsi != None: # self.vc.findViewById('id/subscriberId').setText(imsi[0:15]) self.vc.findViewById('id/button1').touch()
def dump_view_server(package): kwargs1 = {VERBOSE: False, 'ignoresecuredevice': False, 'ignoreversioncheck': False} kwargs2 = {ViewClientOptions.FORCE_VIEW_SERVER_USE: False, ViewClientOptions.START_VIEW_SERVER: True, ViewClientOptions.AUTO_DUMP: False, ViewClientOptions.IGNORE_UIAUTOMATOR_KILLED: True, ViewClientOptions.COMPRESSED_DUMP: True, ViewClientOptions.USE_UIAUTOMATOR_HELPER: False, ViewClientOptions.DEBUG: {}, } kwargs2[ViewClientOptions.FORCE_VIEW_SERVER_USE] = True vc = ViewClient(*ViewClient.connectToDeviceOrExit(**kwargs1), **kwargs2) options = {WINDOW: -1, SAVE_SCREENSHOT: None, SAVE_VIEW_SCREENSHOTS: None, DO_NOT_DUMP_VIEWS: False, DEVICE_ART: None, DROP_SHADOW: False, SCREEN_GLARE: False} windows = vc.list() print windows transform = MAP['b'] for window in windows: if package not in windows[window]: continue print windows[window] vc.dump(window=int(window)) # ViewClient.imageDirectory = options[SAVE_VIEW_SCREENSHOTS] return ViewClientHandler.traverse(vc, transform=transform)
def unlock_device(self, udid, pin): pin = map(int, str(pin)) device, serialno = ViewClient.connectToDeviceOrExit() vc = ViewClient(device=device, serialno=udid) if device.isLocked(): print 'device with serial no ' + udid + ' is locked' device.wake() vc.dump() device.shell('input swipe 357 1227 357 680') vc.dump() for item in pin: item = str(item) key = vc.findViewWithText(item) if key: key.touch() else: print 'key not found or locator is incorrect' enter = vc.findViewById('com.android.systemui:id/key_enter') if enter: enter.touch() else: print 'key not found or locator is incorrect' else: print 'device with serial no ' + udid + ' is unlocked'
class adbDevice(object): # inputMethodRe = re.compile('\[\s+0, 0, 1061, 1920] InputMethod') def __init__(self, serialno=None): self.lock = threading.Semaphore() self.cmd = adbCmd(serialno) self.serialno = serialno def connect(self): self.d, self.serialno = ViewClient.connectToDeviceOrExit(serialno=self.serialno) self.vc = ViewClient(self.d, self.serialno, compresseddump=False, ignoreuiautomatorkilled=True, autodump=False) def startActivity(self, component): component = component.replace('$', '\$') self.cmd.shell(['am', 'start', '-n', component, '--activity-clear-task']) def isConnected(self): if self.__getDevices(self.serialno): return True else: return False def listPackages(self): return self.cmd.shell(['pm', 'list', 'package'], output=True) def reboot(self): self.cmd.reboot() def findAndTouch(self, text): self.dump(0) view = self.vc.findViewWithText(text) if view: view.touch() return True else: return False def dump(self, sleep=0.5, window=-1): try: self.lock.acquire() return self.vc.dump(sleep=sleep, window=-1) except RuntimeError as e: print e.message except ValueError as e: print e.message except socket.error, exc: print 'Caught exception socket.error : ' + str(exc) finally:
class ViewClientWrapper: def __init__(self, serialno): device, serialno = ViewClient.connectToDeviceOrExit(serialno=serialno) self.viewClient = ViewClient(device, serialno) if DEBUG: print >> sys.stderr, "ViewClientWrapper: connected to", device, serialno def dump(self): """Dumps window hierarchy.""" return self.viewClient.dump() def start_activity(self, component): """Starts Activity.""" return self.viewClient.device.startActivity(component) def long_touch_button(self, text): """Long-touches the button.""" self.viewClient.findViewWithTextOrRaise(text).longTouch()
def test_LaunchDemoAPI(self): device, serialno = ViewClient.connectToDeviceOrExit() print("Back to home") self.device.press('KEYCODE_BACK') self.device.press('KEYCODE_HOME') self.device.press('KEYCODE_HOME') self.device.press('KEYCODE_BACK') FLAG_ACTIVITY_NEW_TASK = 0x10000000 # 09-06 01:01:34.964: I/ActivityManager(873): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.android.apis/.ApiDemos bnds=[784,346][880,442]} from pid 991 componentName = 'com.example.android.apis/.ApiDemos' print("Open DemoAPI") device.startActivity(component=componentName, flags=FLAG_ACTIVITY_NEW_TASK) ViewClient.sleep(5) vc = ViewClient(device=device, serialno=serialno) app = vc.findViewWithText('App') if app: app.touch() ViewClient.sleep(1) # windows changed, request a new dump print("Find Alert Dialogs") vc.dump() ad = vc.findViewWithText('Alert Dialogs') if ad: ad.touch() ViewClient.sleep(1) # windows changed, request a new dump print("find List dialog") vc.dump() ld = vc.findViewWithText('List dialog') if ld: ld.touch() ViewClient.sleep(1) # windows changed, request a new dump print("Find Command three") vc.dump() c3 = vc.findViewWithText('Command three') if c3: c3.touch() ViewClient.sleep(1) device.press('KEYCODE_BACK') else: print >> sys.stderr, "Cannot find 'Command three'" else: print >> sys.stderr, "Cannot find 'List dialog'" else: print >> sys.stderr, "Cannot find 'Alert Dialogs'" else: print >> sys.stderr, "Cannot find 'App'"
class Device: """ Handle automation of android devices. Handle finding and pressing buttons, switches, etc. Keep track of when the view updates. """ def __init__(self): d, s = ViewClient.connectToDeviceOrExit() self.viewclient = ViewClient(d, s) self.dirty = True self.time_set_dirty = time.time() self.min_update_wait = 0 self.max_update_wait = 0 @property def dirty(self): """Return true or false, depending of if data needs to be refreshed""" return self.dirty @dirty.setter def dirty(self, value): """Mark the data as needing to be refreshed""" self.dirty = value if value is True: self.time_set_dirty = time.time() def refresh(self): """ If the data has been marked dirty, wait until min_update_wait seconds has passed before getting the data dump from the device. If nothing has changed, continue updating the data dump until max_update_wait seconds has passed. :return: """ if self.dirty: wait_time = self.time_set_dirty + self.min_update_wait - time.time() if wait_time < 0: wait_time = 0 old_data = self.viewclient.views self.viewclient.dump(sleep=wait_time) while time.time() < self.time_set_dirty + self.max_update_wait: if self.has_data_changed(old_data, self.viewclient.views): break old_data = self.viewclient.views self.viewclient.dump() else: logging.debug('update timed out') self.dirty = False @staticmethod def has_data_changed(old_data, new_data): """Compare old_data with the current data, if view's data has changed, return true""" if len(old_data) != len(new_data): return False for view1, view2 in zip(old_data, new_data): if view1.map != view2.map: return False return True def find_view(self, template): """Searches the views on the device and returns a list of views that match the template""" self.refresh() views = [] for view in self.viewclient.views: if template == view: views.append(ViewTemplate.from_view(view)) return views
# type some text def handleEditText(editText): editText.setText('23333') # deep copy utils def deepcopy(oldSet): newSet = set() for item in oldSet: newSet.add(item) return newSet # judge if is the same page def isSamePage(oldViews, newViews): if len(oldViews) != len(newViews): return False else: for view in zip(oldViews, newViews): if (view[0].map != view[1].map): return False return True views = set(vc.dump(window=-1)) # as a set mainActivity = device.getFocusedWindowName() activityStack = [mainActivity] dict = {mainActivity: views} handleViews()
class contacts: def __init__(self, device, devID='emulator-5554',sample = False): '''if sample is True, take snapshot as expected result.''' self.device=device self.sample=sample self.vc=ViewClient(device, devID) #use below code to remove the status bar from the snapshot width = int(device.getProperty('display.width')) height = int(device.getProperty('display.height')) density = device.getProperty('display.density') if density == .75: statusBarHeight = 19 elif density == 1.5: statusBarHeight = 38 elif density == 2.0: statusBarHeight = 50 else: statusBarHeight = 25 self.snap_rect = 0, statusBarHeight, width, height - statusBarHeight def start(self): self.device.startActivity(component=componentName) def getView(self,str,ContentDescription=False): self.vc.dump() if not contentDescription: return self.vc.getViewWithText(str) else: return self.vc.findViewWithContentDescription(str) def isReady(self): while True: view=self.getView('Contact list is being updated to reflect the change of language.') if not view: break sleep(2) return True def isEmpty(self): view=self.getView('Create a new contact') if view: view.touch() view=self.getView('Keep local') if view: view.touch() return True else: return True else: view=self.getView('Add Contact',True) view.touch() return True def snapshot(self,title): snapName = title + '.png' snapFile = logPath + '\\' + snapName result = self.device.takeSnapshot().getSubImage(self.snap_rect) result.writeToFile(snapFile,'png') def addContact(self): trace('start...') self.start() sleep(3) trace('take snapshot') self.snapshot('contact_snap') def editDetails(self): pass def search(self): pass def sort(self): pass def favorite(self): pass
class ApkTestRunner(object): def __init__(self, config): self.config = config self.logger = logging.getLogger(self.config['name']) self.logger.setLevel(logging.INFO) if self.config.get('verbose') and self.config['verbose']: self.logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) self.logger.addHandler(ch) self.config['output'] = os.getenv("OUTPUT", "./output/%s" % config['name']) if os.path.exists(self.config['output']): suffix = datetime.datetime.now().strftime('%Y%m%d%H%M%S') shutil.move(self.config['output'], '%s-%s' % (self.config['output'], suffix)) os.makedirs(self.config['output']) self.results = [] serialno = os.getenv('ANDROID_SERIAL') if serialno is None: serialno = '.*' kwargs1 = { 'serialno': serialno, 'verbose': True, 'ignoresecuredevice': False} self.logger.debug('VC kwargs1: %s' % kwargs1) self.device, self.serialno = ViewClient.connectToDeviceOrExit(**kwargs1) kwargs2 = { 'startviewserver': True, 'forceviewserveruse': False, 'autodump': False, 'ignoreuiautomatorkilled': True, 'compresseddump': False} self.logger.debug('VC kwargs2: %s' % kwargs2) self.vc = ViewClient(self.device, self.serialno, **kwargs2) def run(self): self.validate() for i in range(1, self.config['loops'] + 1): try: self.logger.info('Running iteration [%s/%s]' % (i, self.config['loops'])) self.config['itr'] = i self.logger.info('Test config: %s' % self.config) self.setUp() self.execute() self.parseResult() self.take_screencap() self.tearDown() except Exception as e: self.take_screencap() self.report_result(self.config['name'], 'fail') self.logger.error(e, exc_info=True) sys.exit(1) self.collect_log() self.result_post_processing() def report_result(self, name, result, score=None, units=None): if score is not None: score = float(score) if units is not None: units = str(units) tc_name = str(name) if self.config['loops'] > 1 and self.config['itr'] != 'stats': tc_name = '%s-itr%s' % (name, self.config['itr']) result_string = '%s %s %s %s' % (tc_name, result, score, units) if score is None: result_string = '%s %s' % (tc_name, result) if score is not None and units is None: result_string = '%s %s %s' % (tc_name, result, score) self.logger.info('TestResult: %s' % result_string) with open('%s/result.txt' % self.config['output'], 'a') as f: f.write('%s\n' % result_string) # Save result to results for post processing. result = {'itr': self.config['itr'], 'test_case_id': str(name), 'result': str(result), 'measurement': score, 'units': units} self.results.append(result) def statistics_result(self): if self.config['loops'] == 1: return self.config['itr'] = 'stats' tc_list = [] for result in self.results: if result['measurement'] is not None: tc_list.append(result['test_case_id']) tc_list = set(tc_list) for tc in tc_list: ms_list = [] for result in self.results: if result['test_case_id'] == tc: ms_list.append(result['measurement']) units = '' for result in self.results: if result['test_case_id'] == tc: units = result['units'] break # Calculate and report population standard deviation and standard error. mean = sum(ms_list) / len(ms_list) variance = sum([(e - mean) ** 2 for e in ms_list]) / len(ms_list) pstdev = math.sqrt(variance) pstderr = pstdev / math.sqrt(len(ms_list)) self.report_result('%s-min' % tc, 'pass', min(ms_list), units) self.report_result('%s-max' % tc, 'pass', max(ms_list), units) self.report_result('%s-mean' % tc, 'pass', mean, units) self.report_result('%s-sigma' % tc, 'pass', pstdev, units) self.report_result('%s-stderr' % tc, 'pass', pstderr, units) def result_post_processing(self): self.statistics_result() # Save results to output/name/name-result.csv. fieldnames = ['itr', 'test_case_id', 'result', 'measurement', 'units'] with open('%s/result.csv' % self.config['output'], 'w') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() for result in self.results: writer.writerow(result) self.logger.info('Result saved to %s/result.csv' % self.config['output']) # Save results to output/name/name-result.json with open('%s/result.json' % self.config['output'], 'w') as f: json.dump([self.results], f, indent=4) self.logger.info('Result saved to %s/result.json' % self.config['output']) def dump_always(self): success = False while not success: try: time.sleep(5) self.vc.dump() success = True except RuntimeError: print("Got RuntimeError when call vc.dump()") time.sleep(5) except ValueError: print("Got ValueError when call vc.dump()") time.sleep(5) def call_adb(self, args): self.logger.debug("calling") self.logger.debug("adb %s" % args) try: # Need to set shell=True to save output to host directly. subprocess.check_call("adb %s" % args, shell=True) except (OSError, subprocess.CalledProcessError) as e: print(e) sys.exit(1) def validate(self): if self.config['apk_file_name'] is None: self.logger.error("APK file name not set") sys.exit(1) if self.config['apk_package'] is None: self.logger.error("APK package name not set") sys.exit(1) if self.config['activity'] is None: self.logger.error("Activity name not set") sys.exit(1) def download_apk(self, apk_name): # download APK if not already downloaded apk_path = os.path.join(os.path.abspath(self.config['apk_dir']), apk_name) if not os.path.isfile(apk_path): # create directory for downloaded files if not os.path.exists(os.path.dirname(apk_path)): os.makedirs(os.path.dirname(apk_path)) if self.config['base_url'].startswith("scp://"): # like scp://user@host:/abs_path base_url = self.config['base_url'] remote_dir = base_url.split(":")[2] user_host = base_url.split(":")[1].replace("/", "") host = user_host.split("@")[1] user = user_host.split("@")[0] remote_path = "%s/%s" % (remote_dir, apk_name) scp_cmdline = "scp %s@%s:%s %s" % (user, host, remote_path, apk_path) ret = os.system(scp_cmdline) if ret != 0: self.logger.info('Failed to run command: %s' % scp_cmdline) sys.exit(1) else: apk_url = urlparse.urljoin(self.config['base_url'], apk_name) self.logger.info('Start downloading file: %s' % apk_url) r = requests.get(apk_url, stream=True) if r.status_code == 200: with open(apk_path, 'wb') as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f) else: self.logger.info('Failed to download file: %s' % apk_url) sys.exit(1) else: self.logger.info('APK file already exists: %s' % apk_name) def install_apk(self, apk_name): apk_path = os.path.join(os.path.abspath(self.config['apk_dir']), apk_name) self.logger.info('Installing %s' % os.path.basename(apk_path)) self.call_adb("install %s" % apk_path) def uninstall_apk(self, package): install_packages = subprocess.check_output(['adb', 'shell', 'pm', 'list', 'packages']) if package in install_packages: self.logger.info('Stopping %s' % package) self.call_adb("shell am force-stop %s" % package) self.logger.info('Uninstalling %s' % package) self.call_adb("shell pm uninstall %s" % package) def take_screencap(self): screencap_file = '/data/local/tmp/%s-itr%s.png' % (self.config['name'], self.config['itr']) self.call_adb('shell screencap %s' % screencap_file) self.logger.info('Pulling %s to output directory...' % screencap_file) self.call_adb('pull %s %s' % (screencap_file, self.config['output'])) def collect_log(self): self.logger.info("Saving logcat.log, logcat-events.log and dmesg.log to output directory...") self.call_adb('logcat -d -v time > %s/logcat.log' % self.config['output']) self.call_adb('logcat -d -b events -v time > %s/logcat-events.log' % self.config['output']) self.call_adb('shell dmesg > %s/dmesg.log' % self.config['output']) def set_performance_governor(self, target_governor="performance"): f_scaling_governor = ('/sys/devices/system/cpu/' 'cpu0/cpufreq/scaling_governor') f_governor_backup = '/data/local/tmp/scaling_governor' dir_sys_cpu = '/sys/devices/system/cpu/' self.call_adb('shell "cat %s>%s"' % (f_scaling_governor, f_governor_backup)) f_cpus_remote = '/data/local/tmp/cpus.txt' self.call_adb('shell "ls -d %s/cpu[0-9]* >%s"' % (dir_sys_cpu, f_cpus_remote)) f_cpus_local = os.path.join(os.path.abspath(self.config['output']), 'cpus.txt') self.call_adb('pull %s %s' % (f_cpus_remote, f_cpus_local)) with open(f_cpus_local, 'r') as f: for cpu in f.readlines(): self.call_adb('shell "echo %s>%s/cpufreq/' 'scaling_governor"' % (target_governor, cpu.strip())) def set_back_governor(self): dir_sys_cpu = '/sys/devices/system/cpu/' f_governor_backup = '/data/local/tmp/scaling_governor' f_governor_local = os.path.join(os.path.abspath(self.config['output']), 'scaling_governor') self.call_adb('pull %s %s' % (f_governor_backup, f_governor_local)) with open(f_governor_local, 'r') as f: contents = f.readlines() if len(contents) > 0: gov_policy = contents[0].strip() self.set_performance_governor(target_governor=gov_policy) def setUp(self): # set to peformance governor policay self.set_performance_governor() # Install APK. self.download_apk(self.config['apk_file_name']) self.uninstall_apk(self.config['apk_package']) self.install_apk(self.config['apk_file_name']) # Clear logcat buffer. self.call_adb("logcat -c") self.call_adb("logcat -b events -c") time.sleep(3) # Start intent. self.logger.info('Starting %s' % self.config['apk_package']) self.call_adb("shell am start -W -S %s" % self.config['activity']) time.sleep(5) def execute(self): raise NotImplementedError def parseResult(self): raise NotImplementedError def tearDown(self): self.uninstall_apk(self.config['apk_package']) self.set_back_governor()
import re import sys import os import time from subprocess import call from com.dtmilano.android.viewclient import ViewClient, ViewNotFoundException kwargs1 = {'verbose': False, 'ignoresecuredevice': False} device, serialno = ViewClient.connectToDeviceOrExit(**kwargs1) kwargs2 = {'startviewserver': True, 'forceviewserveruse': False, 'autodump': False, 'ignoreuiautomatorkilled': True, 'compresseddump': False} vc = ViewClient(device, serialno, **kwargs2) time.sleep(2) vc.dump() btn_license = vc.findViewWithText(u'I Agree') if btn_license: btn_license.touch() while True: try: time.sleep(5) vc.dump() btn_start_on = vc.findViewByIdOrRaise("com.eembc.andebench:id/s1_runall") btn_start_on.touch() break except ViewNotFoundException: pass except RuntimeError: pass except ValueError:
device, serialno = ViewClient.connectToDeviceOrExit() DEBUG = True FLAG_ACTIVITY_NEW_TASK = 0x10000000 # We are not using Settings as the bug describes because there's no WiFi dialog in emulator componentName = 'com.android.settings/.Settings' device.startActivity(component=componentName, flags=FLAG_ACTIVITY_NEW_TASK) MonkeyRunner.sleep(3) vc = ViewClient(device=device, serialno=serialno) if DEBUG: vc.traverse(transform=ViewClient.TRAVERSE_CIT) sound = vc.findViewWithText('Sound') if sound: sound.touch() vc.dump() phoneRingtone = vc.findViewWithText('Phone ringtone') if phoneRingtone: phoneRingtone.touch() vc.dump() vespa = vc.findViewWithText('Vespa') if vespa: vespa.touch() MonkeyRunner.sleep(1) ok = vc.findViewById('id/button1') if ok: ok.touch() vc.dump() vespa = vc.findViewWithText('Vespa') # If for some reason the dialog is still there we will have Vespa and OK ok = vc.findViewById('id/button1')
#! /usr/bin/env python ''' Copyright (C) 2014 Diego Torres Milano Created on Apr 24, 2014 @author: diego ''' from com.dtmilano.android.viewclient import ViewClient kwargs1 = {'verbose': True, 'ignoresecuredevice': True} kwargs2 = {'startviewserver': True, 'forceviewserveruse': True, 'autodump': False, 'ignoreuiautomatorkilled': True} vc = ViewClient(*ViewClient.connectToDeviceOrExit(**kwargs1), **kwargs2) windows = vc.list() for wId in windows.keys(): print ">>> window=", wId, windows[wId] vc.dump(window=wId) vc.traverse(transform=ViewClient.TRAVERSE_CIT, indent=" ")
# We are not using Settings as the bug describes because there's no WiFi dialog in emulator #componentName = 'com.android.settings/.Settings' componentName = 'com.dtmilano.android.sampleui/.MainActivity' device.startActivity(component=componentName, flags=FLAG_ACTIVITY_NEW_TASK) ViewClient.sleep(3) # Set it to True or False to decide if AndroidViewClient or plain monkeyrunner is used USE_AVC = True if USE_AVC: # AndroidViewClient vc = ViewClient(device=device, serialno=serialno) showDialogButton = vc.findViewById('id/show_dialog_button') if showDialogButton: showDialogButton.touch() vc.dump() vc.findViewById('id/0x123456').type('Donald') ok = vc.findViewWithText('OK') if ok: # 09-08 20:17:47.860: D/MonkeyStub(2033): translateCommand: tap 265 518 ok.touch() vc.dump() hello = vc.findViewById('id/hello') if hello: if hello.getText() == "Hello Donald": print "OK" else: print "FAIL" else: print >> sys.stderr, "'hello' not found" else:
class action(object): def __init__(self,device,feature,devID='emulator-5554'): ''' constructor @type device: MonkeyDevice @param device: The device or emulator connected @type feature: str @param feature: feature name, use to mark in trace log @type devID: str @param serialno: the serial number of the device or emulator to connect to ''' self.device = device self.feature = feature #use below code to remove the status bar from the snapshot width = int(device.getProperty('display.width')) height = int(device.getProperty('display.height')) density = device.getProperty('display.density') if density == u'.75': statusBarHeight = 19 elif density == u'1.5': statusBarHeight = 38 elif density == u'2.0': statusBarHeight = 50 else: statusBarHeight = 25 self.snap_rect = 0, statusBarHeight, width, height - statusBarHeight #define the point coordinate used to slide screen self.left = (width/4, height/2) self.right = (width/4*3, height/2) self.up = (width/2, height/4) self.down = (width/2, height/4*3) self.center = (width/2, height/2) self.trace('Before instance') self.vc=ViewClient(device, devID) self.trace('After instance') def trace(self,str): ''' trace @type str: str @param str: specified trace info ''' mTrace('[%s]:%s'%(self.feature,str)) def sleep(self,duration=1): ''' Monkey sleep @type duration: int @param duration: how long to sleep ''' MonkeyRunner.sleep(duration) def menu(self): ''' press menu ''' self.device.press('KEYCODE_MENU','DOWN_AND_UP') self.trace('Press menu') self.sleep(3) def scroll(self,times=1,down=True): ''' scoll up or down for some times then touch the highlight submenu item @type down: boolead @param down: scroll down if True or scroll up @type times: int @param times: how many times to scroll ''' keycode = 'KEYCODE_DPAD_DOWN' if down else 'KEYCODE_DPAD_UP' for i in range(times): self.device.press(keycode,'DOWN_AND_UP') self.trace('Scroll %s' % keycode.split('_')[-1].lower()) self.device.press('KEYCODE_ENTER','DOWN_AND_UP') self.trace('Press Enter') self.sleep(2) def back(self): ''' press back ''' self.device.press('KEYCODE_BACK','DOWN_AND_UP') self.trace('Press back') def startComponent(self,componentName): ''' start activity @type componentName: str @param componentName: component name ''' self.device.startActivity(component=componentName) self.trace('Start component: %s' % componentName) self.sleep(2) def stopPackage(self,package): ''' stop activity @type package: str @param package: package name ''' self.device.shell('am force-stop %s' % package) self.trace('Force stop contacts package %s' % package) def type(self,str): ''' type @type str: str @param str: strings to type ''' self.device.type(str) self.trace('Type %s' % str) def slide(self,str,view=None): ''' slide the screen @type: str @param: 'left','right','up','down' @type view: view @param view: specify the view, default to None ''' if str not in ['left','right','up','down']: raise SyntaxError("Wrong Parameter: choose from 'left','right','up' or 'down'") try: cX = view.getX() cY = view.getY() width = view.getWidth() height = view.getHeight() cL = cX + width/4, cY + height/2 cR = cX + width/4*3, cY + height/2 cU = cX + width/2, cY + height/4 cD = cX + width/2, cY + height/4*3 except AttributeError: pass (left, right, up, down) = (cL, cR, cU, cD) if view else (self.left, self.right, self.up, self.down) nav = { 'left':{'start':right,'end':left}, 'right':{'start':left,'end':right}, 'up':{'start':down,'end':up}, 'down':{'start':up,'end':down} } self.device.drag(nav[str]['start'], nav[str]['end'], 0.1, 10) self.trace('Slide the screen from %s to %s ' % (nav[str]['start'],nav[str]['end'])) self.sleep(2) def getView(self,str,cD=False,iD=False,dump=True,regex=False): ''' get the view with the specified text, content description or viewId @type str: str @param str: the query string @type cD: boolean @param cD: whether handle the query str as content description @type iD: boolean @param iD: whether handle the query str as viewId @type dump: boolean @param dump: whether execute dump before findView, depending on whether the screen is changed @return: the view found ''' if dump: if DEBUG: self.trace('Before dump') self.vc.dump() if DEBUG: self.trace('After dump') if cD: view=self.vc.findViewWithContentDescription(str) self.trace('Query view with content description: %s, return is %s' % (str, view is not None)) return view elif iD: view=self.vc.findViewById(str) self.trace('Query view by id: %s, return is %s' % (str, view is not None)) return view elif regex: view=self.vc.findViewWithAttributeThatMatches('text',re.compile(str)) self.trace('Query view that match attribute: %s, return is %s' % (str, view is not None)) return view else: view=self.vc.findViewWithText(str) self.trace('Query view with text: %s, return is %s ' % (str, view is not None)) return view def touch(self,view): ''' touch the specified view @type view: view @param view: specified view @return: True ''' x = view.getX() y = view.getY() w = view.getWidth() h = view.getHeight() self.device.touch(x + w/2, y + h/2,'DWON_AND_UP') self.trace('Touch (%d,%d)' % (x + w/2, y + h/2)) self.sleep(3) return True def snapshot(self,title): ''' take snapshot @type title: str @param title: specify the title of snapshot @return: snapshot object ''' snapName = title + '_' + snapTime() + '.png' snapFolder = 'snapshot' os.system('if not exist %s\\%s mkdir %s\\%s' % (logPath, snapFolder, logPath, snapFolder)) snapFile = logPath + '\\' + snapFolder + '\\' + snapName result = self.device.takeSnapshot().getSubImage(self.snap_rect) self.trace('Take snapshot without the statusbar') result.writeToFile(snapFile,'png') self.trace('Save snapshot to file: %s ' % snapFile) return result def wipe(self,view): ''' wipe the text in specified view @type view: view @param view: specified view ''' try: self.device.drag(view.getXY(),view.getXY(),1,1) self.trace('Wipe text: %s' % str(view.getText())) self.device.press('KEYCODE_DEL','DOWN_AND_UP') except: Exception('Wipe failed')
def Network(): try: from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithText("MAI TEST"): vc.dump() if vc.findViewById("android:id/button1"): vc.dump() time.sleep(1) vc.findViewById("android:id/button1").touch() vc.dump() print("clicked") else: time.sleep(15) else: print"" check() if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): print("4g") os.system("adb shell cmd statusbar collapse") refresh() elif String==str("3G") or combine==str("No signal") or sets==str("4G No signal"): print("3g") time.sleep(1) cdir=os.getcwd() adir=str(glob.glob(cdir + "/" + "logcat.txt")) cut=adir.split("/") before=cut[-1] final=before.replace("']", "") if final=="logcat.txt": print("Log file found Removing now.....") os.remove(final) else: print("No log file found...........") time.sleep(1) os.system("adb shell cmd statusbar collapse") for i in range(4): from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithText("Settings"): vc.dump() vc.findViewWithText("Settings").touch() vc.dump() vc.findViewWithText("Wireless & networks").touch() vc.dump() vc.findViewWithText("Mobile network").touch() vc.dump() break else: os.system("adb shell input swipe 876 856 102 949 ") time.sleep(1) from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithText("Settings"): vc.dump() vc.findViewWithText("Settings").touch() vc.dump() vc.findViewWithText("Wireless & networks").touch() vc.dump() vc.findViewWithText("Mobile network").touch() vc.dump() break from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) vc.findViewWithText("Carrier").touch() vc.dump() try: if not vc.findViewWithText("Automatic") and not vc.findViewWithText("Disable auto-select"): time.sleep(50) vc.dump() check() os.system("adb shell cmd statusbar collapse") if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): refresh() else: time.sleep(1) if vc.findViewWithText(u"中国联通 4G"): vc.dump() vc.findViewWithText(u"中国联通 4G").touch() time.sleep(8) vc.dump() if not vc.findViewWithText("MAI TEST"): time.sleep(32) vc.dump() if vc.findViewWithText("MAI TEST"): vc.dump() PassRegister() elif vc.findViewWithText("Network registration failed"): vc.dump() FailRegister() elif vc.findViewWithText(u"中国联通 LTE"): vc.dump() vc.findViewWithText(u"中国联通 LTE").touch() time.sleep(8) vc.dump() if not vc.findViewWithText("MAI TEST"): time.sleep(32) vc.dump() if vc.findViewWithText("MAI TEST"): vc.dump() PassRegister() elif vc.findViewWithText("Network registration failed"): vc.dump() FailRegister() else: sheet1.write(j,0,PLMN) sheet1.write(j,1,"FAIL") check() os.system("adb shell cmd statusbar collapse") if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): refresh() else: print("") except: print("An Exception occured......") ############################################## ####################################################### try: if vc.findViewWithText("Automatic"): time.sleep(2) vc.dump() vc.findViewById("android:id/switch_widget").touch() vc.dump() vc.findViewById("android:id/button1").touch() time.sleep(50) vc.dump() check() os.system("adb shell cmd statusbar collapse") if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): refresh() else: time.sleep(1) if vc.findViewWithText(u"中国联通 4G"): vc.dump() vc.findViewWithText(u"中国联通 4G").touch() time.sleep(8) if not vc.findViewWithText("MAI TEST") : time.sleep(32) vc.dump() if vc.findViewWithText("MAI TEST"): vc.dump() PassRegister() elif vc.findViewWithText("Network registration failed"): vc.dump() FailRegister() elif vc.findViewWithText(u"中国联通 LTE"): vc.dump() vc.findViewWithText(u"中国联通 LTE").touch() time.sleep(8) vc.dump() if not vc.findViewWithText("MAI TEST"): vc.dump() time.sleep(32) if vc.findViewWithText("MAI TEST"): vc.dump() PassRegister() elif vc.findViewWithText("Network registration failed"): vc.dump() FailRegister() else: sheet1.write(j,0,PLMN) sheet1.write(j,1,"FAIL") check() os.system("adb shell cmd statusbar collapse") if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): refresh() else: print("") except: print("An Exception occured......") try: if vc.findViewWithText("Disable auto-select"): time.sleep(1) vc.dump() vc.findViewById("android:id/button1").touch() time.sleep(50) vc.dump() check() os.system("adb shell cmd statusbar collapse") if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): refresh() else: time.sleep(1) if vc.findViewWithText(u"中国联通 4G"): vc.dump() vc.findViewWithText(u"中国联通 4G").touch() time.sleep(8) vc.dump() if not vc.findViewWithText("MAI TEST") : time.sleep(32) vc.dump() if vc.findViewWithText("MAI TEST"): vc.dump() PassRegister() elif vc.findViewWithText("Network registration failed"): vc.dump() FailRegister() elif vc.findViewWithText(u"中国联通 LTE"): vc.dump() vc.findViewWithText(u"中国联通 LTE").touch() time.sleep(40) vc.dump() if not vc.findViewWithText("MAI TEST"): time.sleep(32) vc.dump() if vc.findViewWithText("MAI TEST"): vc.dump() PassRegister() elif vc.findViewWithText("Network registration failed"): vc.dump() FailRegister() else: sheet1.write(j,0,PLMN) sheet1.write(j,1,"FAIL") check() os.system("adb shell cmd statusbar collapse") if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): refresh() else: print("") except: print("An Exception occured......") except: print("An Exception occured......")
def FailRegister(): try: from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) vc.findViewById("android:id/button1").touch() vc.dump() os.system("adb shell input keyevent KEYCODE_HOME") time.sleep(2) os.system("adb shell pm clear com.android.phone") time.sleep(1) print(sendCommand("AT+CFUN=0")) time.sleep(3) print(sendCommand("AT+CFUN=1")) time.sleep(3) print(sendCommand("AT+CFUN=1,1")) time.sleep(45) from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithText("MAI TEST"): vc.dump() if vc.findViewById("android:id/button1"): vc.dump() time.sleep(1) vc.findViewById("android:id/button1").touch() vc.dump() print("clicked") check() if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): os.system("adb shell cmd statusbar collapse") refresh() else: print("") else: for i in range(4): from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithText("Settings"): vc.dump() vc.findViewWithText("Settings").touch() vc.dump() vc.findViewWithText("Wireless & networks").touch() vc.dump() vc.findViewWithText("Mobile network").touch() vc.dump() break else: os.system("adb shell input swipe 876 856 102 949 ") time.sleep(1) from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithText("Settings"): vc.dump() vc.findViewWithText("Settings").touch() vc.dump() vc.findViewWithText("Wireless & networks").touch() vc.dump() vc.findViewWithText("Mobile network").touch() vc.dump() break from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) vc.findViewWithText("Carrier").touch() time.sleep(2) vc.dump() vc.findViewById("android:id/switch_widget").touch() vc.dump() vc.findViewById("android:id/button1").touch() time.sleep(50) vc.dump() check() if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): os.system("adb shell cmd statusbar collapse") refresh() else: os.system("adb shell cmd statusbar collapse") time.sleep(1) if vc.findViewWithText(u"中国联通 4G"): vc.dump() vc.findViewWithText(u"中国联通 4G").touch() time.sleep(2) vc.dump() if vc.findViewWithText("Network registration failed"): vc.dump() vc.findViewById("android:id/button1").touch() vc.dump() sheet1.write(j,0,PLMN) sheet1.write(j,1,"FAIL") time.sleep(1) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"Registration.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"Registration.png "+fin+PLMN+"Registration.png" ) time.sleep(1) elif vc.findViewWithText("MAI TEST"): vc.dump() vc.findViewById("android:id/button1").touch() vc.dump() refresh() elif vc.findViewWithText(u"中国联通 LTE"): vc.dump() vc.findViewWithText(u"中国联通 LTE").touch() time.sleep(2) vc.dump() if vc.findViewWithText("Network registration failed"): vc.dump() vc.findViewById("android:id/button1").touch() vc.dump() sheet1.write(j,0,PLMN) sheet1.write(j,1,"FAIL") time.sleep(1) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"Registration.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"Registration.png "+fin+PLMN+"Registration.png" ) time.sleep(1) elif vc.findViewWithText("MAI TEST"): vc.dump() vc.findViewById("android:id/button1").touch() vc.dump() refresh() except: print("Found an exception......")
class contacts: ''' contacts class ''' def __init__(self, device, devID='emulator-5554',sample = False): ''' constructor @type device: MonkeyDevice @param device: The device or emulator connected @type devID: str @param serialno: the serial number of the device or emulator to connect to @type sample: boolean @param sample: whether take snapshot as an sampling ''' self.device=device self.sample=sample self.startStatus=False '''the status which indicate whether the contacts activity is started''' self.vc=ViewClient(device, devID) #use below code to remove the status bar from the snapshot width = int(device.getProperty('display.width')) height = int(device.getProperty('display.height')) density = device.getProperty('display.density') if density == .75: statusBarHeight = 19 elif density == 1.5: statusBarHeight = 38 elif density == 2.0: statusBarHeight = 50 else: statusBarHeight = 25 self.snap_rect = 0, statusBarHeight, width, height - statusBarHeight def start(self): ''' start the contacts activity and set the startStatus True if contacts is ready. ''' self.device.startActivity(component=componentName) sleep(3) self.startStatus = self.isReady() def back(self): ''' press back ''' self.device.press('KEYCODE_BACK','DOWN_AND_UP') def getView(self,str,cD=False,iD=False): ''' get the view with the specified text, content description or viewId @type str: str @param str: the query string @type cD: boolean @param cD: whether handle the query str as content description @type iD: boolean @param iD: whether handle the query str as viewId @return: the view found ''' self.vc.dump() sleep(3) if not cD: if not iD: return self.vc.findViewWithText(str) else: return self.vc.findViewById(str) else: return self.vc.findViewWithContentDescription(str) def isReady(self): ''' check whether the contacts is ready. ''' while True: view=self.getView('Contact list is being updated to reflect the change of language.') if not view: trace('Contacts is ready') break else: trace('Contacts is not ready, please wait!') sleep(2) return True def goEdit(self): ''' check whether the contact is empty, then select adding and go to edit view. @return: True ''' self.check() view=self.getView('Create a new contact') if view: view.touch() trace('Click "Create a new contact"') view=self.getView('Keep local') if view: view.touch() trace('Select "Keep local"') else: view=self.getView('Add Contact',True) view.touch() trace('Click "Add Contact"') return True def check(self): ''' check whether the contacts is started before other operation about contacts @return: True ''' if not self.status: trace("Wrong code! please start contacts firstly in you code") raise SyntaxError('contacts should be start firstly!') return True def snapshot(self,title): ''' take snapshot @type title: str @param title: specify the title of snapshot ''' snapName = title + '.png' snapFile = logPath + '\\' + snapName result = self.device.takeSnapshot().getSubImage(self.snap_rect) result.writeToFile(snapFile,'png') def addContact(self,name='',phone='',email=''): #notice firstly call self.goEdit() pass def editDetails(self,phone=''): pass def search(self,str): ''' @type str: str @param str: specify the search keyword ##@return: the view of search result if search result is not null, else return None ''' trace("start searching...") trace("check contact main UI, dump, please wait...") self.vc.dump() while not self.getView("Search",True): self.device.press('KEYCODE_BACK') sleep(2) self.vc.dump() searchView=self.getView("Search",True) searchView.touch() self.device.type(str) trace("search keyword is: "+str) self.snapshot("search_result") ''' tmp=[] self.vc.dump() trace("dump, please wait...") #the id of 1st search result is always 28 for i in self.vc.findViewsContainingPoint((100,200)): tmp.append(i.getId()) result=int(tmp[len(tmp)-1][-2:]) if(result<28): trace("search result: nothing") return None else: self.snapshot("search_result") return self.vc.findViewById(tmp[len(tmp)-1]) ''' def sortAs(self, sortByFirstName=True): ''' sort contact name @type sortByFirstName: boolean @param sortByFirstName: whether sort contact name by first name ''' trace("check contact main UI, dump, please wait...") self.vc.dump() while not self.getView("Search",True): self.device.press('KEYCODE_BACK') sleep(2) self.vc.dump() trace("start sorting...") self.device.press("KEYCODE_MENU","DOWN_AND_UP") trace("click menu, dump, please wait...") self.vc.dump() settingsView=self.getView("Settings") settingsView.touch() sleep(2) trace("click Settings, dump, please wait...") self.vc.dump() self.vc.findViewWithTextOrRaise("Sort list by").touch() trace("click Sort list by, dump, please wait...") self.vc.dump() if sortByFirstName: self.vc.findViewWithTextOrRaise("First name").touch() else: self.vc.findViewWithTextOrRaise("Last name").touch() sleep(2) #conflict with check at the begining #self.device.press("KEYCODE_BACK","DOWN_AND_UP") #sleep(2) def viewAs(self, viewAsFirstNameFirst=True): ''' view contact name @type viewAsFirstNameFirst: boolean @param viewAsFirstNameFirst: whether view contact by first name first ''' trace("check contact main UI, dump, please wait...") self.vc.dump() while not self.getView("Search",True): self.device.press('KEYCODE_BACK') sleep(2) self.vc.dump() trace("start viewing...") self.device.press("KEYCODE_MENU","DOWN_AND_UP") trace("click menu, dump, please wait...") self.vc.dump() settingsView=self.getView("Settings") settingsView.touch() sleep(2) trace("click Settings, dump, please wait...") self.vc.dump() self.vc.findViewWithTextOrRaise("View contact names as").touch() trace("click View contact names as, dump, please wait...") self.vc.dump() if viewAsFirstNameFirst: self.vc.findViewWithTextOrRaise("First name first").touch() else: self.vc.findViewWithTextOrRaise("Last name first").touch() sleep(2) #conflict with check at the begining #self.device.press("KEYCODE_BACK","DOWN_AND_UP") #sleep(2) def favorite(self,name=''): pass
class ApkTestRunner(object): def __init__(self, config): self.config = config self.logger = logging.getLogger(self.config['name']) self.logger.setLevel(logging.INFO) if self.config.get('verbose') and self.config['verbose']: self.logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) self.logger.addHandler(ch) self.config['output'] = os.getenv("OUTPUT", "./output/%s" % config['name']) if os.path.exists(self.config['output']): suffix = datetime.datetime.now().strftime('%Y%m%d%H%M%S') shutil.move(self.config['output'], '%s-%s' % (self.config['output'], suffix)) os.makedirs(self.config['output']) self.results = [] serialno = os.getenv('ANDROID_SERIAL') if serialno is None: serialno = '.*' kwargs1 = { 'serialno': serialno, 'verbose': True, 'ignoresecuredevice': False } self.logger.debug('VC kwargs1: %s' % kwargs1) self.device, self.serialno = ViewClient.connectToDeviceOrExit( **kwargs1) kwargs2 = { 'startviewserver': True, 'forceviewserveruse': False, 'autodump': False, 'ignoreuiautomatorkilled': True, 'compresseddump': False } self.logger.debug('VC kwargs2: %s' % kwargs2) self.vc = ViewClient(self.device, self.serialno, **kwargs2) def run(self): self.validate() for i in range(1, self.config['loops'] + 1): try: self.logger.info('Running iteration [%s/%s]' % (i, self.config['loops'])) self.config['itr'] = i self.logger.info('Test config: %s' % self.config) self.setUp() self.execute() self.parseResult() self.take_screencap() self.tearDown() except Exception as e: self.take_screencap() self.report_result(self.config['name'], 'fail') self.logger.error(e, exc_info=True) sys.exit(1) self.collect_log() self.result_post_processing() def report_result(self, name, result, score=None, units=None): if score is not None: score = float(score) if units is not None: units = str(units) tc_name = str(name) if self.config['loops'] > 1 and self.config['itr'] != 'stats': tc_name = '%s-itr%s' % (name, self.config['itr']) result_string = '%s %s %s %s' % (tc_name, result, score, units) if score is None: result_string = '%s %s' % (tc_name, result) if score is not None and units is None: result_string = '%s %s %s' % (tc_name, result, score) self.logger.info('TestResult: %s' % result_string) with open('%s/result.txt' % self.config['output'], 'a') as f: f.write('%s\n' % result_string) # Save result to results for post processing. result = { 'itr': self.config['itr'], 'test_case_id': str(name), 'result': str(result), 'measurement': score, 'units': units } self.results.append(result) def statistics_result(self): if self.config['loops'] == 1: return self.config['itr'] = 'stats' tc_list = [] for result in self.results: if result['measurement'] is not None: tc_list.append(result['test_case_id']) tc_list = set(tc_list) for tc in tc_list: ms_list = [] for result in self.results: if result['test_case_id'] == tc: ms_list.append(result['measurement']) units = '' for result in self.results: if result['test_case_id'] == tc: units = result['units'] break # Calculate and report population standard deviation and standard error. mean = sum(ms_list) / len(ms_list) variance = sum([(e - mean)**2 for e in ms_list]) / len(ms_list) pstdev = math.sqrt(variance) pstderr = pstdev / math.sqrt(len(ms_list)) self.report_result('%s-min' % tc, 'pass', min(ms_list), units) self.report_result('%s-max' % tc, 'pass', max(ms_list), units) self.report_result('%s-mean' % tc, 'pass', mean, units) self.report_result('%s-sigma' % tc, 'pass', pstdev, units) self.report_result('%s-stderr' % tc, 'pass', pstderr, units) def result_post_processing(self): self.statistics_result() # Save results to output/name/name-result.csv. fieldnames = ['itr', 'test_case_id', 'result', 'measurement', 'units'] with open('%s/result.csv' % self.config['output'], 'w') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() for result in self.results: writer.writerow(result) self.logger.info('Result saved to %s/result.csv' % self.config['output']) # Save results to output/name/name-result.json with open('%s/result.json' % self.config['output'], 'w') as f: json.dump([self.results], f, indent=4) self.logger.info('Result saved to %s/result.json' % self.config['output']) def dump_always(self): success = False while not success: try: time.sleep(5) self.vc.dump() success = True except RuntimeError: print("Got RuntimeError when call vc.dump()") time.sleep(5) except ValueError: print("Got ValueError when call vc.dump()") time.sleep(5) def call_adb(self, args): self.logger.debug("calling") self.logger.debug("adb %s" % args) try: # Need to set shell=True to save output to host directly. subprocess.check_call("adb %s" % args, shell=True) except (OSError, subprocess.CalledProcessError) as e: print(e) sys.exit(1) def validate(self): if self.config['apk_file_name'] is None: self.logger.error("APK file name not set") sys.exit(1) if self.config['apk_package'] is None: self.logger.error("APK package name not set") sys.exit(1) if self.config['activity'] is None: self.logger.error("Activity name not set") sys.exit(1) def download_apk(self, apk_name): # download APK if not already downloaded apk_path = os.path.join(os.path.abspath(self.config['apk_dir']), apk_name) if not os.path.isfile(apk_path): # create directory for downloaded files if not os.path.exists(os.path.dirname(apk_path)): os.makedirs(os.path.dirname(apk_path)) if self.config['base_url'].startswith("scp://"): # like scp://user@host:/abs_path base_url = self.config['base_url'] remote_dir = base_url.split(":")[2] user_host = base_url.split(":")[1].replace("/", "") host = user_host.split("@")[1] user = user_host.split("@")[0] remote_path = "%s/%s" % (remote_dir, apk_name) scp_cmdline = "scp %s@%s:%s %s" % (user, host, remote_path, apk_path) ret = os.system(scp_cmdline) if ret != 0: self.logger.info('Failed to run command: %s' % scp_cmdline) sys.exit(1) else: apk_url = urlparse.urljoin(self.config['base_url'], apk_name) self.logger.info('Start downloading file: %s' % apk_url) r = requests.get(apk_url, stream=True) if r.status_code == 200: with open(apk_path, 'wb') as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f) else: self.logger.info('Failed to download file: %s' % apk_url) sys.exit(1) else: self.logger.info('APK file already exists: %s' % apk_name) def install_apk(self, apk_name, serial_num): apk_path = os.path.join(os.path.abspath(self.config['apk_dir']), apk_name) self.logger.info('Installing %s' % os.path.basename(apk_path)) self.call_adb("-s %s install %s" % serial_num % apk_path) def uninstall_apk(self, package): install_packages = subprocess.check_output( ['adb', 'shell', 'pm', 'list', 'packages']) if package in install_packages: self.logger.info('Stopping %s' % package) self.call_adb("shell am force-stop %s" % package) self.logger.info('Uninstalling %s' % package) self.call_adb("shell pm uninstall %s" % package) def take_screencap(self): screencap_file = '/data/local/tmp/%s-itr%s.png' % (self.config['name'], self.config['itr']) self.call_adb('shell screencap %s' % screencap_file) self.logger.info('Pulling %s to output directory...' % screencap_file) self.call_adb('pull %s %s' % (screencap_file, self.config['output'])) def collect_log(self): self.logger.info( "Saving logcat.log, logcat-events.log and dmesg.log to output directory..." ) self.call_adb('logcat -d -v time > %s/logcat.log' % self.config['output']) self.call_adb('logcat -d -b events -v time > %s/logcat-events.log' % self.config['output']) self.call_adb('shell dmesg > %s/dmesg.log' % self.config['output']) def set_performance_governor(self, target_governor="performance"): f_scaling_governor = ('/sys/devices/system/cpu/' 'cpu0/cpufreq/scaling_governor') f_governor_backup = '/data/local/tmp/scaling_governor' dir_sys_cpu = '/sys/devices/system/cpu/' self.call_adb('shell "cat %s>%s"' % (f_scaling_governor, f_governor_backup)) f_cpus_remote = '/data/local/tmp/cpus.txt' self.call_adb('shell "ls -d %s/cpu[0-9]* >%s"' % (dir_sys_cpu, f_cpus_remote)) f_cpus_local = os.path.join(os.path.abspath(self.config['output']), 'cpus.txt') self.call_adb('pull %s %s' % (f_cpus_remote, f_cpus_local)) with open(f_cpus_local, 'r') as f: for cpu in f.readlines(): self.call_adb('shell "echo %s>%s/cpufreq/' 'scaling_governor"' % (target_governor, cpu.strip())) def set_back_governor(self): dir_sys_cpu = '/sys/devices/system/cpu/' f_governor_backup = '/data/local/tmp/scaling_governor' f_governor_local = os.path.join(os.path.abspath(self.config['output']), 'scaling_governor') self.call_adb('pull %s %s' % (f_governor_backup, f_governor_local)) with open(f_governor_local, 'r') as f: contents = f.readlines() if len(contents) > 0: gov_policy = contents[0].strip() self.set_performance_governor(target_governor=gov_policy) def setUp(self): # set to peformance governor policay self.set_performance_governor() # Install APK. self.download_apk(self.config['apk_file_name']) self.uninstall_apk(self.config['apk_package']) self.install_apk(self.config['apk_file_name']) # Clear logcat buffer. self.call_adb("logcat -c") self.call_adb("logcat -b events -c") time.sleep(3) # Start intent. self.logger.info('Starting %s' % self.config['apk_package']) self.call_adb("shell am start -W -S %s" % self.config['activity']) time.sleep(5) def execute(self): raise NotImplementedError def parseResult(self): raise NotImplementedError def tearDown(self): self.uninstall_apk(self.config['apk_package']) self.set_back_governor()
import re import sys import os try: sys.path.insert(0, os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src')) except: pass from com.dtmilano.android.viewclient import ViewClient TAG = 'CULEBRA' _s = 5 _v = '--verbose' in sys.argv kwargs1 = {'ignoreversioncheck': False, 'verbose': False, 'ignoresecuredevice': False} device, serialno = ViewClient.connectToDeviceOrExit(**kwargs1) kwargs2 = {'forceviewserveruse': False, 'useuiautomatorhelper': False, 'ignoreuiautomatorkilled': True, 'autodump': False, 'startviewserver': True, 'compresseddump': True} vc = ViewClient(device, serialno, **kwargs2) vc.dump(window=-1) vc.findViewWithContentDescriptionOrRaise(u'''Voice Search''').touch() ViewClient.sayText("The 'poke' button on facebook is awesome...\ But I think there should be a 'stab' button...") vc.sleep(_s) vc.dump(window=-1)
print "launching app..." # set a variable with the package's internal name package = 'com.viber.voip' # set a variable with the name of an Activity in the package activity = '.WelcomeActivity' # set the name of the component to start runComponent = package + '/' + activity # run the component device.startActivity(component=runComponent) vc.dump(window='-1') # find a conversation by a Contact's name com_viber_voip___id_from = vc.findViewWithTextOrRaise(u'Tomi') if com_viber_voip___id_from: # click the view com_viber_voip___id_from.touch() vc.dump() com_viber_voip___id_send_text = vc.findViewByIdOrRaise( "com.viber.voip:id/send_text") if com_viber_voip___id_send_text: com_viber_voip___id_send_text.touch()
import sys import os import time from subprocess import call from com.dtmilano.android.viewclient import ViewClient, ViewNotFoundException parent_dir = os.path.realpath(os.path.dirname(__file__)) f_output_result="%s/../common/output-test-result.sh" % parent_dir kwargs1 = {'verbose': False, 'ignoresecuredevice': False} device, serialno = ViewClient.connectToDeviceOrExit(**kwargs1) kwargs2 = {'startviewserver': True, 'forceviewserveruse': False, 'autodump': False, 'ignoreuiautomatorkilled': True, 'compresseddump': False} vc = ViewClient(device, serialno, **kwargs2) vc.dump(window=-1, sleep=5) btn_jbench = vc.findViewByIdOrRaise("it.JBench.bench:id/button1") btn_jbench.touch() time.sleep(2) finished = False while(not finished): try: time.sleep(5) vc.dump() results = vc.findViewByIdOrRaise("it.JBench.bench:id/textViewResult") if re.search('^\d+$', results.getText()): finished = True print "benchmark finished" print "%s=%s" % ("JBench", results.getText().strip()) call([f_output_result, "JBench", 'pass', results.getText().strip(), "points"])
# set a variable with the package's internal name package = 'com.whatsapp' # set a variable with the name of an Activity in the package activity = '.Main' # set the name of the component to start runComponent = package + '/' + activity # run the component device.startActivity(component=runComponent) logger.info('open application', extra=get_extra_data()) ViewClient.sleep(10) dump = vc.dump() try: for view in dump: if view['resource-id'] == 'android:id/list': listview_unique_id = view.uniqueId() first_conversation_id = get_first_contact_unique_id( listview_unique_id) for v in dump: if v.uniqueId() == first_conversation_id: v.touch() logger.info('click first conversation', extra=get_extra_data()) vc.dump() com_whatsapp___id_input_attach_button = vc.findViewByIdOrRaise(
def Call(): try: cdir=os.getcwd() adir=str(glob.glob(cdir + "/" + "logcat.txt")) cut=adir.split("/") before=cut[-1] global final final=before.replace("']", "") if final=="logcat.txt": print("Log file found Removing now.....") os.remove(final) else: print("No log file found...........") os.system("adb shell pm clear com.android.phone") time.sleep(10) check() time.sleep(1) os.system("adb shell cmd statusbar collapse") time.sleep(1) print("bye") if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): try: Call="adb shell am start -a android.intent.action.CALL -d tel:" + str(ISDN) output=subprocess.Popen(Call,stdout=subprocess.PIPE).communicate()[0] time.sleep(15) os.system("adb logcat -d time >> logcat.txt") time.sleep(4) file=open("logcat.txt", "r") lines= file.read() if "CallState DIALING -> ACTIVE" in lines and "isVolteCall()" in lines: time.sleep(1) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"call.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"call.png "+fin+PLMN+"call.png" ) time.sleep(6) os.system("adb shell input keyevent KEYCODE_ENDCALL") sheet1.write(j,2,"PASS") file.close() elif "CallState DIALING -> DISCONNECTED" in lines: time.sleep(1) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"call.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"call.png "+fin+PLMN+"call.png" ) time.sleep(2) sheet1.write(j,2,"FAIL") #############Write it in excel file.close() elif "CallState DIALING -> DIALING" in lines: time.sleep(3) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"call.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"call.png "+fin+PLMN+"call.png" ) time.sleep(2) os.system("adb shell input keyevent KEYCODE_ENDCALL") sheet1.write(j,2,"FAIL")#############Write it in excel file.close() elif "CallState DIALING -> ACTIVE" in lines: time.sleep(5) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"call.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"call.png "+fin+PLMN+"call.png" ) time.sleep(2) os.system("adb shell input keyevent KEYCODE_ENDCALL") sheet1.write(j,2,"FAIL") file.close() elif "CallState DIALING" not in lines: time.sleep(3) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"call.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"call.png "+fin+PLMN+"call.png" ) time.sleep(2) os.system("adb shell input keyevent KEYCODE_ENDCALL") sheet1.write(j,0,PLMN) sheet1.write(j,2,"FAIL")#############Write it in excel file.close() except: print("Exception while dialing.......") else: sheet1.write(j,2,"FAIL") os.system("adb shell input keyevent KEYCODE_WAKEUP") time.sleep(1) os.system("adb shell pm clear com.android.contacts") time.sleep(1) os.system("adb shell input keyevent KEYCODE_HOME") from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) try: vc.findViewWithContentDescription("Phone").touch() vc.dump() time.sleep(1) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"callog.png") time.sleep(2) os .system("adb pull /sdcard/Automation/"+PLMN+"callog.png"+fin+PLMN+"callog.png") time.sleep(2) ###############TakeScreenshot os.system("adb shell input keyevent KEYCODE_HOME") except: print("Exception occured while finding element") except: print("An Exception occured......")
class contacts: ''' contacts class ''' def __init__(self, device, devID='emulator-5554',sample = False): ''' constructor @type device: MonkeyDevice @param device: The device or emulator connected @type devID: str @param serialno: the serial number of the device or emulator to connect to @type sample: boolean @param sample: whether take snapshot as an sampling ''' self.device=device self.sample=sample self.startStatus=False '''the status which indicate whether the contacts activity is started''' self.vc=ViewClient(device, devID) #use below code to remove the status bar from the snapshot width = int(device.getProperty('display.width')) height = int(device.getProperty('display.height')) density = device.getProperty('display.density') if density == .75: statusBarHeight = 19 elif density == 1.5: statusBarHeight = 38 elif density == 2.0: statusBarHeight = 50 else: statusBarHeight = 25 self.snap_rect = 0, statusBarHeight, width, height - statusBarHeight def start(self): ''' start the contacts activity and set the startStatus True if contacts is ready. ''' self.device.startActivity(component=componentName) sleep(3) self.startStatus = self.isReady() def back(self): ''' press back ''' self.device.press('KEYCODE_BACK','DOWN_AND_UP') def getView(self,str,cD=False,iD=False): ''' get the view with the specified text, content description or viewId @type str: str @param str: the query string @type cD: boolean @param cD: whether handle the query str as content description @type iD: boolean @param iD: whether handle the query str as viewId @return: the view found ''' self.vc.dump() sleep(3) if not cD: if not iD: return self.vc.findViewWithText(str) else: return self.vc.findViewById(str) else: return self.vc.findViewWithContentDescription(str) def isReady(self): ''' check whether the contacts is ready. ''' while True: view=self.getView('Contact list is being updated to reflect the change of language.') if not view: trace('Contacts is ready') break else: trace('Contacts is not ready, please wait!') sleep(2) return True def goEdit(self): ''' check whether the contact is empty, then select adding and go to edit view. @return: True ''' self.check() view=self.getView('Create a new contact') if view: view.touch() trace('Click "Create a new contact"') view=self.getView('Keep local') if view: view.touch() trace('Select "Keep local"') else: view=self.getView('Add Contact',True) view.touch() trace('Click "Add Contact"') return True def check(self): ''' check whether the contacts is started before other operation about contacts @return: True ''' if not self.startStatus: trace("Wrong code! please start contacts firstly in you code") raise SyntaxError('contacts should be start firstly!') return True def snapshot(self,title): ''' take snapshot @type title: str @param title: specify the title of snapshot ''' snapName = title + '.png' snapFile = logPath + '\\' + snapName result = self.device.takeSnapshot().getSubImage(self.snap_rect) result.writeToFile(snapFile,'png') def addContact(self,name='',phone='',email=''): #notice firstly call self.goEdit() pass def editDetails(self,name='',phone='',email='',notes='',address='',nickname=''): ''' edit contact details ''' self.check() view = self.getView('id/no_id/27',iD=True) view.touch() sleep(4) trace('enter contact OK') self.device.press('KEYCODE_MENU','DOWN_AND_UP') view = self.getView('Edit') view.touch() sleep(3) trace('enter contact edit view OK') if not name=='': self.editName(name) if not phone=='': if self.getDetails('Phone'): self.editPhone(phone) else: self.editPhone(phone,add=True) self.back() sleep(3) self.back() def getDetails(self,getItem): if self.getView(getItem): return True else: self.device.drag((240,750),(240,50),5.0) sleep(1) if self.getView(getItem): return True else: return False def editName(self,name): trace("edit contact's name") self.check() #find EditText of Name view = self.getView('id/no_id/27',iD=True) #edit name self.device.drag(view.getXY(),view.getXY(),3.0) self.device.press('KEYCODE_DEL','DOWN_AND_UP') view.type(name) sleep(1) trace("edit contact's name OK") def editPhone(self,phone,add=False): trace("edit contact's phone") self.check() if not add: trace('edit phone with no add') #find EditText of Phone view = self.getView('Phone') editId = 'id/no_id/'+str(int((view.getId())[-2:])+6) view = self.getView(editId,iD=True) #edit phone number self.device.drag(view.getXY(),view.getXY(),3.0) self.device.press('KEYCODE_DEL','DOWN_AND_UP') view.type(phone) sleep(1) trace('edit phone with no add OK') else: trace('edit phone with add') #touch 'Add another field' view = self.getView('Add another field') view.touch() sleep(3) #touch 'Phone' and edit view = self.getView('Phone') view.touch() sleep(2) self.device.type(phone) sleep(1) trace('edit phone with add OK') def editEmail(self,email): pass def search(self,str): pass def sort(self): pass def favorite(self,name=''): pass
print benchmark_name, run_result, score_number, score_unit collect_score(benchmark_name, run_result, score_number, score_unit) if fps != "": score_number = fps.split(" ")[0] score_unit = fps.split(" ")[1] print benchmark_name, run_result, score_number, score_unit collect_score(benchmark_name, run_result, score_number, score_unit) cached_result_file = "last_results_2.5.1.xml" device, serialno = ViewClient.connectToDeviceOrExit() kwargs2 = {'startviewserver': True, 'forceviewserveruse': False, 'autodump': False, 'ignoreuiautomatorkilled': True, 'compresseddump': False} vc = ViewClient(device, serialno, **kwargs2) time.sleep(2) vc.dump(window='-1') test_type = vc.findViewWithText("Performance Tests") test_type.touch() time.sleep(2) # By some reason in order to select all test, a back step is required vc.dump(window='-1') test_selection = vc.findViewByIdOrRaise("com.glbenchmark.glbenchmark25:id/buttonAll") device.press('KEYCODE_BACK') time.sleep(3) test_type.touch() time.sleep(2) test_selection.touch() print "All selected!" time.sleep(3)
def SMS(): try: cdir=os.getcwd() adir=str(glob.glob(cdir + "/" + "logcat.txt")) cut=adir.split("/") before=cut[-1] global final final=before.replace("']", "") os.system("adb shell pm clear com.android.phone") time.sleep(10) check() os.system("adb shell cmd statusbar collapse") time.sleep(1) if gets==str("4G Signal") or String==str("LTE Signal") or String==str("4G"): if final=="logcat.txt": print("Log file found Removing now.....") os.remove(final) else: print("No log file found..........") try: time.sleep(1) os.system("adb shell pm clear com.google.android.apps.messaging") from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithContentDescription("Messages"): vc.findViewWithContentDescription("Messages").touch() time.sleep(1) vc.dump() else: device.startActivity("com.huawei.android.launcher/com.huawei.android.launcher.unihome.UniHomeLauncher") time.sleep(1) vc.dump() vc.findViewWithContentDescription("Start chat").touch() time.sleep(1) vc.dump() vc.findViewById("com.google.android.apps.messaging:id/recipient_text_view").touch() time.sleep(2) vc.dump() device.shell("input text " + str(ISDN)) vc.dump() time.sleep(3) vc.findViewById("com.google.android.apps.messaging:id/contact_picker_create_group").touch() time.sleep(1) vc.dump() vc.findViewById("com.google.android.apps.messaging:id/compose_message_text").setText("Hi") time.sleep(1) vc.dump() vc.findViewById("com.google.android.apps.messaging:id/send_message_button_container").touch() time.sleep(4) vc.dump() os.system("adb logcat -d time >> logcat.txt") time.sleep(6) file=open("logcat.txt", "r") lines= file.read() if "BugleDataMode: Processing changed messages for 357" in lines or "Done sending SMS message{id:357} conversation{id:50}, status: MANUAL_RETRY" in lines or "process from ProcessSentMessageAction due to sms_send failure with queues:" in lines: sheet1.write(j,3,"FAIL") time.sleep(1) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"sms.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"sms.png "+fin+PLMN+"sms.png" ) time.sleep(1) file.close() elif "status: SUCCEEDED" in lines: sheet1.write(j,3,"PASS") time.sleep(1) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"sms.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"sms.png "+fin+PLMN+"sms.png" ) time.sleep(1) file.close() #Take screenshot except: print("Exception while sending SMS..............") time.sleep(1) os.system("adb shell pm clear com.google.android.apps.messaging") time.sleep(1) else: sheet1.write(j,3,"FAIL") os.system("adb shell input keyevent KEYCODE_HOME") time.sleep(2) for i in range(4): from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithText("Settings"): vc.dump() vc.findViewWithText("Settings").touch() vc.dump() vc.findViewWithText("Wireless & networks").touch() vc.dump() vc.findViewWithText("Mobile network").touch() vc.dump() break else: os.system("adb shell input swipe 876 856 102 949 ") time.sleep(1) from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithText("Settings"): vc.dump() vc.findViewWithText("Settings").touch() vc.dump() vc.findViewWithText("Wireless & networks").touch() vc.dump() vc.findViewWithText("Mobile network").touch() vc.dump() break from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"Settings.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"Settings.png "+fin+PLMN+"Settings.png" ) time.sleep(1) except: print("An Exception occured......")
chapters = ["Browser", "Multicore", "Metal"] for chapter in chapters: choose_chapter(vc, chapter) # Start benchmark vc_dump(vc) btn_start = vc.findViewByIdOrRaise("com.quicinc.vellamo:id/main_toolbar_operation_button") btn_start.touch() # Wait while Vellamo is running benchmark finished = False while not finished: time.sleep(1) try: vc.dump(window="-1") vc.findViewByIdOrRaise("com.quicinc.vellamo:id/main_toolbar_goback_title") btn_no = vc.findViewByIdOrRaise("com.quicinc.vellamo:id/button_no") btn_no.touch() finished = True except ViewNotFoundException: pass except RuntimeError as e: print e except ValueError as ve: print ve print "Benchmark finished: %s" % chapter device.press("KEYCODE_BACK") device.press("KEYCODE_BACK")
def refresh(): try: cdir=os.getcwd() adir=str(glob.glob(cdir + "/" + "logcat.txt")) cut=adir.split("/") before=cut[-1] global final final=before.replace("']", "") if final=="logcat.txt": print("Log file found Removing now.....") os.remove(final) else: print("No log File found....") from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) device.shell("input keyevent KEYCODE_HOME") vc.dump() for i in range(6): from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithText("Settings"): vc.dump() vc.findViewWithText("Settings").touch() vc.dump() vc.findViewWithText("Wireless & networks").touch() vc.dump() vc.findViewById("android:id/switch_widget").touch() vc.dump() time.sleep(3) vc.findViewById("android:id/switch_widget").touch() vc.dump() device.shell("input keyevent KEYCODE_HOME") vc.dump() break else: os.system("adb shell input swipe 876 856 102 949 ") time.sleep(1) from com.dtmilano.android.viewclient import ViewClient device, serialno=ViewClient.connectToDeviceOrExit() vc=ViewClient(device=device, serialno=serialno) if vc.findViewWithText("Settings"): vc.dump() vc.findViewWithText("Settings").touch() vc.dump() vc.findViewWithText("Wireless & networks").touch() vc.dump() vc.findViewById("android:id/switch_widget").touch() vc.dump() time.sleep(3) vc.findViewById("android:id/switch_widget").touch() vc.dump() device.shell("input keyevent KEYCODE_HOME") vc.dump() break os.system("adb logcat -d time >> logcat.txt") time.sleep(4) file=open("logcat.txt", "r") lines= file.read() if "ims registered= true" in lines: sheet1.write(j,0,PLMN) sheet1.write(j,1,"PASS") time.sleep(1) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"Registration.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"Registration.png "+fin+PLMN+"Registration.png" ) time.sleep(1) print("writing1") file.close() else: sheet1.write(j,0,PLMN) sheet1.write(j,1,"FAIL") time.sleep(1) os.system("adb shell screencap -p /sdcard/Automation/"+PLMN+"Registration.png") time.sleep(1) os .system("adb pull /sdcard/Automation/"+PLMN+"Registration.png "+fin+PLMN+"Registration.png" ) time.sleep(1) print("writing1") file.close() except: print("An Exception occured......")
class contacts: ''' contacts class ''' def __init__(self, device, devID='emulator-5554', sample=False): ''' constructor @type device: MonkeyDevice @param device: The device or emulator connected @type devID: str @param serialno: the serial number of the device or emulator to connect to @type sample: boolean @param sample: whether take snapshot as an sampling ''' self.device = device self.sample = sample self.contactCounter = 0 self.startStatus = False '''the status which indicate whether the contacts activity is started''' #use below code to remove the status bar from the snapshot width = int(device.getProperty('display.width')) height = int(device.getProperty('display.height')) density = device.getProperty('display.density') if density == .75: statusBarHeight = 19 elif density == 1.5: statusBarHeight = 38 elif density == 2.0: statusBarHeight = 50 else: statusBarHeight = 25 self.snap_rect = 0, statusBarHeight, width, height - statusBarHeight #define the point coordinate used to slide screen self.left = (width / 4, height / 2) self.right = (width / 4 * 3, height / 2) self.up = (width / 2, height / 4) self.down = (width / 2, height / 4 * 3) self.center = (width / 2, height / 2) trace('before instance') self.vc = ViewClient(device, devID) trace('after instance') def start(self): ''' start the contacts activity and set the startStatus True if contacts is ready. ''' trace('Starting activity ...') self.device.startActivity(component=componentName) sleep(2) self.startStatus = self.goList() trace('Contacts is started, checking the contacts status...') self.isReady() sleep(2) def stop(self): ''' stop the contacts activity and set the startStatus False ''' self.device.shell('am force-stop %s' % package) trace('force stop contacts package %s' % package) self.startStatus = False def menu(self): ''' press menu ''' self.device.press('KEYCODE_MENU', 'DOWN_AND_UP') trace('press menu') def scroll(self, down=True, times=1): ''' scoll up or down for some times @type down: boolead @param down: scroll down if True or scroll up @type times: int @param times: how many times to scroll ''' keycode = 'KEYCODE_DPAD_DOWN' if down else 'KEYCODE_DPAD_UP' for i in range(times): self.device.press(keycode, 'DOWN_AND_UP') trace('scroll %s' % str) def back(self): ''' press back ''' self.device.press('KEYCODE_BACK', 'DOWN_AND_UP') trace('press back') def slide(self, str, view=None): ''' slide the screen @type: str @param: 'left','right','up','down' @type view: @param view: specify the view, default to None ''' if str not in ['left', 'right', 'up', 'down']: raise SyntaxError( "wrong parameter: choose from 'left','right','up' or 'down'") try: cX, cY = view.getCenter() width = view.getWidth() height = view.getHeight() cL = cX - width / 4, cY cR = cX + width / 4, cY cU = cX, cY - height / 4 cD = cX, cY + height / 4 except AttributeError: pass (left, right, up, down) = (cL, cR, cU, cD) if view else (self.left, self.right, self.up, self.down) nav = { 'left': { 'start': right, 'end': left }, 'right': { 'start': left, 'end': right }, 'up': { 'start': down, 'end': up }, 'down': { 'start': up, 'end': down } } self.device.drag(nav[str]['start'], nav[str]['end'], 0.1, 1) trace('slide the screen from %s to %s ' % (nav[str]['start'], nav[str]['end'])) sleep(2) def getView(self, str, cD=False, iD=False, dump=True, regex=False): ''' get the view with the specified text, content description or viewId @type str: str @param str: the query string @type cD: boolean @param cD: whether handle the query str as content description @type iD: boolean @param iD: whether handle the query str as viewId @type dump: boolean @param dump: whether execute dump before findView, depending on whether the screen is changed @return: the view found ''' if dump: trace('before dump') self.vc.dump() trace('after dump') if cD: view = self.vc.findViewWithContentDescription(str) trace('Query view with content description: %s, return is %s' % (str, view is not None)) return view elif iD: view = self.vc.findViewById(str) trace('Query view by id: %s, return is %s' % (str, view is not None)) return view elif regex: view = self.vc.findViewWithAttributeThatMatches( 'text', re.compile(str)) trace('Query view that match attribute: %s, return is %s' % (str, view is not None)) return view else: view = self.vc.findViewWithText(str) trace('Query view with text: %s, return is %s ' % (str, view is not None)) return view def isReady(self): ''' check whether the contacts is ready. @return: True ''' while True: view = self.getView( 'Contacts list is being updated to reflect the change of language.' ) if not view: trace('Contacts is ready') break else: trace('Contacts is not ready, please wait!') sleep(2) return True def isEmpty(self): ''' check whether the contacts is empty @return: True or False ''' self.check() view = self.getView('No contacts.') if view: trace('Contacts list is empty') return True else: trace('Contacts list is not empty') return False def getCounter(self): ''' get the contacts counter @return: the current contacts counter ''' self.goList() if self.isEmpty(): self.contactCounter = 0 else: while not self.getView('\d+ contacts?', regex=True): self.slide('down') sleep(3) self.contactCounter = int( self.getView('\d+ contacts?', regex=True, dump=False).getText().split()[0]) trace('current contacts counter is %d' % self.contactCounter) return self.contactCounter def goList(self): ''' check whether the screen is in contacts list view, if not, go list view via pressing back key @return: True ''' while True: view = self.getView("All contacts", cD=True) if not view: self.back() sleep(3) else: if not view.isSelected(): trace('Touch "All contacts"') view.touch() break trace('Goto contacts list view') return True def goEdit(self): ''' check whether the contacts is empty, then select adding and go to edit view. @return: True ''' self.check() try: self.getView('Add Contact', cD=True, dump=False).touch() trace('Touch "Add Contact"') sleep(5) return True except AttributeError: pass try: self.getView('Create a new contact', dump=False).touch() trace('Touch "Create a new contact"') sleep(5) self.getView('Keep local').touch() trace('Select "Keep local"') sleep(5) return True except AttributeError: pass def check(self): ''' check whether the contacts is started before other operation about contacts @return: True ''' if not self.startStatus: trace("Wrong code! please start contacts firstly in you code") raise SyntaxError('contacts should be start firstly!') return True def snapshot(self, title): ''' take snapshot @type title: str @param title: specify the title of snapshot @return: snapshot object ''' snapName = title + '.png' snapFolder = 'snapshot' os.system('if not exist %s\\%s mkdir %s\\%s' % (logPath, snapFolder, logPath, snapFolder)) snapFile = logPath + '\\' + snapFolder + '\\' + snapName result = self.device.takeSnapshot().getSubImage(self.snap_rect) trace('take snapshot without the statusbar') result.writeToFile(snapFile, 'png') trace('save the snapshot to file: %s ' % snapFile) return result def wipe(self, view): ''' wipe the text in specified view ''' try: self.device.drag(view.getXY(), view.getXY(), 1, 1) trace('wipe text: %s' % str(view.getText())) self.device.press('KEYCODE_DEL', 'DOWN_AND_UP') except: Exception('wipe failed') def addContact(self, name='', phone='', email='', address=''): self.goEdit() try: offset = 0 if name: view = self.getView('id/no_id/27', iD=True) trace('type %s' % name) view.type(name) view.touch() if phone: view = self.getView('id/no_id/46', iD=True, dump=False) trace('type %s' % phone) view.type(phone) offset += 4 sleep(2) if email: view = self.getView('id/no_id/' + str(57 + offset), iD=True) trace('type %s' % email) view.type(email) offset += 4 sleep(2) if address: view = self.getView('id/no_id/' + str(68 + offset), iD=True) trace('type %s' % address) view.type(address) sleep(2) view = self.getView('Done', dump=False) view.touch() trace('Touch Done') finally: sleep(5) self.goList() def goEditExistContact(self, str): try: self.search(str).touch() sleep(4) except AttributeError: trace('No contact with info ' + str + ' found') return False self.menu() sleep(1) self.scroll(1) self.device.press('KEYCODE_ENTER') sleep(3) return True def editCompany(self, company): view = self.getView('Add organization') if view: trace('Step: add a organization info') view.touch() sleep(1) trace('add the company info') self.device.type(company) sleep(1) else: trace('Step: Edit the organization info') view = self.getView('id/no_id/42', iD=True) self.wipe(view) trace('Edit the company info') self.device.type(company) sleep(1) def editDetails(self, contactsInfo, fieldName, content, update=True): ''' edit details of contact with add or update @type contactsInfo: str @param contactsInfo: information of contacts @type fieldName: str @param fieldName: field string of @return: snapshot object ''' self.goEditExistContact(contactsInfo) if fieldName not in [ 'Name', 'Phone', 'Email', 'Address', 'Company', 'Website', 'Nickname', 'Notes' ]: raise SyntaxError( "wrong 2nd parameter: fieldName choose from 'Name','Phone','Email','Address','Company','Website','Nickname','Notes'" ) if 'Name' == fieldName: self.editName(content) if 'Company' == fieldName: self.editCompany(content) addOrUpdate = 'update' if update else 'add' if 'update' == addOrUpdate: self.updateDetails(fieldName, content) if 'add' == addOrUpdate: self.addDetails(fieldName, content) self.getView('Done', dump=False).touch() trace('Click Done') sleep(3) self.goList() def editName(self, str): #find EditText of Name view = self.getView('id/no_id/27', iD=True) #edit name self.wipe(view) view.type(str) sleep(1) trace("edit contact's name OK") def addDetails(self, fieldName, content): trace('edit' + fieldName + 'with add') #touch 'Add another field' while not self.getView('Add another field').touch(): self.slide('up') sleep(2) sleep(3) #touch fieldName and edit while not self.getView(fieldName): view2 = self.getView('id/no_id/2', iD=True, dump=False) self.slide('up', view2) self.getView(fieldName, dump=False).touch() sleep(2) self.device.type(content) sleep(1) trace('edit' + fieldName + 'with add OK') def updateDetails(self, fieldName, content): trace('Edit field ' + fieldName + ' info') while not self.getView(fieldName): self.slide('up') sleep(2) view = self.getView(fieldName, dump=False) view2 = self.getView(view.getId()[:-2] + str(int(view.getId()[-2:]) + 6), iD=True) self.wipe(view2) sleep(1) view2.type(content) sleep(1) return True def search(self, str): ''' @type str: str @param str: specify the search keyword ##@return: the view of search result if search result is not null, else return None ''' trace("start searching...") self.goList() searchView = self.getView("Search", True) searchView.touch() sleep(2) self.device.type(str) trace("search keyword is: " + str) #the id of 1st search result is always 28 if self.getView("No contacts"): trace("No contact searched") return None else: return self.getView("id/no_id/28", iD=True) def sortAndViewAs(self, sortByFirstName=True, viewAsFirstNameFirst=True): ''' sort contact name @type sortByFirstName: boolean @param sortByFirstName: whether sort contact name by first name @type viewAsFirstNameFirst: boolean @param viewAsFirstNameFirst: whether view contact by first name first ''' self.goList() trace("start sorting...") self.device.press("KEYCODE_MENU", "DOWN_AND_UP") settingsView = self.getView("Settings") settingsView.touch() sleep(2) self.getView("Sort list by").touch() if sortByFirstName: self.getView("First name").touch() sleep(2) self.getView("View contact names as").touch() sleep(2) if viewAsFirstNameFirst: self.getView("First name first").touch() else: self.getView("Last name first").touch() else: self.getView("Last name").touch() sleep(2) self.getView("View contact names as").touch() sleep(2) if viewAsFirstNameFirst: self.getView("First name first").touch() else: self.getView("Last name first").touch() sleep(2) def favor(self, str, favor=True): ''' add or cancel contact to favorites @type str: str @param str: specify the search string @type favor: boolean @param favor: add if True ''' try: self.search(str).touch() sleep(3) except AttributeError: trace('no matched contact found, operation failed!') self.goList() return False aim, action = ('Add to favorites', 'add') if favor else ('Remove from favorites', 'remov') try: self.getView(aim, cD=True).touch() trace('%s successfully' % aim) except AttributeError: trace('%s has been %sed in favorites, not have to %s repeatedly' % (str, action, action)) sleep(3) self.goList() return True def delete(self, kwd=''): '''delete one contact @type kwd: string @param kwd: keyword which contact to be delete, if none,delete first contact @return: ''' #self.start() #trace('launch on contact application') self.goList() if self.isEmpty(): trace('Could not find any contact data,no record!') raise SyntaxError('Could not find any contact data,no record!') if not kwd: # keyword is empty,delete first contact trace('keyword is none, first contact with be delete') find = self.getView('id/no_id/27', iD=True, dump=False) #if find != None: else: # keyword is not none # search specifying contact by keyword find = self.search(kwd) trace('') # if find != None: if not find: trace('Could not find the contact : ' + kwd) raise SyntaxError('Could not find the contact : ' + kwd) else: # delete operate find.touch() sleep(3) trace('show contact detail information') sleep(1) self.device.press('KEYCODE_MENU') sleep(4) delete_menu = self.getView('Delete') trace('choose delete contact') delete_menu.touch() # confirm delete operate ok_menu = self.getView('OK') ok_menu.touch() sleep(3) # if current activity is not Main Activity back to Main Activity self.goList() if 0 == self.getCounter(): trace(' all contacts has been deleted, no record!') trace('operation success.')
class contacts: ''' contacts class ''' def __init__(self, device, devID='emulator-5554', sample=False): ''' constructor @type device: MonkeyDevice @param device: The device or emulator connected @type devID: str @param serialno: the serial number of the device or emulator to connect to @type sample: boolean @param sample: whether take snapshot as an sampling ''' self.device = device self.sample = sample self.startStatus = False '''the status which indicate whether the contacts activity is started''' self.vc = ViewClient(device, devID) #use below code to remove the status bar from the snapshot width = int(device.getProperty('display.width')) height = int(device.getProperty('display.height')) density = device.getProperty('display.density') if density == .75: statusBarHeight = 19 elif density == 1.5: statusBarHeight = 38 elif density == 2.0: statusBarHeight = 50 else: statusBarHeight = 25 self.snap_rect = 0, statusBarHeight, width, height - statusBarHeight def start(self): ''' start the contacts activity and set the startStatus True if contacts is ready. ''' self.device.startActivity(component=componentName) sleep(3) self.startStatus = self.isReady() def back(self): ''' press back ''' self.device.press('KEYCODE_BACK', 'DOWN_AND_UP') def getView(self, str, cD=False, iD=False): ''' get the view with the specified text, content description or viewId @type str: str @param str: the query string @type cD: boolean @param cD: whether handle the query str as content description @type iD: boolean @param iD: whether handle the query str as viewId @return: the view found ''' self.vc.dump() sleep(3) if not cD: if not iD: return self.vc.findViewWithText(str) else: return self.vc.findViewById(str) else: return self.vc.findViewWithContentDescription(str) def isReady(self): ''' check whether the contacts is ready. ''' while True: view = self.getView( 'Contact list is being updated to reflect the change of language.' ) if not view: trace('Contacts is ready') break else: trace('Contacts is not ready, please wait!') sleep(2) return True def goEdit(self): ''' check whether the contact is empty, then select adding and go to edit view. @return: True ''' self.check() view = self.getView('Create a new contact') if view: view.touch() trace('Click "Create a new contact"') view = self.getView('Keep local') if view: view.touch() trace('Select "Keep local"') else: view = self.getView('Add Contact', True) view.touch() trace('Click "Add Contact"') return True def check(self): ''' check whether the contacts is started before other operation about contacts @return: True ''' if not self.status: trace("Wrong code! please start contacts firstly in you code") raise SyntaxError('contacts should be start firstly!') return True def snapshot(self, title): ''' take snapshot @type title: str @param title: specify the title of snapshot ''' snapName = title + '.png' snapFile = logPath + '\\' + snapName result = self.device.takeSnapshot().getSubImage(self.snap_rect) result.writeToFile(snapFile, 'png') def addContact(self, name='', phone='', email=''): #notice firstly call self.goEdit() pass def editDetails(self, phone=''): pass def search(self, str): ''' @type str: str @param str: specify the search keyword ##@return: the view of search result if search result is not null, else return None ''' trace("start searching...") trace("check contact main UI, dump, please wait...") self.vc.dump() while not self.getView("Search", True): self.device.press('KEYCODE_BACK') sleep(2) self.vc.dump() searchView = self.getView("Search", True) searchView.touch() self.device.type(str) trace("search keyword is: " + str) self.snapshot("search_result") ''' tmp=[] self.vc.dump() trace("dump, please wait...") #the id of 1st search result is always 28 for i in self.vc.findViewsContainingPoint((100,200)): tmp.append(i.getId()) result=int(tmp[len(tmp)-1][-2:]) if(result<28): trace("search result: nothing") return None else: self.snapshot("search_result") return self.vc.findViewById(tmp[len(tmp)-1]) ''' def sortAs(self, sortByFirstName=True): ''' sort contact name @type sortByFirstName: boolean @param sortByFirstName: whether sort contact name by first name ''' trace("check contact main UI, dump, please wait...") self.vc.dump() while not self.getView("Search", True): self.device.press('KEYCODE_BACK') sleep(2) self.vc.dump() trace("start sorting...") self.device.press("KEYCODE_MENU", "DOWN_AND_UP") trace("click menu, dump, please wait...") self.vc.dump() settingsView = self.getView("Settings") settingsView.touch() sleep(2) trace("click Settings, dump, please wait...") self.vc.dump() self.vc.findViewWithTextOrRaise("Sort list by").touch() trace("click Sort list by, dump, please wait...") self.vc.dump() if sortByFirstName: self.vc.findViewWithTextOrRaise("First name").touch() else: self.vc.findViewWithTextOrRaise("Last name").touch() sleep(2) #conflict with check at the begining #self.device.press("KEYCODE_BACK","DOWN_AND_UP") #sleep(2) def viewAs(self, viewAsFirstNameFirst=True): ''' view contact name @type viewAsFirstNameFirst: boolean @param viewAsFirstNameFirst: whether view contact by first name first ''' trace("check contact main UI, dump, please wait...") self.vc.dump() while not self.getView("Search", True): self.device.press('KEYCODE_BACK') sleep(2) self.vc.dump() trace("start viewing...") self.device.press("KEYCODE_MENU", "DOWN_AND_UP") trace("click menu, dump, please wait...") self.vc.dump() settingsView = self.getView("Settings") settingsView.touch() sleep(2) trace("click Settings, dump, please wait...") self.vc.dump() self.vc.findViewWithTextOrRaise("View contact names as").touch() trace("click View contact names as, dump, please wait...") self.vc.dump() if viewAsFirstNameFirst: self.vc.findViewWithTextOrRaise("First name first").touch() else: self.vc.findViewWithTextOrRaise("Last name first").touch() sleep(2) #conflict with check at the begining #self.device.press("KEYCODE_BACK","DOWN_AND_UP") #sleep(2) def favorite(self, name=''): pass
class YkspTestCase(unittest.TestCase): package = None serial = None dirRoot = None logsFilename = None screenshotFolder = None screendumpFolder = None screenCount = 0 def setUp(self): # Connnect to device self.device, self.serialno = ViewClient.connectToDeviceOrExit(serialno=YkspTestCase.serial) # Wake device self.device.wake() # Create ViewClient instance self.vc = ViewClient(self.device, self.serialno, autodump=False) def tearDown(self): # Force-stop the app self.device.shell('am force-stop %s' % YkspTestCase.package) def launchApp(self, package=None): ''' Launches an app as if from the launcher. @type package: str @param package: An optional parameter to specify an application to launch by its package name. If not provided, the application package name provided in the application manifest is used. ''' if package is None: package = YkspTestCase.package # Launch application only if the package is installed if self.device.shell('pm path %s' % package): self.device.shell('monkey -p %s -c android.intent.category.LAUNCHER 1' % package) else: self.fail('Failed to launch application. %s is not installed on this device' % package) def refreshScreen(self, sleep=1): ''' Updates the view tree. This method or saveScreen() must be called after each screen transition to keep the view tree in sync with the device screen. @type sleep: float @param sleep: An optional parameter to indicate the time to sleep before refreshing the screen. Defaults to one second. ''' self.vc.dump(window=-1, sleep=sleep) def saveScreen(self, tag=None, sleep=1): ''' Updates the view tree and saves to disk the screenshot and screendump of the device screen. This method or refreshScreen() must be called after each screen transition to keep the view tree in sync with the device screen. @type tag: str @param tag: The tag for this screen. This is appended to the filename. @type sleep: float @param sleep: An optional parameter to indicate the time to sleep before saving the screen. Defaults to one second. ''' if sleep > 0: self.vc.sleep(sleep) filename = YkspTestCase.screenCount if tag: filename = '%s-%s' % (filename, tag) # Take a screenshot and save self.device.takeSnapshot(reconnect=True).save('%s/%s/%s.png' % (YkspTestCase.dirRoot, YkspTestCase.screenshotFolder, filename), 'PNG') # Take a screendump and save screendump = self.vc.dump(window=-1, sleep=0) screendumpStream = open('%s/%s/%s.txt' % (YkspTestCase.dirRoot, YkspTestCase.screendumpFolder, filename), 'w') self.vc.traverse(transform=self.vc.TRAVERSE_CITPS, stream=screendumpStream) screendumpStream.close() YkspTestCase.screenCount += 1 @staticmethod def parseArgs(argv): try: opts, args = getopt.getopt(argv[1:], 'hp:s:r:l:m:n:', ['help', 'package=', 'serial=', 'root=', 'logs=', 'screenshots=', 'screendumps=']) except getopt.GetoptError: YkspTestCase.usage(2) for opt, arg in opts: if opt in ('-h', '--help'): YkspTestCase.usage(2) elif opt in ('-p', '--package'): YkspTestCase.package = arg argv.remove(opt) argv.remove(arg) elif opt in ('-s', '--serial'): YkspTestCase.serial = arg argv.remove(opt) argv.remove(arg) elif opt in ('-r', '--root'): YkspTestCase.dirRoot = arg argv.remove(opt) argv.remove(arg) elif opt in ('-l', '--logs'): YkspTestCase.logsFilename = arg argv.remove(opt) argv.remove(arg) elif opt in ('-m', '--screenshots'): YkspTestCase.screenshotFolder = arg argv.remove(opt) argv.remove(arg) elif opt in ('-n', '--screendumps'): YkspTestCase.screendumpFolder = arg argv.remove(opt) argv.remove(arg) if YkspTestCase.package is None: print '\nError:' print '--package must be specified' YkspTestCase.usage(2) if YkspTestCase.serial is None: print '\nError:' print '--serial must be specified' YkspTestCase.usage(2) if YkspTestCase.dirRoot is None: print '\nError:' print '--root must be specified' YkspTestCase.usage(2) if YkspTestCase.screenshotFolder is None: print '\nError:' print '--screenshots must be specified' YkspTestCase.usage(2) if YkspTestCase.screendumpFolder is None: print '\nError:' print '--screendumps must be specified' YkspTestCase.usage(2) if os.path.isdir(YkspTestCase.dirRoot) is False: print '\nError:' print '--root specifies an invalid directory' YkspTestCase.usage(2) @staticmethod def usage(exitVal=0): print '\nUsage:' print '-h, --help OPTIONAL print this help and exit' print '-p, --package <package> REQUIRED specify the package name of the application' print '-s, --serial <serial> REQUIRED specify the serial number of the device to run this test case' print '-r, --root <dir> REQUIRED specify the root directory to save the results of this test case' print '-l, --logs <dir> OPTIONAL specify the filename to save the PyUnit logs' print '-m, --screenshots <folder> REQUIRED specify the folder name to save the screenshots' print '-n, --screendumps <folder> REQUIRED specify the folder name to save the screendumps' sys.exit(exitVal) @staticmethod def main(argv): YkspTestCase.parseArgs(argv) # Create subdirectories dirScreenshot = '%s/%s' % (YkspTestCase.dirRoot, YkspTestCase.screenshotFolder) if os.path.isdir(dirScreenshot) is False: os.mkdir(dirScreenshot) dirScreendump = '%s/%s' % (YkspTestCase.dirRoot, YkspTestCase.screendumpFolder) if os.path.isdir(dirScreendump) is False: os.mkdir(dirScreendump) # Configure logging and execute test case if YkspTestCase.logsFilename: logsStream = open('%s/%s' % (YkspTestCase.dirRoot, YkspTestCase.logsFilename), 'w') runner = unittest.TextTestRunner(stream=logsStream, verbosity=2) unittest.main(testRunner=runner) else: unittest.main()
class LeHaiEmulate(): def __init__(self): self.device = None self.serialno = None self.vc = None self.accountfilename = 'lehai_imei_list.'+time.strftime('%Y-%m-%d',time.localtime(time.time())) def openapp(self): self.device,self.serialno = ViewClient.connectToDeviceOrExit(serialno=None) FLAG_ACTIVITY_NEW_TASK = 0x10000000 componentName = 'com.lehai.ui/com.showself.ui.LoadingActivity' self.device.startActivity(component=componentName,flags=FLAG_ACTIVITY_NEW_TASK) ViewClient.sleep(3) self.vc = ViewClient(self.device,self.serialno,forceviewserveruse=True) def activeMobile(self,imei,imsi=None): if self.device == None : self.openapp() waitViewById('id/quick_guide_viewpager',self.vc) self.device.dragDip((500,300),(30,300),200,2) self.vc.dump() self.device.touch(615,378,2) waitViewById('id/home_bottom_tab5',self.vc) self.vc.findViewById('id/home_bottom_tab5').touch() self.vc.dump() waitViewById('id/btn_login_note_left',self.vc) #self.vc.findViewById('id/btn_login_note_left').touch() self.device.touch(160,1188,2) self.vc.dump() waitViewByTx('乐嗨号注册',self.vc) self.vc.findViewWithText('乐嗨号注册').touch() self.vc.dump() name = ''.join(map(lambda xx:(hex(ord(xx))[2:]),os.urandom(5))) self.vc.findViewById('id/et_lehai_reg_account').setText(name) self.vc.findViewById('id/et_reg_password').setText('abc1234') self.vc.findViewById('id/btn_lehai_reg').touch() self.vc.dump() waitViewById('id/btn_register_finish',self.vc) self.vc.findViewById('id/btn_register_finish').touch() self.vc.dump() waitViewById('id/imageView_classify_more_recommend',self.vc) self.vc.findViewById('id/imageView_classify_more_recommend').touch() ViewClient.sleep(5) f = open(self.accountfilename,'a') try: f.writelines(name+"\t"+imei+"\t"+imsi+"\r\n") finally: f.flush() f.close() def reactiveMobile(self): if self.device == None : self.openapp() waitViewById('id/rgBottomNav',self.vc) self.device.touch(675,95,2) ViewClient.sleep(3) self.vc.findViewById('id/game_name').touch()
#! /usr/bin/env python # -*- coding: utf-8 -*- import time from com.dtmilano.android.viewclient import ViewClient from com.dtmilano.android.adb import adbclient device, serialno = ViewClient.connectToDeviceOrExit() vc = ViewClient(device, serialno) adb = adbclient.AdbClient(serialno='.*') def wait_for_id(vc, 'id): while True: vc.dump(window=-1) if vc.findViewById(id) is None: time.sleep(0.5) else: return def wait_for_id_and_touch(id): while True: vc.dump(window=-1) if vc.findViewById(id) is None: time.sleep(0.5) else: vc.findViewByIdOrRaise(id).touch() return def wait_for_text(vc, 'text): while True: vc.dump(window=-1)
class SSRDumpListenerThread(threading.Thread): class State(object): IDLE = "idle" BEING_DUMPED = "being dumped" DUMPED = "has been dumped" def __init__(self, device, serialno): super(SSRDumpListener.SSRDumpListenerThread, self).__init__() self.daemon = True self.stoprequest = threading.Event() self.lock = threading.Lock() self.device = device self.serialno = serialno self.vc = ViewClient(device, serialno, autodump=False) self.state = SSRDumpListener.SSRDumpListenerThread.State.IDLE def join(self, timeout=None): self.stoprequest.set() super(SSRDumpListener.SSRDumpListenerThread, self).join(timeout) def run(self): pattern = re.compile("Window{.+?}") while not self.stoprequest.isSet(): try: win_dumpsys, _ = subprocess.Popen( \ "adb -s {} shell dumpsys window windows | grep \"Window #\"".format(self.serialno), \ shell=True, stdout=subprocess.PIPE).communicate() win_info_strs = map( lambda s: pattern.search(s.strip()).group(0), win_dumpsys.splitlines()) win_info_strs = [ s[7:-1] for s in win_info_strs if len(s) > 7 ] self.win_info = dict([ (ss[2], ss[0]) for ss in map(lambda s: s.split(), win_info_strs) ]) if SSRDumpListener.FILTER in self.win_info.keys(): self.vc.dump( window=self.win_info[SSRDumpListener.FILTER], sleep=0) views = dict([(v.getId(), v) for v in self.vc.getViewsById().values() if len(v.getId()) > 0]) if SSRDumpListener.MSG_VIEW_ID in views.keys(): msg = views[SSRDumpListener.MSG_VIEW_ID].getText() if SSRDumpListener.RAMDUMP_COMPLETED_KEYMSG in msg: self.state = SSRDumpListener.SSRDumpListenerThread.State.DUMPED else: self.state = SSRDumpListener.SSRDumpListenerThread.State.BEING_DUMPED else: self.state = SSRDumpListener.SSRDumpListenerThread.State.IDLE except: pass time.sleep(SSRDumpListener.PERIOD) def dismiss_dialog(self): if self.state == SSRDumpListener.SSRDumpListenerThread.State.IDLE: return self.vc.dump(window=self.win_info[SSRDumpListener.FILTER], sleep=0) views = dict([(v.getId(), v) for v in self.vc.getViewsById().values() if len(v.getId()) > 0]) if SSRDumpListener.BTN_ID in views.keys(): x, y = views[SSRDumpListener.BTN_ID].getCenter() self.device.touch(x, y) self.state = SSRDumpListener.SSRDumpListenerThread.State.IDLE
class contacts: ''' contacts class ''' def __init__(self, device, devID='emulator-5554',sample = False): ''' constructor @type device: MonkeyDevice @param device: The device or emulator connected @type devID: str @param serialno: the serial number of the device or emulator to connect to @type sample: boolean @param sample: whether take snapshot as an sampling ''' self.device=device self.sample=sample self.contactCounter=0 self.startStatus=False '''the status which indicate whether the contacts activity is started''' #use below code to remove the status bar from the snapshot width = int(device.getProperty('display.width')) height = int(device.getProperty('display.height')) density = device.getProperty('display.density') if density == .75: statusBarHeight = 19 elif density == 1.5: statusBarHeight = 38 elif density == 2.0: statusBarHeight = 50 else: statusBarHeight = 25 self.snap_rect = 0, statusBarHeight, width, height - statusBarHeight #define the point coordinate used to slide screen self.left = (width/4, height/2) self.right = (width/4*3, height/2) self.up = (width/2, height/4) self.down = (width/2, height/4*3) self.center = (width/2, height/2) trace('before instance') self.vc=ViewClient(device, devID) trace('after instance') def start(self): ''' start the contacts activity and set the startStatus True if contacts is ready. ''' trace('Starting activity ...') self.device.startActivity(component=componentName) sleep(2) self.startStatus = self.goList() trace('Contacts is started, checking the contacts status...') self.isReady() sleep(2) def stop(self): ''' stop the contacts activity and set the startStatus False ''' self.device.shell('am force-stop %s' % package) trace('force stop contacts package %s' % package) self.startStatus = False def back(self): ''' press back ''' self.device.press('KEYCODE_BACK','DOWN_AND_UP') trace('press back') def slide(self,str): ''' slide the screen @type: str @param: 'left','right','up','down' ''' if str not in ['left','right','up','down']: raise SyntaxError("wrong parameter: choose from 'left','right','up' or 'down'") nav = { 'left':{'start':self.right,'end':self.left}, 'right':{'start':self.left,'end':self.right}, 'up':{'start':self.down,'end':self.up}, 'down':{'start':self.up,'end':self.down} } self.device.drag(nav[str]['start'], nav[str]['end'], 0.1, 1) trace('slide the screen from %s to %s ' % (nav[str]['start'],nav[str]['end'])) sleep(2) def getView(self,str,cD=False,iD=False,dump=True,regex=False): ''' get the view with the specified text, content description or viewId @type str: str @param str: the query string @type cD: boolean @param cD: whether handle the query str as content description @type iD: boolean @param iD: whether handle the query str as viewId @type dump: boolean @param dump: whether execute dump before findView, depending on whether the screen is changed @return: the view found ''' if dump: trace('before dump') self.vc.dump() trace('after dump') if cD: view=self.vc.findViewWithContentDescription(str) trace('Query view with content description: %s, return is %s' % (str, view is not None)) return view elif iD: view=self.vc.findViewById(str) trace('Query view by id: %s, return is %s' % (str, view is not None)) return view elif regex: view=self.vc.findViewWithAttributeThatMatches('text',re.compile(str)) trace('Query view that match attribute: %s, return is %s' % (str, view is not None)) return view else: view=self.vc.findViewWithText(str) trace('Query view with text: %s, return is %s ' % (str, view is not None)) return view def isReady(self): ''' check whether the contacts is ready. @return: True ''' while True: view=self.getView('Contacts list is being updated to reflect the change of language.') if not view: trace('Contacts is ready') break else: trace('Contacts is not ready, please wait!') sleep(2) return True def isEmpty(self): ''' check whether the contacts is empty @return: True or False ''' self.check() view=self.getView('No contacts.') if view: trace('Contacts list is empty') return True else: trace('Contacts list is not empty') return False def getCounter(self): ''' get the contacts counter @return: the current contacts counter ''' self.goList() if self.isEmpty(): self.contactCounter=0 else: while not self.getView('\d+ contacts?',regex=True): self.slide('down') sleep(3) self.contactCounter = int(self.getView('\d+ contacts?',regex=True,dump=False).getText().split()[0]) trace('current contacts counter is %d' % self.contactCounter) return self.contactCounter def goList(self): ''' check whether the screen is in contacts list view, if not, go list view via pressing back key @return: True ''' while True: view=self.getView("All contacts",cD=True) if not view: self.back() sleep(3) else: if not view.isSelected(): trace('Touch "All contacts"') view.touch() break trace('Goto contacts list view') return True def goEdit(self): ''' check whether the contacts is empty, then select adding and go to edit view. @return: True ''' self.check() try: self.getView('Add Contact',cD=True,dump=False).touch() trace('Touch "Add Contact"') sleep(5) return True except AttributeError: pass try: self.getView('Create a new contact',dump=False).touch() trace('Touch "Create a new contact"') sleep(5) self.getView('Keep local').touch() trace('Select "Keep local"') sleep(5) return True except AttributeError: pass def check(self): ''' check whether the contacts is started before other operation about contacts @return: True ''' if not self.startStatus: trace("Wrong code! please start contacts firstly in you code") raise SyntaxError('contacts should be start firstly!') return True def snapshot(self,title): ''' take snapshot @type title: str @param title: specify the title of snapshot @return: snapshot object ''' snapName = title + '.png' snapFolder = 'snapshot' os.system('if not exist %s\\%s mkdir %s\\%s' % (logPath, snapFolder, logPath, snapFolder)) snapFile = logPath + '\\' + snapFolder + '\\' + snapName result = self.device.takeSnapshot().getSubImage(self.snap_rect) trace('take snapshot without the statusbar') result.writeToFile(snapFile,'png') trace('save the snapshot to file: %s ' % snapFile) return result def wipe(self,view): ''' wipe the text in specified view ''' try: self.device.drag(view.getXY(),view.getXY(),1,1) trace('wipe text: %s' % str(view.getText())) self.device.press('KEYCODE_DEL','DOWN_AND_UP') except: Exception('wipe failed') def addContact(self,name='',phone='',email='',address=''): self.goEdit() try: offset = 0 if name: view=self.getView('id/no_id/27',iD=True) trace('type %s' % name) view.type(name) view.touch() if phone: view=self.getView('id/no_id/46',iD=True,dump=False) trace('type %s' % phone) view.type(phone) offset += 4 sleep(2) if email: view=self.getView('id/no_id/' + str(57 + offset), iD=True) trace('type %s' % email) view.type(email) offset += 4 sleep(2) if address: view=self.getView('id/no_id/' + str(68 + offset), iD=True) trace('type %s' % address) view.type(address) sleep(2) view=self.getView('Done',dump=False) view.touch() trace('Touch Done') finally: sleep(5) self.goList() def goEditExistContact(self,str): trace('Search a contact to edit') view=self.search(str) if not view: raise SyntaxError('No '+str+' contact to edit') view.touch() sleep(4) self.device.press('KEYCODE_MENU') sleep(2) self.device.press('KEYCODE_DPAD_DOWN') sleep(1) self.device.press('KEYCODE_ENTER') sleep(3) def slideByView(self,view): trace('SlideByView') startp=(view.getX()+view.getWidth()-10,view.getY()+view.getHeight()-10) endpoint=(view.getX()+view.getWidth()-10,view.getY()+10) self.device.drag(startp,endpoint,0.5,1) sleep(1) def editCompany(self,company,action): view=self.getView('Add organization') if view: trace('Step: add a organization info') view.touch() sleep(1) trace('add the company info') self.device.type(company) sleep(1) view=self.getView('Title') trace("add a company's Title") view.type(company) else: trace('Step: Edit the organization info') view=self.getView('id/no_id/42',iD=True) self.wipe(view) trace('Edit the company info') self.device.type(company) view=self.getView('id/no_id/43',iD=True) trace("Edit the company's Title") self.wipe(view) self.device.type(company) def editAnotherField(self,fieldName,content,action): find=1 view=self.getView(fieldName) view2=self.getView('Add another field') while not view: self.device.drag((440,760),(440,160),2,5) sleep(1) view=self.getView(fieldName) view2=self.getView('Add another field') if view2: if not view: find=0 break if 0==find: trace('Step: add field '+fieldName+' info') view2.touch() trace('Click Add another field') sleep(2) view=self.getView(fieldName) if not view: view2=self.getView('id/no_id/2',iD=True) self.slideByView(view2) view=self.getView(fieldName) view.touch() sleep(1) #view=self.getView(fieldName) #view2=self.getView(view.getId()[:-2]+str(int(view.getId()[-2:])+6),iD=True) #view2.type(content) sleep(1) self.device.type(content) sleep(2) else: trace('Step: Edit field '+fieldName+' info') view2=self.getView(view.getId()[:-2]+str(int(view.getId()[-2:])+6),iD=True) self.wipe(view2) sleep(1) view2.type(content) sleep(1) def editDetails(self,nameOrNumber,company='',website='',nickname='',notes='',action='add'): ''' ''' self.goEditExistContact(nameOrNumber) if not company=='': self.editCompany(company,action) if not website=='': self.editAnotherField('Website',website,action) if not nickname=='': self.editAnotherField('Nickname',nickname,action) if not website=='': self.editAnotherField('Notes',notes,action) view=self.getView('Done') trace('Click Done') view.touch() sleep(3) self.goList() def search(self,str): ''' @type str: str @param str: specify the search keyword ##@return: the view of search result if search result is not null, else return None ''' trace("start searching...") self.goList() searchView=self.getView("Search",True) searchView.touch() sleep(2) self.device.type(str) trace("search keyword is: "+str) #the id of 1st search result is always 28 if self.getView("No contacts"): trace("No contact searched") return None else: return self.getView("id/no_id/28",iD=True) def sortAndViewAs(self, sortByFirstName=True, viewAsFirstNameFirst=True): ''' sort contact name @type sortByFirstName: boolean @param sortByFirstName: whether sort contact name by first name @type viewAsFirstNameFirst: boolean @param viewAsFirstNameFirst: whether view contact by first name first ''' self.goList() trace("start sorting...") self.device.press("KEYCODE_MENU","DOWN_AND_UP") settingsView=self.getView("Settings") settingsView.touch() sleep(2) self.getView("Sort list by").touch() if sortByFirstName: self.getView("First name").touch() sleep(2) self.getView("View contact names as").touch() sleep(2) if viewAsFirstNameFirst: self.getView("First name first").touch() else: self.getView("Last name first").touch() else: self.getView("Last name").touch() sleep(2) self.getView("View contact names as").touch() sleep(2) if viewAsFirstNameFirst: self.getView("First name first").touch() else: self.getView("Last name first").touch() sleep(2) def favor(self,str,favor=True): ''' add or cancel contact to favorites @type str: str @param str: specify the search string @type favor: boolean @param favor: add if True ''' try: self.search(str).touch() sleep(3) except AttributeError: trace('no matched contact found, operation failed!') self.goList() return False aim, action = ('Add to favorites', 'add') if favor else ('Remove from favorites', 'remov') try: self.getView(aim, cD=True).touch() trace('%s successfully' % aim) except AttributeError: trace('%s has been %sed in favorites, not have to %s repeatedly' % (str, action, action)) sleep(3) self.goList() return True def delete(self,kwd = ''): '''delete one contact @type kwd: string @param kwd: keyword which contact to be delete, if none,delete first contact @return: ''' #self.start() #trace('launch on contact application') self.goList() if self.isEmpty(): trace('Could not find any contact data,no record!') raise SyntaxError('Could not find any contact data,no record!') if not kwd : # keyword is empty,delete first contact trace('keyword is none, first contact with be delete') find = self.getView('id/no_id/27',iD=True,dump=False) #if find != None: else : # keyword is not none # search specifying contact by keyword find = self.search(kwd) trace('') # if find != None: if not find : trace('Could not find the contact : ' + kwd) raise SyntaxError('Could not find the contact : ' + kwd) else: # delete operate find.touch() sleep(3) trace('show contact detail information') sleep(1) self.device.press('KEYCODE_MENU') sleep(4) delete_menu = self.getView('Delete') trace('choose delete contact') delete_menu.touch() # confirm delete operate ok_menu = self.getView('OK') ok_menu.touch() sleep(3) # if current activity is not Main Activity back to Main Activity self.goList() if 0 == self.getCounter() : trace(' all contacts has been deleted, no record!') trace('operation success.')
class contacts: ''' contacts class ''' def __init__(self, device, devID='emulator-5554',sample = False): ''' constructor @type device: MonkeyDevice @param device: The device or emulator connected @type devID: str @param serialno: the serial number of the device or emulator to connect to @type sample: boolean @param sample: whether take snapshot as an sampling ''' self.device=device self.sample=sample self.contactCounter=0 self.startStatus=False '''the status which indicate whether the contacts activity is started''' #use below code to remove the status bar from the snapshot width = int(device.getProperty('display.width')) height = int(device.getProperty('display.height')) density = device.getProperty('display.density') if density == .75: statusBarHeight = 19 elif density == 1.5: statusBarHeight = 38 elif density == 2.0: statusBarHeight = 50 else: statusBarHeight = 25 self.snap_rect = 0, statusBarHeight, width, height - statusBarHeight #define the point coordinate used to slide screen self.left = (width/4, height/2) self.right = (width/4*3, height/2) self.up = (width/2, height/4) self.down = (width/2, height/4*3) self.center = (width/2, height/2) trace('before instance') self.vc=ViewClient(device, devID) trace('after instance') def start(self): ''' start the contacts activity and set the startStatus True if contacts is ready. ''' trace('Starting activity ...') self.device.startActivity(component=componentName) sleep(2) self.startStatus = self.goList() trace('Contacts is started, checking the contacts status...') self.isReady() sleep(2) def stop(self): ''' stop the contacts activity and set the startStatus False ''' self.device.shell('am force-stop %s' % package) trace('force stop contacts package %s' % package) self.startStatus = False def menu(self): ''' press menu ''' self.device.press('KEYCODE_MENU','DOWN_AND_UP') trace('press menu') def scroll(self,down=True,times=1): ''' scoll up or down for some times then touch the highlight submenu item @type down: boolead @param down: scroll down if True or scroll up @type times: int @param times: how many times to scroll ''' keycode = 'KEYCODE_DPAD_DOWN' if down else 'KEYCODE_DPAD_UP' for i in range(times): self.device.press(keycode,'DOWN_AND_UP') trace('scroll %s' % keycode.split('_')[-1].lower()) self.device.press('KEYCODE_ENTER','DOWN_AND_UP') trace('press Enter') def back(self): ''' press back ''' self.device.press('KEYCODE_BACK','DOWN_AND_UP') trace('press back') def slide(self,str,view=None): ''' slide the screen @type: str @param: 'left','right','up','down' @type view: @param view: specify the view, default to None ''' if str not in ['left','right','up','down']: raise SyntaxError("wrong parameter: choose from 'left','right','up' or 'down'") try: cX,cY = view.getCenter() width = view.getWidth() height = view.getHeight() cL = cX - width/4, cY cR = cX + width/4, cY cU = cX, cY - height/4 cD = cX, cY + height/4 except AttributeError: pass (left, right, up, down) = (cL, cR, cU, cD) if view else (self.left, self.right, self.up, self.down) nav = { 'left':{'start':right,'end':left}, 'right':{'start':left,'end':right}, 'up':{'start':down,'end':up}, 'down':{'start':up,'end':down} } self.device.drag(nav[str]['start'], nav[str]['end'], 0.1, 10) trace('slide the screen from %s to %s ' % (nav[str]['start'],nav[str]['end'])) sleep(2) def getView(self,str,cD=False,iD=False,dump=True,regex=False): ''' get the view with the specified text, content description or viewId @type str: str @param str: the query string @type cD: boolean @param cD: whether handle the query str as content description @type iD: boolean @param iD: whether handle the query str as viewId @type dump: boolean @param dump: whether execute dump before findView, depending on whether the screen is changed @return: the view found ''' if dump: trace('before dump') self.vc.dump() trace('after dump') if cD: view=self.vc.findViewWithContentDescription(str) trace('Query view with content description: %s, return is %s' % (str, view is not None)) return view elif iD: view=self.vc.findViewById(str) trace('Query view by id: %s, return is %s' % (str, view is not None)) return view elif regex: view=self.vc.findViewWithAttributeThatMatches('text',re.compile(str)) trace('Query view that match attribute: %s, return is %s' % (str, view is not None)) return view else: view=self.vc.findViewWithText(str) trace('Query view with text: %s, return is %s ' % (str, view is not None)) return view def isReady(self): ''' check whether the contacts is ready. @return: True ''' while True: view=self.getView('Contacts list is being updated to reflect the change of language.') if not view: trace('Contacts is ready') break else: trace('Contacts is not ready, please wait!') sleep(2) return True def isEmpty(self): ''' check whether the contacts is empty @return: True or False ''' self.check() view=self.getView('No contacts.') if view: trace('Contacts list is empty') return True else: trace('Contacts list is not empty') return False def getCounter(self): ''' get the contacts counter @return: the current contacts counter ''' self.goList() if self.isEmpty(): self.contactCounter=0 else: while True: try: self.contactCounter = int(self.getView('\d+ contacts?',regex=True).getText().split()[0]) break except AttributeError: self.slide('down') sleep(1) trace('current contacts counter is %d' % self.contactCounter) return self.contactCounter def goList(self): ''' check whether the screen is in contacts list view, if not, go list view via pressing back key @return: True ''' while True: view=self.getView("All contacts",cD=True) if not view: self.back() sleep(3) else: if not view.isSelected(): trace('Touch "All contacts"') view.touch() break trace('Goto contacts list view') return True def goEdit(self): ''' check whether the contacts is empty, then select adding and go to edit view. @return: True ''' self.check() try: self.getView('Add Contact',cD=True,dump=False).touch() trace('Touch "Add Contact"') sleep(5) return True except AttributeError: pass try: self.getView('Create a new contact',dump=False).touch() trace('Touch "Create a new contact"') sleep(5) self.getView('Keep local').touch() trace('Select "Keep local"') sleep(5) return True except AttributeError: pass def check(self): ''' check whether the contacts is started before other operation about contacts @return: True ''' if not self.startStatus: trace("Wrong code! please start contacts firstly in you code") raise SyntaxError('contacts should be start firstly!') return True def snapshot(self,title): ''' take snapshot @type title: str @param title: specify the title of snapshot @return: snapshot object ''' snapName = title + '.png' snapFolder = 'snapshot' os.system('if not exist %s\\%s mkdir %s\\%s' % (logPath, snapFolder, logPath, snapFolder)) snapFile = logPath + '\\' + snapFolder + '\\' + snapName result = self.device.takeSnapshot().getSubImage(self.snap_rect) trace('take snapshot without the statusbar') result.writeToFile(snapFile,'png') trace('save the snapshot to file: %s ' % snapFile) return result def wipe(self,view): ''' wipe the text in specified view ''' try: self.device.drag(view.getXY(),view.getXY(),1,1) trace('wipe text: %s' % str(view.getText())) self.device.press('KEYCODE_DEL','DOWN_AND_UP') except: Exception('wipe failed') def addContact(self,name='',phone='',email='',address=''): self.goEdit() try: offset = 0 if name: view=self.getView('id/no_id/27',iD=True) trace('type %s' % name) view.type(name) view.touch() if phone: view=self.getView('id/no_id/46',iD=True,dump=False) trace('type %s' % phone) view.type(phone) offset += 4 sleep(2) if email: view=self.getView('id/no_id/' + str(57 + offset), iD=True) trace('type %s' % email) view.type(email) offset += 4 sleep(2) if address: view=self.getView('id/no_id/' + str(68 + offset), iD=True) trace('type %s' % address) view.type(address) sleep(2) view=self.getView('Done',dump=False) view.touch() trace('Touch Done') finally: sleep(5) self.goList() def goEditExistContact(self,searchInfo): ''' go to Edit view of exist contact @type searchInfo: str @param searchInfo: information of contacts @return:True ''' trace('Search a contact to edit') view=self.search(searchInfo) if not view: raise SyntaxError('No '+searchInfo+' contact to edit') view.touch() sleep(4) self.device.press('KEYCODE_MENU') sleep(2) self.device.press('KEYCODE_DPAD_DOWN') sleep(1) self.device.press('KEYCODE_ENTER') sleep(4) return True def editName(self,name): ''' edit Name details of contacts @type name: str @param name: content of Name @return: True ''' #find EditText of Name view = self.getView('id/no_id/27',iD=True) #edit name self.wipe(view) view.type(name) sleep(1) trace("edit contact's name OK") return True def editCompany(self,company): ''' edit Company details of contacts @type company: str @param company: content of Company @return: True ''' view=self.getView('Add organization') if view: trace('Step: add a organization info') view.touch() sleep(1) trace('add the company info') self.device.type(company) sleep(1) else: trace('Step: Edit the organization info') view=self.getView('id/no_id/42',iD=True) self.wipe(view) trace('Edit the company info') self.device.type(company) sleep(1) return True def editDetails(self,contactsInfo,action='update',**editInfo): ''' edit details of contact with add or update @type contactsInfo: str @param contactsInfo: information of contacts @type action: str @param action: 'add' or 'update' details @type editInfo: str @param editInfo: collect all need edit information @return: True ''' self.goEditExistContact(contactsInfo) for fieldName in editInfo: if fieldName not in ['Name','Phone','Email','Address','Company','Website','Nickname','Notes']: raise SyntaxError("wrong parameter: fieldName choose from 'Name','Phone','Email','Address','Company','Website','Nickname','Notes'") if 'update'==action: for updateField in editInfo: if 'Name' == updateField: self.editName(editInfo[updateField]) elif 'Company' == updateField: self.editCompany(editInfo[updateField]) else: self.updateDetails(updateField,editInfo[updateField]) if 'add'==action: for addField in editInfo: if 'Name' == addField: self.editName(editInfo[addField]) elif 'Company' == addField: self.editCompany(editInfo[addField]) else: self.addDetails(addField,editInfo[addField]) self.getView('Done').touch() trace('Click Done') sleep(3) self.goList() return True def addDetails(self,fieldName,content): ''' add details of 'fieldName' with 'content' @type fieldName: str @param fieldName: name of field that will be eidt , e.g: Phone,Email,etc @type content: str @param content: edit content @return:True ''' trace('edit '+fieldName+ ' with add') #touch 'Add another field' while True: try: self.getView('Add another field').touch() sleep(3) break except AttributeError: self.slide('up') sleep(2) #touch fieldName and edit while True: try: self.getView(fieldName).touch() sleep(2) break except AttributeError: view2 = self.getView('id/no_id/2',iD=True,dump=False) self.slide('up',view2) sleep(1) self.device.type(content) sleep(1) trace('edit '+fieldName+' with add OK') return True def updateDetails(self,fieldName,content): ''' update details of 'fieldName' with 'content' @type fieldName: str @param fieldName: name of field that will be eidt , e.g: Phone,Email,etc @type content: str @param content: edit content @return:True ''' trace('Edit field '+fieldName+' info') #find fieldName while not self.getView(fieldName): self.slide('up') sleep(2) #get editView of fieldName view = self.getView(fieldName,dump=False) view2=self.getView(view.getId()[:-2]+str(int(view.getId()[-2:])+6),iD=True) #wipe old content and update with new content self.wipe(view2) sleep(1) view2.type(content) sleep(1) return True def search(self,str): ''' search contact by keyword @type str: str @param str: specify the search keyword @return: the view of search result if search result is not null, else return False ''' trace("start searching...") try: self.getView("Search",True).touch() sleep(2) self.device.type(str) trace("search keyword is: "+str) except AttributeError: if self.isEmpty(): trace("No contacts exist") else: trace("No contacts searched") return False #the id of 1st search result is always 28 return self.getView("id/no_id/28",iD=True) def sortAndViewAs(self, sort=True, first=True): ''' sort and view contact name @type sort: boolean @param sort: whether sort contact name or view contact @type first: boolean @param first: whether sort and view contact by first name or last name @return: boolean ''' trace("start sorting...") self.menu() self.scroll(times=4) sleep(2) sortOrView="Sort list by" if sort else "View contact names as" firstOrLast="First name*" if first else "Last name*" try: self.getView(sortOrView).touch() sleep(1) self.getView(firstOrLast,regex=True).touch() return True except AttributeError: return False finally: self.goList() def favor(self,str,favor=True): ''' add or cancel contact to favorites @type str: str @param str: specify the search string @type favor: boolean @param favor: add if True ''' try: self.search(str).touch() sleep(3) except AttributeError: trace('no matched contact found, operation failed!') self.goList() return False aim, action = ('Add to favorites', 'add') if favor else ('Remove from favorites', 'remov') try: self.getView(aim, cD=True).touch() trace('%s successfully' % aim) except AttributeError: trace('%s has been %sed in favorites, not have to %s repeatedly' % (str, action, action)) sleep(3) self.goList() return True def delete(self,kwd = ''): '''delete one contact @type kwd: string @param kwd: keyword which contact to be delete, if none,delete first contact @return: True if operate sucess, False if operate fail. ''' if self.isEmpty(): trace('Could not find any contact data,no record!') return False find = self.search(kwd) if kwd else self.getView('id/no_id/27',iD=True,dump=False) try: # delete operate find.touch() sleep(4) trace('show contact detail information') self.menu() sleep(3) self.scroll(times=3) trace('choose delete contact') self.getView('OK').touch() sleep(3) return True except AttributeError: return False finally: self.goList()