def switch_window(self, page):
        if self.new_window_flag:
            if page in list(self.pages):
                page = '通用'
                g.current_page = '通用'
            self.new_window_flag = False

        if page != '通用':
            if page not in list(self.pages):
                # 如果当前页未注册,则需要先清除和当前窗口绑定的页面
                for k in list(self.pages):
                    if self.current_window == self.pages[k]:
                        self.pages.pop(k)
                # 在把当前窗口捆定到当前页面
                self.pages[page] = self.current_window

            elif self.pages[page] != self.current_window:
                # 如果当前窗口为 HOME,则关闭之
                if self.current_window == 'HOME':
                    g.driver.close()
                    self.windows.pop('HOME')
                # 再切换到需要操作的窗口
                tw = self.windows[self.pages[page]]
                logger.info('--- Switch Windows: %s' % repr(tw))
                g.driver.switch_to_window(tw)
                self.current_window = self.pages[page]
                logger.info('--- Current Windows: %s' %
                            repr(self.current_window))
 def close(self):
     all_handles = g.driver.window_handles
     for handle in all_handles:
         # 切换到每一个窗口,并关闭它
         g.driver.switch_to_window(handle)
         g.driver.close()
         logger.info('--- Close th Windows: %s' % repr(handle))
 def current_url(cls, data, output):
     logger.info('DATA:%s' % repr(data['text']))
     logger.info('REAL:%s' % repr(g.driver.current_url))
     if data['text'].startswith('*'):
         assert data['text'][1:] in g.driver.current_url
     else:
         assert data['text'] == g.driver.current_url
     # 只能获取到元素 url
     for key in output:
         g.var[key] = g.driver.current_url
 def title(cls, data, output):
     logger.info('DATA:%s' % repr(data['text']))
     logger.info('REAL:%s' % repr(g.driver.title))
     if data['text'].startswith('*'):
         assert data['text'][1:] in g.driver.title
     else:
         assert data['text'] == g.driver.title
     # 只能获取到元素标题
     for key in output:
         g.var[key] = g.driver.title
    def run(self, sheet_name):
        # 1.从 Excel 获取测试用例集
        try:
            data = self.testcase_workbook.read(sheet_name)
            testsuite = testsuite_format(data)
            logger.info('Testsuite imported from Excel:\n' +
                        json.dumps(testsuite, ensure_ascii=False, indent=4))
            logger.info('From Excel import testsuite success')
        except:
            logger.exception('*** From Excel import testsuite fail ***')
            self.code = -1
            sys.exit(self.code)

        # 2.初始化全局对象
        try:
            g.init(self.desired_caps, self.server_url)
            g.set_driver()
            # 如果测试数据文件存在,则从该文件里读取数据,赋值到全局变量列表里
            data_file = Path('data') / (g.plan_name + '-' + sheet_name +
                                        '.csv')
            if data_file.is_file():
                g.var = get_record(str(data_file))
            w.init()
        except:
            logger.exception('*** Init global object fail ***')
            self.code = -1
            sys.exit(self.code)

        # 3.解析测试用例集
        try:
            parse(testsuite)
            logger.debug('testsuite has been parsed:\n' + str(testsuite))
        except:
            logger.exception('*** Parse testsuite fail ***')
            self.code = -1
            sys.exit(self.code)

        # 4.执行测试套件
        ts = TestSuite(testsuite, sheet_name, self.report_ts[sheet_name],
                       self.conditions)
        ts.run()

        # 5.判断测试结果
        if self.report_ts[sheet_name].high_errors + self.report_ts[sheet_name].medium_errors + \
                self.report_ts[sheet_name].high_failures + self.report_ts[sheet_name].medium_failures:
            self.code = -1

        # 6.保存测试结果
        try:
            self.report_data[sheet_name] = testsuite2report(testsuite)
            data = testsuite2data(testsuite)
            self.report_workbook.write(data, sheet_name)
        except:
            logger.exception('*** Save the report is fail ***')
def check(step):
    data = step['data']
    if not data:
        data = step['expected']

    element = step['element']
    element_location = locating_element(element)
    if '#' in element:
        e_name = element.split('#')[0] + '#'
    else:
        e_name = element
    by = e.elements[e_name]['by']
    output = step['output']

    if by in ('title', 'current_url'):
        getattr(Common, by)(data, output)

    else:
        for key in data:
            # 预期结果
            expected = data[key]
            # 切片操作处理
            s = re.findall(r'\[.*?\]', key)
            if s:
                s = s[0]
                key = key.replace(s, '')

            if key == 'text':
                real = element_location.text
            else:
                real = element_location.get_attribute(key)
            if s:
                real = eval('real' + s)

            logger.info('DATA:%s' % repr(expected))
            logger.info('REAL:%s' % repr(real))
            compare(expected, real)

        # 获取元素其他属性
        for key in output:
            if output[key] == 'text':
                g.var[key] = element_location.text
            elif output[key] in ('text…', 'text...'):
                if element_location.text.endswith('...'):
                    g.var[key] = element_location.text[:-3]
                else:
                    g.var[key] = element_location.text
            else:
                g.var[key] = element_location.get_attribute(output[key])
def message(step):
    data = step['data']
    text = data.get('text', '')
    element = step['element']
    value = e.get(element)[1]

    if value.lower() in ('确认', 'accept', '确定'):
        g.driver.switch_to_alert().accept()
    elif value.lower() in ('取消', '关闭', 'cancel', 'close'):
        g.driver.switch_to_alert().dismiss()
    elif value.lower() in ('输入', 'input'):
        g.driver.switch_to_alert().send_keys(text)
        g.driver.switch_to_alert().accept()
    logger.info('--- Switch Frame: Alert')
    w.frame = 'Alert'
Пример #8
0
def sql(step):
    element = step['element']
    _sql = e.get(element)[1]

    logger.info('SQL: %s' % repr(_sql))
    # 获取连接参数
    value = e.get(step['page'] + '-' + 'config')[1]
    arg = data_format(value)

    if step['page'] not in g.db.keys():
        g.db[step['page']] = DB(arg)
    if _sql.lower().startswith('select'):
        row = g.db[step['page']].fetchone(_sql)
        logger.info('SQL result: %s' % repr(row))
        if not row:
            raise Exception('*** Fetch None ***')
    else:
        g.db[step['page']].execute(_sql)

    result = {}
    if _sql.lower().startswith('select'):
        keys = _sql[6:].split('FROM')[0].split('from')[0].strip().split(',')
        for i, k in enumerate(keys):
            keys[i] = k.split(' ')[-1]
        result = dict(zip(keys, row))
        logger.info('keys result: %s' % repr(result))

    data = step['data']
    if not data:
        data = step['expected']
    if data:
        for key in data:
            sv, pv = data[key], result[key]
            logger.info('key: %s, expect: %s, real: %s' %
                        (repr(key), repr(sv), repr(pv)))

            compare(sv, pv)

    output = step['output']
    if output:
        logger.info('output: %s' % repr(output))
        for key in output:
            g.var[key] = result[output[key]]
Пример #9
0
def tab_name(step):
    element = step['element']
    name = step['data']['text']
    # 从所有窗口中查找给定元素,如果查询到就命名,否则报错
    all_handles = g.driver.window_handles
    logger.info('All Handles: %s' % all_handles)

    flag = False
    for handle in all_handles:
        #logger.info('Page Source: %s \n%s' % (handle, g.driver.page_source))
        #logger.info('All Windows: %s' %w.windows)
        if handle not in w.windows.values():
            # 切换至此窗口
            g.driver.switch_to_window(handle)
            try:
                # 成功定位到关键元素
                element_location = locating_element(element, 'CLICK')
                # 添加到窗口资源池 g.windows
                w.windows[name] = handle
                # 把当前窗口名字改为新窗口名称
                w.current_window = name
                flag = True
                logger.info('Current Window: %s' % repr(name))
                logger.info('Current Handle: %s' % repr(handle))
            except Exception as exception:
                pass
    if not flag:
        raise Exception(
            'Tab Name Fail: the element:%s in all tab is not found' % element)
 def switch_frame(self, frame):
     if frame.strip():
         frame = [x.strip() for x in frame.split('|')]
         if frame != self.frame:
             if self.frame != 0:
                 g.driver.switch_to.default_content()
             for f in frame:
                 logger.info('--- Frame Value:  %s' % repr(f))
                 if f.startswith('#'):
                     f = int(f[1:])
                 elif '#' in f:
                     from rill_framework.testcase import elements_format
                     from rill_framework.locator import locating_element
                     element = elements_format('通用', f)[2]
                     f = locating_element(element)
                 logger.info('--- Switch Frame: %s' % repr(f))
                 g.driver.switch_to.frame(f)
             self.frame = frame
     else:
         if self.frame != 0:
             g.driver.switch_to.default_content()
             self.frame = 0
Пример #11
0
    def setup(self, testcase, case):
        logger.info('Start running the SETUP testcase...')
        # setup 执行成功标记

        def run_setup(testcase):
            if testcase:
                tc = TestCase(testcase)
                tc.run()
                if testcase['result'] == 'Pass':
                    flag = 'Y'
                else:
                    flag = 'N'
            else:
                flag = 'O'
            return flag

        setup_flag = run_setup(self.setup_testcase)

        if setup_flag == 'N':
            base_flag = run_setup(self.base_testcase)
            if base_flag == 'Y':
                setup_flag = run_setup(self.setup_testcase)
                if setup_flag == 'N':
                    testcase['result'] = 'Block'
                    case.block('Blocked', 'SETUP is not Pass')
                    logger.warn('Run the testcase: %s|%s Blocked, SETUP is not Pass' % (
                        testcase['id'], testcase['title']))
                    return False
            elif base_flag == 'O':
                testcase['result'] = 'Block'
                case.block('Blocked', 'SETUP is not Pass')
                logger.warn('Run the testcase: %s|%s Blocked, SETUP is not Pass' % (
                    testcase['id'], testcase['title']))
                return False

        return True
 def switch_context(self, context):
     if context.strip() == '':
         context = 'NATIVE_APP'
     logger.info('--- ALL   Contexts:%s' % g.driver.contexts)
     logger.info('--- Input  Context:%s' % repr(context))
     if context != self.current_context:
         if context == '':
             context = None
         logger.info('--- Switch Context:%s' % repr(context))
         g.driver.switch_to.context(context)
         self.current_context = context
Пример #13
0
def request(kw, step):
    element = step['element']
    url = e.get(element)[1]
    if url.startswith('/'):
        url = url[1:]

    data = step['data']
    _data = {}
    _data['headers'] = json2dict(data.pop('headers', '{}'))
    if data.get('cookies'):
        data['cookies'] = json2dict(data['cookies'])
    if kw == 'get':
        _data['params'] = json2dict(data.pop('params', '{}')) or json2dict(data.pop('data', '{}'))
    elif kw == 'post':
        _data['data'] = json2dict(data.pop('data', '{}'))
        _data['json'] = json2dict(data.pop('json', '{}'))
        _data['files'] = eval(data.pop('files', 'None'))
    elif kw in ('put', 'patch'):
        _data['data'] = json2dict(data.pop('data', '{}'))

    for k in data:
        for s in ('{', '[', 'False', 'True'):
            if s in data[k]:
                try:
                    data[k] = eval(data[k])
                except:
                    logger.warning('Try eval data fail: %s' %data[k])
                break
    expected = step['expected']
    expected['status_code'] = expected.get('status_code', None)
    expected['text'] = expected.get('text', None)
    expected['json'] = json2dict(expected.get('json', '{}'))
    expected['cookies'] = json2dict(expected.get('cookies', '{}'))
    expected['headers'] = json2dict(expected.get('headers', '{}'))

    if not g.http.get(step['page']):
        g.http[step['page']] = Http(step)
    http = g.http[step['page']]

    if kw == 'post':
        if http.headers_post:
            http.r.headers.update(eval(http.headers_post))
    else:
        if http.headers_get:
            http.r.headers.update(eval(http.headers_get))

    logger.info('URL: %s' % http.baseurl + url)

    # 处理 before_send
    before_send = data.pop('before_send', '')
    if before_send:
        _data, data = getattr(http_handle, before_send)(kw, _data, data)
    else:
        _data, data = getattr(http_handle, 'before_send')(kw, _data, data)

    if _data['headers']:
        for k in [x for x in _data['headers']]:
            if not _data['headers'][k]:
                del http.r.headers[k]
                del _data['headers'][k]
        http.r.headers.update(_data['headers'])

    if kw == 'get':
        r = getattr(http.r, kw)(http.baseurl + url,
                                params=_data['params'], **data)
    elif kw == 'post':
        r = getattr(http.r, kw)(http.baseurl + url,
            data=_data['data'], json=_data['json'], files=_data['files'], **data)
    elif kw in ('put', 'patch'):
        r = getattr(http.r, kw)(http.baseurl + url,
            data=_data['data'], **data)
    elif kw in ('delete', 'options'):
        r = getattr(http.r, kw)(http.baseurl + url, **data)

    logger.info('status_code: %s' % repr(r.status_code))
    try: # json 响应
        logger.info('response json: %s' % repr(r.json()))
    except: # 其他响应
        logger.info('response text: %s' % repr(r.text))

    response = {'status_code': r.status_code, 'headers':r.headers,
                '_cookies': r.cookies, 'content': r.content, 'text': r.text}

    try:
        response['cookies'] = requests.utils.dict_from_cookiejar(r.cookies)
    except:
         response['cookies'] = r.cookies

    try:
        j = r.json()
        response['json'] = j
    except:
        response['json'] = {}

    # 处理 after_receive
    after_receive = expected.pop('after_receive', '')
    if after_receive:
        response = getattr(http_handle, after_receive)(response)
    else:
        response = getattr(http_handle, 'after_receive')(response)

    if expected['status_code']:
        assert str(expected['status_code']) == str(response['status_code'])

    if expected['text']:
        if expected['text'].startswith('*'):
            assert expected['text'][1:] in response['text']
        else:
            assert expected['text'] == response['text']

    if expected['headers']:
        result = check(expected['headers'], response['headers'])
        if result['result']:
            step['remark'] += str(result['result'])
        logger.info('headers check result: %s' % result)
        assert result['code'] == 0

    if expected['cookies']:
        logger.info('response cookies: %s' % response['cookies'])
        result = check(expected['cookies'], response['cookies'])
        if result['result']:
            step['remark'] += str(result['result'])
        logger.info('cookies check result: %s' % result)
        assert result['code'] == 0

    if expected['json']:
        result = check(expected['json'], response['json'])
        if result['result']:
            step['remark'] += str(result['result'])
        logger.info('json check result: %s' % result)
        assert result['code'] == 0

    output = step['output']
    # if output:
    #     logger.info('output: %s' % repr(output))

    for k, v in output.items():
        if v == 'status_code':
            g.var[k] = response['status_code']
            logger.info('%s: %s' %(k, repr(g.var[k])))
        elif v == 'text':
            g.var[k] = response['text']
            logger.info('%s: %s' %(k, repr(g.var[k])))
        elif k == 'json':
            sub = json2dict(output.get('json', '{}'))
            result = check(sub, response['json'])
            # logger.info('Compare json result: %s' % result)
            g.var = dict(g.var, **result['var'])
            logger.info('json var: %s' %(repr(result['var'])))
        elif k == 'cookies':
            sub = json2dict(output.get('cookies', '{}'))
            result = check(sub, response['cookies'])
            # logger.info('Compare json result: %s' % result)
            g.var = dict(g.var, **result['var'])
            logger.info('cookies var: %s' %(repr(result['var'])))
Пример #14
0
    def run(self):
        logger.info('Run the TestCase: %s|%s' %
                    (self.testcase['id'], self.testcase['title']))
        self.testcase['result'] = 'Pass'
        self.testcase['report'] = ''
        if_result = ''

        for index, step in enumerate(self.testcase['steps']):
            # 统计开始时间
            step['start_timestamp'] = timestamp()

            # if 为否,不执行 then 语句
            if step['control'] == '>' and not if_result:
                step['score'] = '-'
                continue

            # if 为真,不执行 else 语句
            if step['control'] == '<' and if_result:
                step['score'] = '-'
                continue

            logger.info('Run the Step: %s|%s|%s' %
                        (step['no'], step['keyword'], step['element']))

            step['page'], step['custom'], step['element'] = elements_format(
                step['page'], step['element'])
            try:
                after_function = step['data'].pop('AFTER_FUNCTION', '')
                # 变量替换
                replace_dict(step['data'])
                replace_dict(step['expected'])

                step['data'].pop('BEFORE_FUNCTION', '')

                if isinstance(step['element'], str):
                    step['element'] = replace(step['element'])
                elif isinstance(step['element'], list):
                    for i in range(len(step['element'])):
                        step['element'][i] = replace(step['element'][i])

                step['vdata'] = v_data(step['data'])

                # 处理强制等待时间
                t = step['data'].pop('等待时间', 0)
                sleep(float(t))

                if g.platform.lower() in (
                        'desktop', ) and step['keyword'] in web_keywords:
                    if step['keyword'] not in ('MESSAGE', '对话框'):
                        # 判断页面是否已和窗口做了关联,如果没有,就关联当前窗口,如果已关联,则判断是否需要切换
                        w.switch_window(step['page'])
                        # 切换 frame 处理,支持变量替换
                        frame = replace(step['custom'])
                        w.switch_frame(frame)

                    # 根据关键字调用关键字实现
                    getattr(web, step['keyword'].lower())(step)

                elif g.platform.lower() in (
                        'ios',
                        'android') and step['keyword'] in mobile_keywords:
                    # 切換 context 處理
                    context = replace(step['custom']).strip()
                    w.switch_context(context)

                    if w.current_context.startswith('WEBVIEW'):
                        # 切换标签页
                        tab = step['data'].get('标签页')
                        if tab:
                            del step['data']['标签页']
                            g.driver.switch_to_window(w.windows[tab])
                        logger.info('Current Context: %s' %
                                    repr(w.current_context))

                    # 根据关键字调用关键字实现
                    getattr(mobile, step['keyword'].lower())(step)

                elif step['keyword'] in http_keywords:
                    # 根据关键字调用关键字实现
                    getattr(http, step['keyword'].lower())(step)

                elif step['keyword'].lower() == 'execute':
                    if step['page'] in ('SNIPPET', '用例片段'):
                        result, steps = getattr(common,
                                                step['keyword'].lower())(step)
                        self.testcase['result'] = result
                        self.snippet_steps[index + 1] = steps
                        if result != 'Pass':
                            break
                    # elif step['page'] in ('SCRIPT', '脚本'):
                    #     # 判断页面是否已和窗口做了关联,如果没有,就关联当前窗口,如果已关联,则判断是否需要切换
                    #     w.switch_window(step['page'])
                    #     # 切换 frame 处理,支持变量替换
                    #     frame = replace(step['custom'])
                    #     w.switch_frame(frame)
                    #     common.script(step)

                else:
                    # 根据关键字调用关键字实现
                    getattr(common, step['keyword'].lower())(step)
                logger.info('Run the Step: %s|%s|%s is Pass' %
                            (step['no'], step['keyword'], step['element']))
                step['score'] = 'OK'

                # if 语句结果赋值
                if step['control'] == '^':
                    if_result = True

                if after_function:
                    replace_dict({'after_function': after_function})
                # 操作后,等待0.2秒
                sleep(0.2)
            except Exception as exception:
                step['snapshot'] = file_name = g.plan_name + '-' + g.sheet_name + g.start_time + \
                    '#' + self.testcase['id'] + '-' + str(step['no']) + '.png'
                snapshot_file = str(Path('snapshot') / file_name)

                if g.platform.lower() in (
                        'desktop', ) and step['keyword'] in web_keywords:
                    try:
                        g.driver.get_screenshot_as_file(snapshot_file)
                    except:
                        logger.exception('*** save the screenshot is fail ***')

                elif g.platform.lower() in (
                        'ios',
                        'android') and step['keyword'] in mobile_keywords:
                    try:
                        g.driver.switch_to_default_content()
                        w.current_context = 'NATIVE_APP'
                        g.driver.get_screenshot_as_file(snapshot_file)
                    except:
                        logger.exception('*** save the screenshot is fail ***')

                logger.exception(
                    'Run the Step: %s|%s|%s is Failure' %
                    (step['no'], step['keyword'], step['element']))
                step['score'] = 'NO'

                # if 语句结果赋值
                if step['control'] == '^':
                    if_result = False
                    continue

                self.testcase['result'] = 'Fail'
                self.testcase['report'] = 'step-%s|%s|%s: %s' % (
                    step['no'], step['keyword'], step['element'], exception)
                step['remark'] += str(exception)
                break

            # 统计结束时间
            step['end_timestamp'] = timestamp()

        steps = []
        i = 0
        for k in self.snippet_steps:
            steps += self.testcase['steps'][i:k] + self.snippet_steps[k]
            i = k
        steps += self.testcase['steps'][i:]
        self.testcase['steps'] = steps
Пример #15
0
    def run(self):

        self.testsuite_start()

        # 当前测试用例
        current = {'result': 'Pass'}
        # 上一个测试用例
        previous = {}

        # 1.执行用例
        for testcase in self.testsuite:
            # 根据筛选条件,把不需要执行的测试用例跳过
            flag = False
            for k,v in self.conditions.items():
                if not isinstance(v, list):
                    v = [v]
                if testcase[k] not in v:
                    testcase['result'] = '-'
                    flag = True
            if flag:
                continue
            # 统计开始时间
            testcase['start_timestamp'] = timestamp()
            # xml 测试报告-测试用例初始化
            if testcase['flag'] != 'N':
                case = self.report.create_case(
                    testcase['title'], testcase['id'])
                case.start()
                case.priority = testcase['priority']
                # 用例上下文
                previous = current
                current = testcase
            else:
                testcase['result'] = 'Skip'
                # case.skip('Skip', 'Autotest Flag is N')
                logger.info('Run the testcase: %s|%s Skipped, because the flag=N or the condition=snippet' % (
                    testcase['id'], testcase['title']))
                # 统计结束时间
                testcase['end_timestamp'] = timestamp()
                continue

            if testcase['condition'].lower() not in ('base', 'setup'):
                if testcase['condition'].lower() == 'sub':
                    if previous['result'] != 'Pass':
                        testcase['result'] = 'Block'
                        case.block(
                            'Blocked', 'Main or pre Sub testcase is not pass')
                        logger.warn('Run the testcase: %s|%s Blocked, Main or pre Sub TestCase is not Pass' % (
                            testcase['id'], testcase['title']))
                        # 统计结束时间
                        testcase['end_timestamp'] = timestamp()    
                        continue
                # 如果前置条件为 skip,则此用例不执行前置条件
                elif testcase['condition'].lower() == 'skip':
                    pass
                else:
                    result = self.setup(testcase, case)
                    #if result == 'N':
                    if not result:
                        # 统计结束时间
                        testcase['end_timestamp'] = timestamp()
                        continue

            try:
                tc = TestCase(testcase)
                tc.run()

                # 统计结束时间
                testcase['end_timestamp'] = timestamp()

                if testcase['result'] == 'Pass':
                    case.succeed()
                elif testcase['result'] == 'Fail':
                    case.fail('Fail', testcase['report'])
                    if testcase['condition'].lower() == 'base':
                        logger.warn('Run the testcase: %s|%s Fail, BASE is not Pass. Break the AutoTest' % (
                            testcase['id'], testcase['title']))
                        break
                    if testcase['condition'].lower() == 'setup':
                        logger.warn('Run the testcase: %s|%s Fail, SETUP is not Pass. Break the AutoTest' % (
                            testcase['id'], testcase['title']))
                        break
Пример #16
0
                        break
                    if testcase['condition'].lower() == 'setup':
                        logger.warn('Run the testcase: %s|%s Fail, SETUP is not Pass. Break the AutoTest' % (
                            testcase['id'], testcase['title']))
                        break
            except Exception as exception:
                case.error('Error', 'Remark:%s |||Exception:%s' %
                           (testcase['remark'], exception))
                logger.exception('Run the testcase: %s|%s fail' %
                                 (testcase['id'], testcase['title']))
                if testcase['condition'].lower() == 'base':
                    logger.warn('Run the testcase: %s|%s Error, BASE is not Pass. Break the AutoTest' % (
                        testcase['id'], testcase['title']))
                    break
                if testcase['condition'].lower() == 'setup':
                    logger.warn('Run the testcase: %s|%s Error, SETUP is not Pass. Break the AutoTest' % (
                        testcase['id'], testcase['title']))
                    break

        self.report.finish()

        # 2.清理环境
        try:
            if g.platform.lower() in ('desktop',):
                w.close()
                g.driver.quit()
                logger.info('--- Quit th Driver: %s' %g.browserName) 
        except:
            logger.exception('Clear the env is fail')

        self.testsuite_end()