Example #1
0
def main(argv):
    # simple command line parameter support. only [-f ini_file] [-h] support
    # usage = "usage: %prog [options]"
    #
    # parser = argparse.ArgumentParser()
    # parser.add_argument("echo")
    # args = parser.parse_args()
    # print args.echo
    # parser = OptionParser(usage)
    #    parser.add_option("-f", "--file", dest="scptfilename",  \
    #              help="specify script file to run", metavar="FILE")
    #    parser.add_option("-r", "--reference", \
    #              help="list fw usage keywords and examples")
    #    (options, args) = parser.parse_args()
    #    if len(args)==0:
    #        parser.print_help()
    #        return
    #    print options
    #    scptfilename=options.scptfilename
    #    print scptfilename

    deviceIds = Shell().getShellCmdOutput(r"adb devices")
    # deviceIdList = filter(lambda x: len(x) > 0, devices.split('\n'))  # .split('\t',1)[0]
    deviceId = None
    connected_RE = re.compile("^\S+\t*device$")
    for line in deviceIds.split('\n'):
        # if deviceIdList[i].strip() == 'List of devices attached':
        #     print 'list start'
        #     deviceIdList = deviceIdList[i+1:]
        #     break
        if connected_RE.match(line):
            deviceId = line.split('\t', 1)[0]
    if deviceId is None:
        print "device/emulator not found. Please check the USB connection or start the emulator and try again."
        return
    # print("Got device %s." % deviceId)

    idev = iDevice(deviceId)
    try_count = 0
    tv = None

    while tv is None:
        if try_count == 0:
            vtext = raw_input("please enter the view text you are looking for:")
        else:
            vtext = raw_input('Sorry, The view was not found. Please check the text in the screen'
                              ' and try again [Q|q to exit]:')
        if vtext.lower() == 'q':
            return
        idev.vc.dump()
        tv = idev.vc.findViewWithText(vtext)
        try_count += 1

    print "The view's id is:", tv.getId()
    # print "target view's tag is:", tv.getTag()

    idev.vc.findViewsWithSameId(tv, [tv])
Example #2
0
def getDeviceIdList():
    devices = Shell().getShellCmdOutput(r"adb devices")  # |awk -F'\t' '{print $1}'
    print devices
    deviceIdList = []  # filter(lambda x: len(x) > 0, devices.split('\n'))  # .split('\t',1)[0]
    connected_RE = re.compile("^\S+\t*device$")
    for line in devices.split('\n'):
        # if deviceIdList[i].strip() == 'List of devices attached':
        #     print 'list start'
        #     deviceIdList = deviceIdList[i+1:]
        #     break
        if connected_RE.match(line):
            deviceIdList.append(line.split('\t', 1)[0])
    if len(deviceIdList) > 0:
        printLog('List of devices attached: \n' + str(deviceIdList))
    return deviceIdList
Example #3
0
def __getDeviceInfo(deviceId, propName):
    cmd = "adb -s " + deviceId + " shell getprop | awk -F':' '/" + propName + "/ { print $2 }'|tr -d '[] '"
    # add alarm to detect timeout
    shell = Shell()
    counter = 0
    while counter < 2:
        try:
            with time_limit(FETCH_DEVICEINFO_TIMEOUT):
                output = shell.getShellCmdOutput(cmd).splitlines()
                if len(output) > 0:
                    return output[0].strip()
                else:
                    return 'UNKNOWN'
        except TimeoutException:
            printLog("Timed out! Failed to retrieve device info.", logging.ERROR)
            # todo: reboot device or emulator
            output = shell.getShellCmdOutput('adb reboot')
            time.sleep(20)
            counter += 1
Example #4
0
    def __init__(self):

        # device = TestDevicePool().getDevice()
        # if device is None:
        #     print("NO IDLE DEVICE AVAILABLE. TERMINATE.")
        #     assert False
        # # self.threadName='<'+self.device.model+'_'+self.device.deviceId+'> '
        # print("Got device %s." % device.deviceId)
        devices = Shell().getShellCmdOutput(r"adb devices")
        # deviceIdList = filter(lambda x: len(x) > 0, devices.split('\n'))  # .split('\t',1)[0]
        deviceIdList = []  # filter(lambda x: len(x) > 0, devices.split('\n'))  # .split('\t',1)[0]
        connected_RE = re.compile("^\S+\t*device$")
        for line in devices.split("\n"):
            # if deviceIdList[i].strip() == 'List of devices attached':
            #     print 'list start'
            #     deviceIdList = deviceIdList[i+1:]
            #     break
            if connected_RE.match(line):
                deviceIdList.append(line.split("\t", 1)[0])

        if len(deviceIdList) > 0:
            print ("List of devices:")
            for j in range(len(deviceIdList)):
                print ("%d: %s\n" % (j, deviceIdList[j]))
            try:
                # connect device
                self.adbc, self.serial_no = ViewClient.connectToDeviceOrExit(verbose=DEBUG, serialno=deviceIdList[0])
                print "device %s connected." % self.serial_no
                self.devices = self.adbc.getDevices()
                for device in self.devices:
                    print device.serialno
            except:
                traceback.print_exc()
                raise RuntimeError("cannot connect to device.")
        else:
            raise RuntimeError("cannot find device.")
Example #5
0
    def __init__(self, suite=DEFAULT_TEST_SUITE, buildnum=0):
        """
        constructor.
        """

        self.test_buildnum = buildnum
        """ the build number to verify """
        self.test_suite = suite
        """ the suite to test"""

        self.Pass = 0
        """ Passed testcase number"""
        self.Fail = 0
        """ failed testcase number """
        self.Total = 0
        """ total testcase number """
        self.ALTList = []
        """ activity launch time list """
        self.exception_map_list = [{}, {}]
        """ app exception map list: one keeps formulated exceptions and the other keeps raw exceptions """
        self.start_time = None
        """ test start time"""
        self.end_time = None
        """ test finish time"""
        self.shell = Shell()
        """ Shell object """
        # do environment validation
        if not path.isdir(TC_DIR):
            print ("Required directory %s does not exist. please check and run again." % TC_DIR)
            return
        if not path.isdir(TS_DIR):
            print ("Required directory %s does not exist. please check and run again." % TS_DIR)
            return
        if not path.isdir(SNAPSHOT_DIR):
            mkdir(SNAPSHOT_DIR)
        # remove old log file
        if path.isfile(TESTER_DEBUG_LOG_FILE):
            if Tester.DEBUG == logging.DEBUG:
                print ("Removing old log file...")
            remove(TESTER_DEBUG_LOG_FILE)
        # truncate_file(TESTER_DEBUG_LOG_FILE)

        # create new log file
        # Oct 21: need to assign a different logger id each time, otherwise it will use the existing one
        # which will be closed at the end of run()
        self.logHandler = createLogger(Tester.DEBUG)
        """ log file handler """
        # get device, by default get the connected Genymotion device
        self.device = None
        self.device = TestDevicePool().getDevice()  # make='Genymotion')
        """ test device """
        if self.device is None:
            raise EnvironmentError("[Tester] NO DEVICE OR MORE THAN ONE DEVICE FOUND. QUIT.")

        if Tester.DEBUG == logging.DEBUG:
            printLog("[Tester] FOUND DEVICE.", logging.DEBUG)

        if Tester.GET_BUILD:
            if not self.getBuild():
                raise EnvironmentError("[Tester] Get build failed.")
        # build testcase pool
        self.testPool = TestCasePool.fromSuite(self.test_suite)
        """ testcase pool for current test run """
        if len(self.testPool) == 0:
            raise EnvironmentError("[Tester] NO TESTCASE IN THE TEST SUITE. QUIT.")
Example #6
0
class Tester:
    """ The Tester class plays a tester role -- It manages test build, testcase,
    test devices, and test results. It uses AppTestRunner to execute testcases.
    """

    EXCEPTION_AGGREGATION_MODE = 0
    """ 0: use thread/class as key, 1: use exception as key"""
    GET_BUILD = True
    """ used to control if tester gets the build file before test starts, or use the installed build in test"""
    DEBUG = logging.NOTSET
    """ control log verbosity"""

    def __init__(self, suite=DEFAULT_TEST_SUITE, buildnum=0):
        """
        constructor.
        """

        self.test_buildnum = buildnum
        """ the build number to verify """
        self.test_suite = suite
        """ the suite to test"""

        self.Pass = 0
        """ Passed testcase number"""
        self.Fail = 0
        """ failed testcase number """
        self.Total = 0
        """ total testcase number """
        self.ALTList = []
        """ activity launch time list """
        self.exception_map_list = [{}, {}]
        """ app exception map list: one keeps formulated exceptions and the other keeps raw exceptions """
        self.start_time = None
        """ test start time"""
        self.end_time = None
        """ test finish time"""
        self.shell = Shell()
        """ Shell object """
        # do environment validation
        if not path.isdir(TC_DIR):
            print ("Required directory %s does not exist. please check and run again." % TC_DIR)
            return
        if not path.isdir(TS_DIR):
            print ("Required directory %s does not exist. please check and run again." % TS_DIR)
            return
        if not path.isdir(SNAPSHOT_DIR):
            mkdir(SNAPSHOT_DIR)
        # remove old log file
        if path.isfile(TESTER_DEBUG_LOG_FILE):
            if Tester.DEBUG == logging.DEBUG:
                print ("Removing old log file...")
            remove(TESTER_DEBUG_LOG_FILE)
        # truncate_file(TESTER_DEBUG_LOG_FILE)

        # create new log file
        # Oct 21: need to assign a different logger id each time, otherwise it will use the existing one
        # which will be closed at the end of run()
        self.logHandler = createLogger(Tester.DEBUG)
        """ log file handler """
        # get device, by default get the connected Genymotion device
        self.device = None
        self.device = TestDevicePool().getDevice()  # make='Genymotion')
        """ test device """
        if self.device is None:
            raise EnvironmentError("[Tester] NO DEVICE OR MORE THAN ONE DEVICE FOUND. QUIT.")

        if Tester.DEBUG == logging.DEBUG:
            printLog("[Tester] FOUND DEVICE.", logging.DEBUG)

        if Tester.GET_BUILD:
            if not self.getBuild():
                raise EnvironmentError("[Tester] Get build failed.")
        # build testcase pool
        self.testPool = TestCasePool.fromSuite(self.test_suite)
        """ testcase pool for current test run """
        if len(self.testPool) == 0:
            raise EnvironmentError("[Tester] NO TESTCASE IN THE TEST SUITE. QUIT.")

    def __del__(self):
        if self.device:
            del self.device
        del self.ALTList
        self.logHandler.close()
        logging.shutdown()

    def __reset(self):
        """
        reset counters and remove result file and temp files
        Note: execution log file is not removed at the beginning of each run, but during the init.
        """
        self.Pass = 0
        self.Fail = 0
        self.Total = 0
        self.ALTList = []
        self.start_time = None
        self.end_time = None

        # remove old result file
        if path.isfile(self.test_suite + ".txt"):
            print "Removing old result file %s ..." % (self.test_suite + ".txt")
            remove(self.test_suite + ".txt")
        if path.isfile(APPLOG_FILE):
            print "Removing old app log file %s ..." % APPLOG_FILE
            remove(APPLOG_FILE)
        if path.isfile(ADBLOG_FILE):
            print "Removing old ADB log file %s ..." % ADBLOG_FILE
            remove(ADBLOG_FILE)
        # remove temp png files
        self.shell.runShellCmd(r"rm *.png")
        self.shell.runShellCmd(r"rm %s/*.png" % SNAPSHOT_DIR)
        # reset test pool status
        for tc in self.testPool:
            tc.result = TestStatus.NotRun
            tc.crash = False

    def getBuild(self):
        """
        get the specified build file to current directory
        this is an abstract method. subclasses should implement it.
        """
        raise NotImplementedError("Please implement getBuild()!")

    def generateTestReport(self):
        """
        generate test report content
        this is an abstract method. subclasses should implement it.
        """
        raise NotImplementedError("Please implement generateTestReport()!")

    def scanExceptionInAppLog(self, file_path):
        """
        scan the app log for exceptions, and parse them into lists of exception, class and line numbers
        this is an abstract method. subclasses should implement it.
        @param file_path: file path (string)
        @return: two maps: one keeps formulated exceptions and the other keeps raw exceptions
        @rtype list
        """
        raise NotImplementedError("Please implement scanExceptionInAppLog()!")

    @staticmethod
    def __convertTime(rawtime):
        """
        split the minute part from second part, and convert to launch time in seconds.
        the input raw time may contain seconds and milliseconds, e.g. 1s12ms (2014-07-22)
        @param rawtime: raw time string
        @return: the processed time string
        """
        # printLog('[getTime] raw time: %s'% rawtime)
        # remove the trailing '\n' and 'ms'
        rawtime = rawtime.split("m")[0]
        # rawtime=rawtime[0:(len(rawtime)-2)]
        # printLog('[getTime] stripped raw time: %s'% rawtime)
        if not rawtime.isdigit():
            sec, ms = rawtime.split("s")
            rawtime = str(int(sec) * 1000 + int(ms))
            # printLog('[getTime] converted time: %s(ms)' % rawtime)
        return rawtime

    @staticmethod
    def getLaunchTime(fname):
        """
        scan logcat file and retrieve activity launch time data
        2015-09-01: refactored to remove the dependency to external shell script
        @param fname: the logcat filename
        @return: a list of activities and their launch time
        """
        if not os.path.isfile(fname):
            return ""

        ALTList = []
        LT_RE = re.compile("^I/ActivityManager\(\s*\d+\): Displayed {}/(\S+): \+(\S+)\s*$".format(APP_PKG_NAME))

        try:
            with open(ADBLOG_FILE, "r") as fd:
                lines = filter(lambda x: not x.startswith("\n") and APP_PKG_NAME in x, fd.readlines())
                for line in lines:
                    # printLog('[getLaunchTime] current line: %s'% line)
                    if LT_RE.match(line):
                        activity, ltime = LT_RE.search(line).groups()
                        ltime = Tester.__convertTime(ltime.rstrip("\n"))
                        # Oct 23: changed method to get activity name and time
                        # use ':' to split columns in get_ALT.sh and '+' to split
                        # activity name and launch time
                        ALTList.append((activity, ltime))
        except Exception, e:
            printLog(
                "[getLaunchTime] Caught exception while writing launch time data to file: %s" % e.message, logging.ERROR
            )
        finally: