コード例 #1
0
class AppPractice(unittest.TestCase):
    """练习"""
    def setUp(self):
        try:
            self.base_page = BasePage()
            self.log = MyLog().get_log().logger
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def test_app_practice(self):
        """app练习"""
        try:
            # 用例开始,输入负责人姓名,必须
            self.base_page.case_start("李彬")

            if not self.base_page.home_page_to("练习"):  # 判断待办事项中是否有练习
                if AppPractice.enter(self) is False:  # 首页进入考试
                    # 如果没有练习试卷就结束用例
                    self.base_page.case_pass()
                    return

            # 开始答题
            AppPractice.answer(self)

            # 用例成功,必须
            self.base_page.case_pass()
        except Exception as e:
            self.log.error(e)
            # 用例失败,必须
            self.base_page.case_failed()
            raise Exception("出现异常!")
        finally:
            self.base_page.back_to()

    def enter(self):
        """进入练习"""
        practice_module = ("css_selector", "img[src='img/practice-icon.png']"
                           )  # 首页“练习”menu
        practice_title = ("css_selector", "div.title.ng-binding")  # “练习”title
        practice_list = (
            "css_selector",
            "ion-item.item-remove-animate.item-text-wrap.item.item-complex"
        )  # “练习”试卷
        practice_state = ("css_selector",
                          "span.tag.ng-binding.tag-orange.tag-right"
                          )  # “未练习”标签

        try:
            self.assertIs(self.base_page.displayed(practice_module), True,
                          "首页异常!")
            self.log.debug("从首页进入练习模块")
            self.base_page.click_elem_tag(practice_module)
            self.base_page.screen_shot()
            self.assertIs(self.base_page.displayed(practice_title), True,
                          "进入练习模块异常!")
            if self.base_page.displayed(practice_list):
                if self.base_page.displayed(practice_state):
                    self.log.debug("进入练习试卷")
                    self.base_page.click_elem_tag(practice_state)
                else:
                    self.log.debug("暂无未练习的试卷,进入已完成试卷中重新练习!")
                    practice_count = len(
                        self.base_page.find_elements(practice_list))
                    i = random.randint(0, practice_count - 1)
                    self.base_page.click_elem_tag(practice_list,
                                                  tag=i,
                                                  roll=True)
                return True
            else:
                self.log.debug("暂无内容!")
                return False
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def answer(self):
        """答题"""
        title = ("css_selector", "div.title.ng-binding")  # “练习”title
        exam_name = ("css_selector",
                     "h2.exam-title.font-large.text-center.ng-binding")  # 试卷名称
        start_answer_button = ("xpath", "//a[contains(text(), '开始练习')]")
        continue_answer_button = ("xpath", "//a[contains(text(), '继续练习')]")
        re_answer_button = ("xpath", "//a[contains(text(), '重新练习')]")
        count_num_elem = ("css_selector", "span.item-num.ng-binding"
                          )  # 题号和试题数量
        option_elem = ("css_selector", "li.option-list-li")  # 选项
        next_elem = ("css_selector", "div.col.col-33.col-center.text-right"
                     )  # 下一题
        submit_elem = ("css_selector", "a.button.button-clear.button-calm"
                       )  # 提交
        result_element = ("css_selector", "div.title.ng-binding")  # 练习结果title
        answer_sheet_elem = ("css_selector",
                             "button.button.button-calm.exam-button"
                             )  # 答题页面的右上角的“答题卡”
        submit_button = ("css_selector",
                         "button.button.button-block.button-calm")  # 提交按钮
        # 登录成功提示,有未答题提示,自动提交试卷提示
        popup_title = ("css_selector", "h3.popup-title.ng-binding")  # 提示框title

        try:
            self.base_page.screen_shot()
            self.assertIs(self.base_page.displayed(title), True, "进入试卷异常!")
            self.base_page.get_text(exam_name, text="试卷名称:")

            if self.base_page.displayed(re_answer_button):
                self.log.debug("点击[重新练习]按钮")
                self.base_page.click_elem_tag(re_answer_button)
            elif self.base_page.displayed(start_answer_button):
                self.log.debug("点击[开始练习]按钮")
                self.base_page.click_elem_tag(start_answer_button)
            elif self.base_page.displayed(continue_answer_button):
                self.log.debug("点击[继续练习]按钮")
                self.base_page.click_elem_tag(continue_answer_button)
            # 用答题页面的“答题卡”元素断言
            self.assertIs(self.base_page.displayed(answer_sheet_elem), True,
                          "进入答题页异常!")
            # 获取题目总数
            num = self.base_page.get_text(count_num_elem)
            count_num_str = num.split('/')[1:][0]  # 考题总数
            current_num_str = num.split('/')[:1][0]  # 当前题号

            self.log.debug("开始答题")
            count_num = int(count_num_str)
            current_num = int(current_num_str)

            while current_num <= count_num:
                self.log.debug("第%s题" % current_num)
                count_option = len(
                    self.base_page.find_elements(option_elem))  # 选项数量
                i = random.randint(0, count_option - 1)
                self.base_page.click_elem_tag(option_elem, tag=i)
                self.base_page.screen_shot()
                # 点击下一题按钮
                if current_num < count_num:
                    self.base_page.click_elem_tag(next_elem)
                    current_num += 1
                else:
                    break

                if current_num >= 6:
                    self.log.debug("中断答题")
                    self.base_page.screen_shot()
                    self.base_page.click_elem_tag(answer_sheet_elem)
                    self.base_page.screen_shot()

                    if not self.base_page.displayed(popup_title):
                        self.log.debug("进入答题卡页面提交试卷!")
                        # 点击提交按钮
                        self.base_page.click_elem_tag(submit_button, roll=True)
                        self.base_page.screen_shot()
                        break
                    else:
                        break

            # 手动提交试卷
            if current_num == count_num and not self.base_page.displayed(
                    popup_title):
                self.log.debug("答题完毕后点击'提交'按钮,手动提交试卷!")
                self.base_page.click_elem_tag(submit_elem, tag=1)
                self.base_page.screen_shot()
            # 自动提交试卷(中断答题/超过离开次数)
            elif self.base_page.displayed(popup_title):
                self.base_page.popup()
            # 用成绩单页面的“成绩单”元素断言
            self.assertIs(self.base_page.displayed(result_element), True,
                          "考试结果提交异常!")
            self.log.debug("练习完成!")
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def tearDown(self):
        self.base_page.case_end()
コード例 #2
0
class AppExams(unittest.TestCase):
    """考试"""
    def setUp(self):
        try:
            self.common = Common()
            self.base_page = BasePage()
            self.log = MyLog().get_log().logger
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def test_app_exams(self):
        """app考试"""
        try:
            # 用例开始,输入负责人姓名,必须
            self.base_page.case_start("李彬")
            if not self.base_page.home_page_to("考试"):  # 判断待办事项中是否有考试
                if AppExams.enter(self) is False:  # 首页进入考试
                    # 如果没有可以考试的试卷就结束用例
                    self.base_page.case_pass()
                    return

            # 开始答题
            AppExams.answer(self)

            # 用例成功,必须
            self.base_page.case_pass()
        except Exception as e:
            self.log.error(e)
            # 用例失败,必须
            self.base_page.case_failed()
            raise Exception("出现异常!")
        finally:
            self.base_page.back_to()

    def answer(self):
        """答题"""
        exam_name = ("css_selector",
                     "h2.exam-title.font-large.text-center.ng-binding")  # 试卷名称
        start_answer_button = ("xpath", "//a[contains(text(), '开始答题')]")
        re_answer_button = ("xpath", "//a[contains(text(), '重新答题')]")
        exam_time_elem = ("css_selector", "span.countdown.ng-binding")  # 考试时长
        count_num_elem = ("css_selector", "span.item-num.ng-binding"
                          )  # 题号和试题数量
        option_elem = ("css_selector", "li.option-list-li")  # 选项
        next_elem = ("css_selector", "div.col.col-33.col-center.text-right"
                     )  # 下一题
        submit_elem = ("css_selector", "a.button.button-clear.button-calm"
                       )  # 提交
        result_element = ("css_selector", "div.title.ng-binding")  # 成绩单title
        answer_sheet_elem = ("css_selector",
                             "button.button.button-calm.exam-button"
                             )  # 答题页面的右上角的“答题卡”
        submit_button = ("css_selector",
                         "button.button.button-block.button-calm")  # 提交按钮
        # 登录成功提示,有未答题提示,自动提交试卷提示
        popup_title = ("css_selector", "h3.popup-title.ng-binding")  # 提示框title

        try:
            self.base_page.screen_shot()
            self.assertIs(self.base_page.displayed(exam_name), True, "进入试卷异常!")
            self.base_page.get_text(exam_name, text="试卷名称:")

            if self.base_page.displayed(start_answer_button):
                self.log.debug("点击开始答题按钮")
                self.base_page.click_elem_tag(start_answer_button)
            elif self.base_page.displayed(re_answer_button):
                self.log.debug("点击重新答题按钮")
                self.base_page.click_elem_tag(re_answer_button)

            # 提示框
            self.base_page.popup()
            # 用答题页面的“答题卡”元素断言
            self.assertIs(self.base_page.displayed(answer_sheet_elem), True,
                          "进入答题页异常!")
            # 获取考试时常
            self.base_page.get_text(exam_time_elem, text="剩余考试时长:")
            # 获取题目总数
            num = self.base_page.get_text(count_num_elem)
            count_num_str = num.split('/')[1:][0]  # 考题总数
            current_num_str = num.split('/')[:1][0]  # 当前题号

            self.log.debug("开始答题")
            count_num = int(count_num_str)
            current_num = int(current_num_str)
            # 自动提交试卷的提示框和总题数
            try:
                while not self.base_page.displayed(
                        popup_title) and current_num <= count_num:
                    self.log.debug("第%s题" % current_num)
                    count_option = len(
                        self.base_page.find_elements(option_elem))  # 选项数量
                    i = random.randint(0, count_option - 1)
                    self.base_page.click_elem_tag(option_elem, tag=i)
                    self.base_page.screen_shot()
                    # 点击下一题按钮
                    if current_num < count_num:
                        self.base_page.click_elem_tag(next_elem)
                        current_num += 1

                    if current_num >= 6:
                        self.log.debug("中断答题")
                        self.base_page.screen_shot()
                        self.base_page.click_elem_tag(answer_sheet_elem)
                        self.base_page.screen_shot()

                        if not self.base_page.displayed(popup_title):
                            self.log.debug("进入答题卡页面提交试卷!")
                            # 点击提交按钮
                            self.base_page.click_elem_tag(submit_button,
                                                          roll=True)
                            self.base_page.screen_shot()
                            break
                        else:
                            break
                    else:
                        self.log.debug("置于后台")
                        self.base_page.app_driver.background_app(0)

                # 手动提交试卷
                if current_num == count_num and not self.base_page.displayed(
                        popup_title):
                    self.log.debug("答题完毕后点击'提交'按钮,手动提交试卷!")
                    self.base_page.click_elem_tag(submit_elem, tag=1)
                    self.base_page.screen_shot()
                    self.assertIs(self.base_page.displayed(submit_button),
                                  True, "答题完毕后提交失败,未进入答题卡页面!")

                    # 答题卡页面点击提交按钮
                    self.base_page.click_elem_tag(submit_button, roll=True)
                    # 答题卡页点击提交按钮后的提示框
                    self.assertIs(self.base_page.displayed(popup_title), True,
                                  "答题卡页面点击提交按钮后未出现提示框!")
                    # 提示框
                    self.base_page.popup()
                # 自动提交试卷(时间到了/超过离开次数)
                elif self.base_page.displayed(popup_title):
                    self.base_page.popup()
                # 用成绩单页面的“成绩单”元素断言
                self.assertIs(self.base_page.displayed(result_element), True,
                              "考试结果提交异常!")
                self.log.debug("提交成功!")
            except Exception as e:
                # 过程中出现弹框(自动提交弹框)
                if self.base_page.displayed(popup_title):
                    self.base_page.popup()
                    # 用成绩单页面的“成绩单”元素断言
                    self.assertIs(self.base_page.displayed(result_element),
                                  True, "考试结果提交异常!")
                    self.log.debug("提交成功!")
                else:
                    self.log.error(e)
                    raise Exception("出现异常!")
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def enter(self):
        """进入试卷"""
        try:
            exams_module = ("css_selector", "img[src='img/exam.png']"
                            )  # 首页“考试”menu
            exam_state = ("css_selector",
                          "span.tag.ng-binding.tag-warning.tag-right"
                          )  # “未考试”标签
            prompt_nothing = ("css_selector", "div.nw-nothing-text"
                              )  # “暂无内容”提示
            exams_type = ("css_selector",
                          "div.exam-tabs.text-center.font-small.ng-binding"
                          )  # “未考试/已交卷”menu

            self.assertIs(self.base_page.displayed(exams_module), True,
                          "首页异常!")
            self.log.debug("从首页进入考试模块")
            self.base_page.click_elem_tag(exams_module)
            self.base_page.screen_shot()
            self.assertIs(self.base_page.displayed(exams_type), True,
                          "进入考试模块异常!")
            if self.base_page.displayed(exam_state):
                self.log.debug("进入试卷")
                self.base_page.click_elem_tag(exam_state)
                return True
            else:
                if self.base_page.displayed(prompt_nothing):
                    self.log.debug("未考试中暂无内容!")
                else:
                    self.log.debug("暂无未考试的试卷!")
                self.log.debug("进入已交卷中查看")
                self.base_page.click_elem_tag(exams_type, tag=1)
                self.base_page.screen_shot()
                if self.base_page.displayed(prompt_nothing):
                    self.log.debug("已交卷中暂无内容!")
                    return False
                else:
                    return AppExams.find_the_paper(self)
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def find_the_paper(self):
        """已交卷中查找可以重新答题的试卷"""
        exams_type = ("css_selector",
                      "div.exam-tabs.text-center.font-small.ng-binding"
                      )  # 已交卷menu
        exam_state = ("css_selector",
                      "span.tag.ng-binding.tag-success.tag-right")  # "已考试"标签
        exam_name = ("css_selector",
                     "h2.exam-title.font-large.text-center.ng-binding")  # 试卷名称
        re_answer_button = ("xpath", "//a[contains(text(), '重新答题')]")  # 重新答题按钮

        try:
            count = len(self.base_page.find_elements(exam_state))  # "已考试"标签总数
            # self.log.debug("[已考试]标签数量:%s" % str(count))

            i = 0
            j = 1
            n = 0
            if count != 0:
                while j <= count:
                    self.base_page.click_elem_tag(exams_type, tag=1)
                    self.log.debug("进入试卷")
                    self.base_page.click_elem_tag(exam_state, tag=i, roll=True)

                    if self.base_page.displayed(re_answer_button):
                        n += 1
                        self.log.debug("该试卷可以重新答题")
                        return True

                    self.base_page.get_text("试卷名称:", exam_name)
                    self.base_page.screen_shot()
                    self.log.debug("该试卷不能重新答题,继续查看下一个试卷")
                    self.base_page.back()
                    i += 2
                    j += 1
                    if j % 10 == 0:
                        self.log.debug("向上滑动屏幕!")
                        self.base_page.swipe_up()
                        self.base_page.screen_shot()
                        elements = self.base_page.find_elements(exam_state)
                        count = len(elements)
            if n == 0:
                self.log.debug("已交卷中没有可以重新答题的试卷!")
                return False
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def tearDown(self):
        # 用例结束,必须
        self.base_page.case_end()
コード例 #3
0
class AppSurvey(unittest.TestCase):
    """问卷调查"""
    def setUp(self):
        try:
            self.base_page = BasePage()
            self.log = MyLog().get_log().logger
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def test_app_survey(self):
        """app问卷调查"""
        try:
            # 用例开始,输入负责人姓名,必须
            self.base_page.case_start("李彬")

            if AppSurvey.enter(self) is False:  # 首页进入问卷调查
                # 如果没有有效的问卷调查就结束用例
                self.base_page.case_pass()
                return

            # 开始答题
            AppSurvey.answer(self)

            # 用例成功,必须
            self.base_page.case_pass()
        except Exception as e:
            self.log.error(e)
            # 用例失败,必须
            self.base_page.case_failed()
            raise Exception("出现异常!")
        finally:
            self.base_page.back_to()

    def enter(self):
        """进入问卷调查"""
        survey_module = ("css_selector", "img[src='img/survey.png']"
                         )  # 首页“问卷调查”menu
        survey_title = ("css_selector", "div.title.ng-binding")  # “问卷调查”title
        survey_list = (
            "css_selector",
            "ion-item.item-remove-animate.item-text-wrap.item.item-complex"
        )  # “问卷调查”问卷
        survey_state = ("css_selector",
                        "span.tag.ng-binding.tag-warning.tag-right")  # “未填写”标签

        try:
            self.assertIs(self.base_page.displayed(survey_module), True,
                          "首页异常!")
            self.log.debug("从首页进入问卷调查模块")
            self.base_page.click_elem_tag(survey_module)
            self.base_page.screen_shot()
            self.assertIs(self.base_page.displayed(survey_title), True,
                          "进入问卷调查模块异常!")
            if self.base_page.displayed(survey_list):
                if self.base_page.displayed(survey_state):
                    self.log.debug("进入问卷")
                    self.base_page.click_elem_tag(survey_state)
                    return True
                else:
                    self.log.debug("暂无未填写的问卷!")
                    return False
            else:
                self.log.debug("暂无内容!")
                return False
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def answer(self):
        """答题"""
        survey_name = ("css_selector",
                       "h2.exam-title.font-large.text-center.ng-binding"
                       )  # 问卷名称
        start_answer_button = ("css_selector",
                               "a.button.button-block.button-calm")  # “开始填写”按钮
        problem_name = ("css_selector", "div.paper-title.font-big.ng-binding"
                        )  # 问题名称
        submit_button = (
            "css_selector",
            "button.button.button-full.button-calm.lesson-footer-button"
        )  # 提交按钮
        text = u"大幅度dddz12345,,kds。,.,m@!~" * 5

        try:
            self.base_page.screen_shot()
            self.assertIs(self.base_page.displayed(survey_name), True,
                          "进入问卷异常!")
            self.base_page.get_text(survey_name, text="问卷名称:")

            if self.base_page.displayed(start_answer_button):
                self.log.debug("点击[开始填写]按钮")
                self.base_page.click_elem_tag(start_answer_button)
                self.base_page.screen_shot()

            # 用答题页面的“提交”按钮断言
            self.assertIs(self.base_page.displayed(submit_button), True,
                          "进入答题页异常!")
            # 问题数量
            problem_count = len(self.base_page.find_elements(problem_name))
            self.log.debug("问题数量:%s" % problem_count)

            i = 1
            while i <= problem_count:
                problem_type_elem = (
                    "xpath", "//div[@class='survey-content'][%s]//span[2]" % i
                )  # 问题类型
                problem_type = self.base_page.get_text(problem_type_elem,
                                                       text="第%s题:" % i)

                if "单选题" in problem_type or "评分题" in problem_type:
                    radio = ("xpath",
                             "//div[@class='survey-content'][%s]//label" % i
                             )  # 单选题和评分题选项
                    radio_count = len(self.base_page.find_elements(radio))
                    a = random.randint(0, radio_count - 1)
                    self.base_page.click_elem_tag(radio, tag=a)
                elif "多选题" in problem_type:
                    multiple = (
                        "xpath",
                        "//div[@class='survey-content'][%s]//div[@ng-repeat='option in question.questionOptionList']"
                        % i)  # 多选题选项
                    multiple_count = len(
                        self.base_page.find_elements(multiple))
                    b = random.randint(0, multiple_count - 1)
                    self.base_page.click_elem_tag(multiple, tag=b)
                    c = b
                    while c == b:
                        c = random.randint(0, multiple_count - 1)
                    self.base_page.click_elem_tag(multiple, tag=c)
                elif "简答题" in problem_type:
                    textarea = (
                        "xpath",
                        "//div[@class='survey-content'][%s]//textarea[@class='no-resize ng-pristine ng-untouched ng-invalid ng-invalid-required']"
                        % i)  # 问答题输入框
                    self.base_page.input_tag(textarea, text=text)
                i += 1
                self.base_page.screen_shot()

            self.base_page.click_elem_tag(submit_button)
            self.base_page.screen_shot()
            self.base_page.popup()
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def tearDown(self):
        self.base_page.case_end()
        self.base_page.quit()
コード例 #4
0
class BasePage(object):
    """页面元素基本操作,page module"""
    web_case_num = 0  # web用例编号
    web_driver = None  # 用于标记web用例
    app_driver = None  # 用于标记APP用例
    current_driver = ""  # 用于标记当前是web端还是APP端的用例
    _instance_lock = threading.Lock()  # 设置单例锁

    def __new__(cls, *args, **kwargs):
        """单例模式(支持多线程)"""
        if not hasattr(cls, "_instance"):
            with cls._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = object.__new__(cls)
        return cls._instance

    def __init__(self):
        try:
            self.config = ReadConfig()
            self.log = MyLog().get_log().logger
            self.common = Common()
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def open_app(self):
        """打开app"""
        try:
            # 读取app参数
            system = self.config.get_app_param("system")  # 系统类型
            udid = self.config.get_app_param("udid")  # 手机udid
            version = self.config.get_app_param("version")  # 手机系统版本
            app_package = self.config.get_app_param("app_package")  # 待测app包名
            app_activity = self.config.get_app_param(
                "app_activity")  # 待测app的activity名
            # app_address = self.config.get_app_param("app_address")  # app安装包路径
            # android_process = self.config.get_app_param("androidProcess")  # 小程序线程名

            desired_caps = {
                'platformName': system,
                'platformVersion': version,
                'automationName': 'appium',
                'deviceName': 'udid',
                'udid': udid,
                'newCommandTimeout': 60,
                'appActivity': app_activity,
                'appPackage': app_package,
                'unicodeKeyboard': True,
                'resetKeyboard': True,
                'setWebContentsDebuggingEnabled': True,
                'recreateChromeDriverSessions': True,
                'noReset': True,
                # 'app': app_address,
                # 'chromeOptions': {'androidProcess': android_process}
            }
            # 操作APP端元素的webdriver实例
            self.app_driver = appium.webdriver.Remote(
                'http://127.0.0.1:4723/wd/hub', desired_caps)
            self.current_driver = "app_driver"  # 标记为APP端用例
            time.sleep(10)
            self.switch_context()  # H5时需要切换context
        except Exception as e:
            self.log.error(e)
            raise Exception("打开app时异常!")

    def open_browser(self, browser="chrome"):
        """打开浏览器"""
        try:
            if browser == "chrome" or browser == "Chrome":
                driver = selenium.webdriver.Chrome()
            elif browser == "firefox" or browser == "Firefox" or browser == "FireFox" or browser == "ff":
                driver = selenium.webdriver.Firefox()
            elif browser == "ie" or browser == "IE" or browser == "internet explorer":
                driver = selenium.webdriver.Ie()
            else:
                raise Exception(
                    self.log.error("没有找到浏览器 %s, 你可以输入'Chrome,Firefox or Ie'" %
                                   browser))

            self.web_driver = driver  # 操作web端元素的webdriver实例
            self.current_driver = "web_driver"  # 标记为web端用例
            self.web_driver.maximize_window()
        except Exception as e:
            self.log.error(e)
            raise Exception("打开%s浏览器时异常!" % browser)

    def get(self, url, element):
        """打开web端URL, element用于等待页面加载完成"""
        try:
            if url != "" or url != " ":
                self.web_driver.get(url)
                self.wait_elem(element)  # 等待元素出现
            else:
                raise Exception("URL地址错误!")
        except Exception as e:
            self.log.error(e)
            raise Exception("打开网址时异常!")

    def refresh(self):
        """刷新页面"""
        if self.current_driver == "web_driver":
            self.web_driver.refresh()
        else:
            self.swipe_down()

    def back(self):
        """返回上一页"""
        try:
            if self.current_driver == "web_driver":
                self.web_driver.back()
            else:
                self.app_driver.keyevent(4)
            time.sleep(0.5)
        except Exception as e:
            self.log.error(e)
            raise Exception("返回时异常!")

    def quit(self):
        """退出程序"""
        try:
            if self.current_driver == "web_driver":
                self.web_driver.quit()
            else:
                # H5时用
                self.app_driver.switch_to.context("NATIVE_APP")
                # input_name = self.app_driver.active_ime_engine
                # self.log.debug("当前输入法:%s" % input_name)
                input_list = self.app_driver.available_ime_engines
                # self.log.debug("现有输入法:%s" % input_list)
                self.app_driver.activate_ime_engine(input_list[0])
                # input_name = self.app_driver.active_ime_engine
                # self.log.debug("更改当前输入法为:%s" % input_name)
                self.app_driver.quit()
        except Exception as e:
            self.log.error(e)
            raise Exception("退出程序时异常!")

    def click_elem_tag(self, elements, tag=0, roll=False, t=1):
        """根据元素下标点击元素"""
        for i in range(1, 6, +1):  # 操作失败后重试
            try:
                if roll:  # 是否需要滚动页面
                    self.location(elements, tag)  # app端页面上下微调
                elem = self.find_elements_tag(elements, tag)
                elem.click()
                time.sleep(t)
                break
            except Exception as e:
                time.sleep(1)
                self.log.debug("等待 %s s %s" % (i, e))
        else:
            self.log.error("%s元素未出现!" % str(elements))
            raise Exception("点击元素时异常!")

    def input_tag(self, elements, text, tag=0, roll=False):
        """输入文本"""
        for i in range(1, 6, +1):  # 操作失败后重试
            try:
                if roll:  # 是否需要滚动页面
                    self.location(elements, tag)  # app端页面上下微调
                elem = self.find_elements_tag(elements, tag)
                elem.clear()
                elem.send_keys(text)
                break
            except Exception as e:
                time.sleep(1)
                self.log.debug("等待 %s s %s" % (i, e))
        else:
            self.log.error("%s元素未出现!" % str(elements))
            raise Exception("输入文本时异常!")

    def get_text(self, *args, text="", tag=0):
        """获取文本内容,可多条,text为获取内容的标题/属性"""
        value = ""  # 文本内容
        for param in args:
            for i in range(1, 6, +1):  # 操作失败后重试
                try:
                    elem = self.find_elements_tag(param, tag)
                    value = elem.text  # web端获取文本内容

                    if value == "":
                        value = elem.get_attribute("name")  # app获取文本内容

                    if value != "":
                        self.log.debug("%s%s" % (text, value))
                        break
                except Exception as e:
                    time.sleep(1)
                    self.log.debug("等待 %s s %s" % (i, e))
            else:
                self.log.error("%s元素未出现!" % str(param))
                raise Exception("获取元素文本时异常!")
        return value

    def switch_context(self, tag=1):
        """切换环境,tag=0时为android原生context"""
        try:
            contexts = self.app_driver.contexts  # 获取当前所有context
            self.log.debug("contexts:%s" % contexts)
            if len(contexts) != 1:  # 需要切换context
                self.app_driver.switch_to.context(contexts[tag])  # 切换context
                self.log.debug("切换context")
            context = self.app_driver.current_context  # 获取当前context
            self.log.debug("current_context: %s" % context)
        except Exception as e:
            self.log.error(e)
            raise Exception("切换context时异常!")

    def switch_handle(self, element):
        """切换句柄"""
        try:
            handles = self.app_driver.window_handles
            if len(handles) != 1:  # 需要切换句柄
                self.log.debug("handles:%s" % handles)
                self.app_driver.switch_to.window(handles[-1])
                if self.displayed(element):  # 判断该句柄下是否有该元素
                    self.log.debug("切换handle")
            return self.displayed(element)
        except Exception as e:
            self.log.error(e)
            raise Exception("切换handle时异常!")

    def home_page_to(self, module):
        """首页待办事项进入功能模块"""
        module_elem = ("xpath", "//span[contains(text(), '%s')]" % module
                       )  # 待办事项中的模块标签
        result = False
        try:
            if self.displayed(module_elem):
                self.log.debug("从首页的待办事项进入%s" % module)
                self.screen_shot()
                self.click_elem_tag(module_elem)
                self.screen_shot()
                result = True
            return result
        except Exception as e:
            self.log.error(e)
            raise Exception("从首页的待办事项进入%s时异常!" % module)

    def back_to(self, *args):
        """返回(首页)或指定元素页面(须该页独有元素)"""
        try:
            home_menu = ("css_selector", "span.tab-title.ng-binding"
                         )  # 首页底部menu
            username_input = ("css_selector", "input[type='text']"
                              )  # 用户名输入框定位信息

            menu_elem = ()
            if args != ():
                menu_elem = args[0]
            self.log.debug("返回")
            i = 1
            while i <= 5:  # 最多返回5级页面
                if self.displayed(username_input):  # 判断是否处于登录页
                    raise Exception("登录失败!")
                self.back()
                self.screen_shot()
                if args == ():  # 返回首页
                    if self.switch_handle(home_menu):
                        self.click_elem_tag(home_menu)
                        break
                elif args != ():  # 返回指定元素页面
                    if self.switch_handle(menu_elem):
                        break
                self.log.debug("返回:%s" % i)
                i += 1
            else:
                raise Exception("返回时异常!")
        except Exception as e:
            self.log.error(e)
            raise Exception("返回时异常!")

    def popup(self):
        """获取弹框信息,点击按钮"""
        popup_title = ("css_selector", "h3.popup-title.ng-binding")  # 提示框title
        popup_info = ("css_selector", "div.popup-body")  # 提示信息
        popup_ok_button = ("css_selector",
                           "button.button.ng-binding.button-calm")  # 确定按钮
        try:
            n = len(self.find_elements(popup_title))
            # self.log.debug("弹框数量:%s" % n)
            self.get_text(popup_title, popup_info, tag=n - 1)
            self.screen_shot()
            self.click_elem_tag(popup_ok_button, tag=n - 1)
            self.screen_shot()

        except Exception as e:
            self.log.error(e)
            raise Exception("操作弹框时异常!")

    def roll(self, elements):
        """web端页面下滑"""
        elem = self.find_elements_tag(elements)
        selenium.webdriver.ActionChains(
            self.web_driver).move_to_element(elem).perform()
        time.sleep(1)
        self.log.debug("滚动页面!")

    def screen_shot(self):
        """截图"""
        try:
            current_time = str(self.common.get_now_time())  # 获取当前时间
            func_name = sys._getframe().f_back.f_code.co_name  # 获取调用函数名
            line_number = sys._getframe().f_back.f_lineno  # 获取调用行号

            path = self.common.get_result_path(
                case_name,
                "%s %s %s.png" % (current_time, func_name, line_number))
            if self.current_driver == "web_driver":  # web端直接截图
                self.web_driver.get_screenshot_as_file(path)
            else:  # 移动端截图
                contexts = self.app_driver.contexts  # 获取所有的context
                current_context = self.app_driver.current_context  # 获取当前的context
                if current_context == contexts[0]:  # 如果是android原生环境直接截图
                    self.app_driver.get_screenshot_as_file(path)
                else:  # 如果是H5页面先切换到android原生环境再截图
                    self.app_driver.switch_to.context(contexts[0])
                    self.app_driver.get_screenshot_as_file(path)
                    self.app_driver.switch_to.context(
                        contexts[1])  # 截完图后回到原来的context
        except Exception as e:
            self.log.error(e)
            raise Exception("截图保存时异常!")

    def case_start(self, principal, api_case_name="", api_case_num=0):
        """用例开始,参数为负责人姓名,api测试名,api测试编号"""
        try:
            global case_name  # 获取调用函数名作为截图文件夹名
            if api_case_name == "" and api_case_num == 0:
                case_name = sys._getframe().f_back.f_code.co_name
                self.web_case_num += 1
                self.log.debug("web用例%s:%s,负责人:%s" %
                               (self.web_case_num, case_name, principal))
            else:
                case_name = api_case_name  # 将全局变量case_name重新赋值
                self.log.debug("api用例%s:%s,负责人:%s" %
                               (api_case_num, api_case_name, principal))
        except Exception as e:
            self.log.error(e)
            raise Exception("用例开始时异常!")

    def case_end(self):
        """用例结束"""
        self.log.debug("*" * 100 + "\n")  # "*"号不可改,用于提取用例失败的日志

    def case_pass(self):
        """用例通过"""
        self.log.debug("=" * 10 + "%s: pass!" % case_name + "=" * 10)

    def case_failed(self):
        """用例失败"""
        self.log.debug("=" * 10 + "%s: failed!" % case_name +
                       "=" * 10)  # "failed!"不可改,用于标记用例失败的日志

    def find_elements_tag(self, elements, tag=0):
        """查找元素(一个具体的元素点击和输入时定位)"""
        try:
            key = elements[0]  # 定位方式
            value = elements[1]  # 值

            if self.current_driver == "web_driver":  # web定位
                if key == "css_selector":
                    elem = self.web_driver.find_elements_by_css_selector(
                        value)[tag]
                elif key == "xpath":
                    elem = self.web_driver.find_elements_by_xpath(value)[tag]
                elif key == "id":
                    elem = self.web_driver.find_elements_by_id(value)[tag]
                elif key == "name":
                    elem = self.web_driver.find_elements_by_name(value)[tag]
                elif key == "class":
                    elem = self.web_driver.find_elements_by_class_name(
                        value)[tag]
                elif key == "link_text":
                    elem = self.web_driver.find_elements_by_link_text(value)
                elif key == "partial_link_text":
                    elem = self.web_driver.find_elements_by_partial_link_text(
                        value)
                elif key == "tag_name":
                    elem = self.web_driver.find_elements_by_tag_name(
                        value)[tag]
                else:
                    self.log.error("定位类型书写错误:%s" % str(elements))
                    raise Exception
                return elem
            else:  # app定位
                if key == "css_selector":
                    elem = self.app_driver.find_elements_by_css_selector(
                        value)[tag]
                elif key == "xpath":
                    elem = self.app_driver.find_elements_by_xpath(value)[tag]
                elif key == "accessibility_id":
                    elem = self.app_driver.find_elements_by_accessibility_id(
                        value)[tag]
                elif key == "id":
                    elem = self.app_driver.find_elements_by_id(value)[tag]
                elif key == "name":
                    elem = self.app_driver.find_elements_by_name(value)[tag]
                elif key == "class":
                    elem = self.app_driver.find_elements_by_class_name(
                        value)[tag]
                elif key == "link_text":
                    elem = self.app_driver.find_elements_by_link_text(value)
                elif key == "partial_link_text":
                    elem = self.app_driver.find_elements_by_partial_link_text(
                        value)
                elif key == "tag_name":
                    elem = self.app_driver.find_elements_by_tag_name(
                        value)[tag]
                else:
                    self.log.error("定位类型书写错误:%s" % str(elements))
                    raise Exception
                return elem
        except Exception as e:
            # self.log.debug("元素不存在:%s,%s" % (str(elements), e))
            raise Exception

    def find_elements(self, elements):
        """查找元素集合"""
        try:
            key = elements[0]
            value = elements[1]

            if self.current_driver == "web_driver":  # web查找元素
                if key == "css_selector":
                    elem = self.web_driver.find_elements_by_css_selector(value)
                elif key == "xpath":
                    elem = self.web_driver.find_elements_by_xpath(value)
                elif key == "id":
                    elem = self.web_driver.find_elements_by_id(value)
                elif key == "name":
                    elem = self.web_driver.find_elements_by_name(value)
                elif key == "class_name":
                    elem = self.web_driver.find_elements_by_class_name(value)
                elif key == "link_text":
                    elem = self.web_driver.find_elements_by_link_text(value)
                elif key == "partial_link_text":
                    elem = self.web_driver.find_elements_by_partial_link_text(
                        value)
                elif key == "tag_name":
                    elem = self.web_driver.find_element_by_tag_name(value)
                else:
                    self.log.error("函数类型书写错误:%s" % str(elements))
                    raise Exception
                return elem
            else:  # APP查找元素
                if key == "css_selector":
                    elem = self.app_driver.find_elements_by_css_selector(value)
                elif key == "xpath":
                    elem = self.app_driver.find_elements_by_xpath(value)
                elif key == "accessibility_id":
                    elem = self.app_driver.find_elements_by_accessibility_id(
                        value)
                elif key == "id":
                    elem = self.app_driver.find_elements_by_id(value)
                elif key == "name":
                    elem = self.app_driver.find_elements_by_name(value)
                elif key == "class":
                    elem = self.app_driver.find_elements_by_class_name(value)
                elif key == "link_text":
                    elem = self.app_driver.find_elements_by_link_text(value)
                elif key == "partial_link_text":
                    elem = self.app_driver.find_elements_by_partial_link_text(
                        value)
                elif key == "tag_name":
                    elem = self.app_driver.find_elements_by_tag_name(value)
                else:
                    self.log.error("函数类型书写错误:%s" % str(elements))
                    raise Exception
                return elem
        except Exception as e:
            # self.log.debug("元素不存在:%s,%s" % (str(elements), e))
            raise Exception

    def wait_elem(self, element):
        """等待元素出现"""
        key = element[0]
        value = element[1]
        locator = None

        try:
            if key == "css_selector":
                locator = (By.CSS_SELECTOR, value)
            elif key == "xpath":
                locator = (By.XPATH, value)
            elif key == "id":
                locator = (By.ID, value)
            elif key == "name":
                locator = (By.NAME, value)
            elif key == "class":
                locator = (By.CLASS_NAME, value)
            elif key == "link_text":
                locator = (By.LINK_TEXT, value)
            elif key == "partial_link_text":
                locator = (By.PARTIAL_LINK_TEXT, value)
            elif key == "tag_name":
                locator = (By.TAG_NAME, value)

            if self.current_driver == "web_driver":
                WebDriverWait(self.web_driver, 20, 0.5).until(
                    ec.presence_of_element_located(locator),
                    "%s元素未出现!" % str(element))
            else:
                WebDriverWait(self.app_driver, 20, 0.5).until(
                    ec.presence_of_element_located(locator),
                    "%s元素未出现!" % str(element))
        except Exception as e:
            self.log.error(e)
            raise Exception("等待元素出现时异常!")

    # def judgment(self, elements, tag=0):
    #     """判断元素是否存在"""
    #     for i in range(1, 6, +1):
    #         time.sleep(1)
    #         try:
    #             self.find_elements_tag(elements, tag)
    #             return True
    #         except Exception as e:
    #             return False

    # 方式二(速度较慢):
    # key = elements[0]
    # value = elements[1]
    # locator = None
    #
    # if key == "css_selector":
    #     locator = (By.CSS_SELECTOR, value)
    # elif key == "xpath":
    #     locator = (By.XPATH, value)
    # elif key == "id":
    #     locator = (By.ID, value)
    # elif key == "name":
    #     locator = (By.NAME, value)
    # elif key == "class":
    #     locator = (By.CLASS_NAME, value)
    # elif key == "link_text":
    #     locator = (By.LINK_TEXT, value)
    # elif key == "partial_link_text":
    #     locator = (By.PARTIAL_LINK_TEXT, value)
    # elif key == "tag_name":
    #     locator = (By.TAG_NAME, value)
    #
    # if current_driver == "web_driver":
    #     try:
    #         WebDriverWait(self.web_driver, 20, 0.5).until(lambda x: x.find_element(*locator))
    #         return True
    #     except:
    #         return False
    # else:
    #     try:
    #         WebDriverWait(self.app_driver, 20, 0.5).until(lambda x: x.find_element(*locator))
    #         return True
    #     except:
    #         return False

    def displayed(self, elements, tag=0):
        """判断元素是否可见"""
        try:
            elem = self.find_elements_tag(elements, tag)
            return elem.is_displayed()  # 元素可见为True,隐藏为False
        except Exception as e:
            return False  # 没有找到元素

    def swipe_up(self, x=0.5, y1=0.85, y2=0.15, t=500):
        """屏幕向上滑动"""
        try:
            self.swipe(x, y1, y2, t)
            self.log.debug("上滑")
        except Exception as e:
            self.log.error(e)
            raise Exception("屏幕向上滑动时异常!")

    def swipe_down(self, x=0.5, y1=0.15, y2=0.85, t=500):
        """屏幕向下滑动"""
        try:
            self.swipe(x, y1, y2, t)
            self.log.debug("下滑")
        except Exception as e:
            self.log.error(e)
            raise Exception("屏幕向下滑动时异常!")

    def swipe(self, x, y1, y2, t):
        """上下滑动"""
        try:
            coordinate_x = self.app_driver.get_window_size()['width']  # 获取屏幕宽度
            coordinate_y = self.app_driver.get_window_size()[
                'height']  # 获取屏幕高度
            x1 = int(coordinate_x * x)  # x坐标
            y1 = int(coordinate_y * y1)  # 起始y坐标
            y2 = int(coordinate_y * y2)  # 终点y坐标
            self.app_driver.swipe(x1, y1, x1, y2, t)
            time.sleep(1)
        except Exception as e:
            raise Exception(e)

    def location(self, element, tag=0):
        """屏幕内容上下微调"""
        current_context = ""
        try:
            elem = self.find_elements_tag(
                element, tag)  # css_selector不能在android环境下定位,所以定位完成后再切换环境
            y1 = elem.location["y"]  # 获取元素y坐标
            # self.log.debug(y1)

            contexts = self.app_driver.contexts  # 获取所有的context
            current_context = self.app_driver.current_context  # 获取当前的context
            if current_context != contexts[
                    0]:  # 当前为非android环境时需要切换为APP_context才能进行滑动操作
                self.app_driver.switch_to.context(contexts[0])

            y2 = self.app_driver.get_window_size()['height']  # 获取屏幕高度
            # self.log.debug(y2)

            while y1 + 200 > y2 or y1 < 100:  # 判断是否需要滑动
                if y1 + 200 > y2:
                    self.swipe(x=0.02, y1=0.85, y2=0.45, t=500)  # 向上滑
                    self.screen_shot()

                n = y1

                if current_context == contexts[
                        1]:  # 当前为非H5环境时需要切换为H5环境才能获取元素坐标
                    self.app_driver.switch_to.context(contexts[1])
                y1 = elem.location["y"]
                # self.log.debug(y1)
                if current_context != contexts[
                        0]:  # 当前为非android环境时需要切换为APP_context才能进行滑动操作
                    self.app_driver.switch_to.context(contexts[0])

                if y1 < 100:
                    self.swipe(x=0.02, y1=0.60, y2=0.75, t=500)  # 向下滑
                    self.screen_shot()

                if n == y1:
                    break
        except Exception as e:
            self.log.error(e)
            raise Exception("位置调整时异常!")
        finally:
            self.app_driver.switch_to.context(current_context)  # 微调完成后切换为原来的环境
コード例 #5
0
class AppCurriculum(unittest.TestCase):
    """课程"""
    def setUp(self):
        try:
            self.base_page = BasePage()
            self.log = MyLog().get_log().logger
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def test_app_curriculum(self):
        """app课程"""
        try:
            # 用例开始,输入负责人姓名,必须
            self.base_page.case_start("李彬")

            if not self.base_page.home_page_to("课程"):  # 判断待办事项中是否有课程
                if AppCurriculum.enter(self) is False:  # 首页进入课程
                    # 如果没有课程就结束用例
                    self.base_page.case_pass()
                    return

            # 开始学习
            AppCurriculum.study(self)

            # 用例成功,必须
            self.base_page.case_pass()
        except Exception as e:
            self.log.error(e)
            # 用例失败,必须
            self.base_page.case_failed()
            raise Exception("出现异常!")
        finally:
            self.base_page.back_to()

    def enter(self):
        """进入课程"""
        module = ("css_selector", "img[src='img/lesson.png']")  # 首页“课程”menu
        title = ("css_selector", "div.title.ng-binding")  # “课程”title
        curriculum_list = (
            "css_selector",
            "ion-item.item-remove-animate.item-text-wrap.item.item-complex"
        )  # “课程”list
        state = ("css_selector", "span.tag.ng-binding.tag-orange.tag-right"
                 )  # “未学习”标签

        try:
            self.assertIs(self.base_page.displayed(module), True, "首页异常!")
            self.log.debug("从首页进入课程模块")
            self.base_page.click_elem_tag(module)
            self.base_page.screen_shot()
            self.assertIs(self.base_page.displayed(title), True, "进入课程模块异常!")

            if self.base_page.displayed(curriculum_list):
                if self.base_page.displayed(state):
                    self.log.debug("进入课程")
                    self.base_page.click_elem_tag(state, roll=True)
                else:
                    self.log.debug("暂无未学习的课程,进入已学习的课程中重新学习!")
                    count = len(
                        self.base_page.find_elements(curriculum_list))  # 课程数量
                    i = random.randint(0, count - 1)
                    self.base_page.click_elem_tag(curriculum_list,
                                                  tag=i,
                                                  roll=True)
                return True
            else:
                self.log.debug("暂无内容!")
                return False
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def study(self):
        """学习"""
        curriculum_name = ("css_selector",
                           "h1.exam-title.font-large.text-center.ng-binding"
                           )  # 课程名称
        curriculum_exam = (
            "css_selector",
            "button.button.button-full.button-calm.lesson-footer-button"
        )  # 随堂考试
        curriculum_list = (
            "css_selector",
            "ion-item.item-remove-animate.item-complex.item-text-wrap.item"
        )  # 课件list
        # state = ("css_selector", "span.tag.ng-binding.tag-orange.tag-right")  # “未学习”标签
        courseware_name = ("css_selector",
                           "h2.exam-title.font-large.text-center.ng-binding"
                           )  # 课件名称
        start_answer_button = ("xpath", "//a[contains(text(), '开始学习')]")

        try:
            self.base_page.screen_shot()
            self.assertIs(self.base_page.displayed(curriculum_name), True,
                          "进入课程异常!")
            self.base_page.get_text(curriculum_name, text="课程名称:")

            # 随堂考试(只能放课件学习的前面,不然会有句柄切换问题)
            if self.base_page.displayed(curriculum_exam):
                AppCurriculum.answer(self)
                self.base_page.back_to(curriculum_name)

            curriculum_count = len(
                self.base_page.find_elements(curriculum_list))
            if curriculum_count != 0:
                self.base_page.switch_handle(curriculum_list)
                i = random.randint(0, curriculum_count - 1)
                self.base_page.click_elem_tag(curriculum_list,
                                              tag=i,
                                              roll=True)
                self.assertIs(self.base_page.displayed(courseware_name), True,
                              "进入课件异常!")
                self.base_page.get_text(courseware_name, text="进入课件:")
                self.base_page.screen_shot()

                if self.base_page.displayed(start_answer_button):
                    self.log.debug("点击开始学习按钮")
                    self.base_page.click_elem_tag(start_answer_button, t=2)
                    self.base_page.screen_shot()

                self.base_page.back_to(curriculum_name)
                self.log.debug("学习完成!")
            else:
                self.log.debug("暂无内容!")
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def answer(self):
        """随堂考试"""
        curriculum_exam = (
            "css_selector",
            "button.button.button-full.button-calm.lesson-footer-button"
        )  # 随堂考试
        count_num_elem = ("css_selector", "span.item-num.ng-binding"
                          )  # 题号和试题数量
        option_elem = ("css_selector", "li.option-list-li")  # 选项
        next_elem = ("css_selector", "div.col.col-33.col-center.text-right"
                     )  # 下一题
        submit_elem = ("css_selector", "a.button.button-clear.button-calm"
                       )  # 提交
        result_element = ("css_selector", "div.title.ng-binding")  # 练习结果title
        answer_sheet_elem = ("css_selector",
                             "button.button.button-calm.exam-button"
                             )  # 答题页面的右上角的“答题卡”
        submit_button = ("css_selector",
                         "button.button.button-block.button-calm")  # 提交按钮
        # 登录成功提示,有未答题提示,自动提交试卷提示
        popup_title = ("css_selector", "h3.popup-title.ng-binding")  # 提示框title

        try:
            self.log.debug("进入随堂考试")
            self.base_page.click_elem_tag(curriculum_exam)
            self.base_page.screen_shot()

            # 用答题页面的“答题卡”元素断言
            self.assertIs(self.base_page.displayed(answer_sheet_elem), True,
                          "进入答题页异常!")
            # 获取题目总数
            num = self.base_page.get_text(count_num_elem)
            count_num_str = num.split('/')[1:][0]  # 考题总数
            current_num_str = num.split('/')[:1][0]  # 当前题号

            self.log.debug("开始答题")
            count_num = int(count_num_str)
            current_num = int(current_num_str)

            while current_num <= count_num:
                self.log.debug("第%s题" % current_num)
                count_option = len(
                    self.base_page.find_elements(option_elem))  # 选项数量
                i = random.randint(0, count_option - 1)
                self.base_page.click_elem_tag(option_elem, tag=i)
                self.base_page.screen_shot()
                # 点击下一题按钮
                if current_num < count_num:
                    self.base_page.click_elem_tag(next_elem)
                    current_num += 1
                else:
                    break

                if current_num >= 6:
                    self.log.debug("中断答题")
                    self.base_page.screen_shot()
                    self.base_page.click_elem_tag(answer_sheet_elem)
                    self.base_page.screen_shot()

                    if not self.base_page.displayed(popup_title):
                        self.log.debug("进入答题卡页面提交试卷!")
                        # 点击提交按钮
                        self.base_page.click_elem_tag(submit_button, roll=True)
                        self.base_page.screen_shot()
                        break
                    else:
                        break

            # 手动提交试卷
            if current_num == count_num and not self.base_page.displayed(
                    popup_title):
                self.log.debug("答题完毕后点击'提交'按钮,手动提交试卷!")
                self.base_page.click_elem_tag(submit_elem, tag=1)
                self.base_page.screen_shot()
            # 自动提交试卷(中断答题/超过离开次数)
            elif self.base_page.displayed(popup_title):
                self.base_page.popup()
            # 用成绩单页面的“成绩单”元素断言
            self.assertIs(self.base_page.displayed(result_element), True,
                          "考试结果提交异常!")
            self.log.debug("提交成功!")
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def tearDown(self):
        self.base_page.case_end()
コード例 #6
0
class SendEmail(object):
    """发送测试报告"""
    _instance_lock = threading.Lock()  # 设置单例锁

    def __new__(cls, *args, **kwargs):
        """单例模式(支持多线程)"""
        if not hasattr(cls, "_instance"):
            with cls._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = object.__new__(cls)
        return cls._instance

    def __init__(self):
        try:
            self.common = Common()  # 实例化一个common调用公用函数
            self.log = MyLog().get_log().logger  # 实例化一个log打印日志
            self.config = ReadConfig()  # 实例化一个read_config读取email的配置信息
            self.msg = email.mime.multipart.MIMEMultipart(
                'alternative')  # 实例化一个email发送email
            self.log_dir = self.common.get_result_path()  # 获取存储日志的时间目录
            self.principal_name_list = []  # 错误用例负责人list
            self.zip_path = self.log_dir + ".zip"  # 设置存放zip的路径
            self.result = False  # 发送结果标志
            self.num = 0  # 发送失败后重试次数
        except Exception as e:
            self.log.error(e)
            raise Exception("SendEmail.__init__异常!")

    def with_zip(self):
        """附件以zip格式发送邮件"""
        while self.result is False and self.num < 3:  # 发送失败后重试3次
            try:
                # 提取错误用例负责人姓名
                file_list = os.listdir(self.log_dir)  # 获取时间目录下的文件列表
                for file in file_list:
                    file_name = os.path.splitext(file)[0]  # 文件名
                    # 用正则表达式查找文件名为汉字的文件(负责人对应的错误日志文件),正则表达式为:非汉字的字符用""替换掉
                    if file_name == re.sub("[^\u4e00-\u9fa5]+", "", file_name):
                        self.principal_name_list.append(
                            file_name)  # 添加负责人姓名到principal_name_list中

                # 创建一个写入的zip对象
                with zipfile.ZipFile(
                        self.zip_path, mode='w',
                        compression=zipfile.ZIP_DEFLATED) as zip_obj:
                    for path, folders, files in os.walk(self.log_dir):
                        for file in files:
                            zip_obj.write(os.path.join(path, file))  # 将内容写入zip
                # 添加附件
                part = MIMEApplication(open(self.zip_path,
                                            'rb').read())  # 读取内容
                part.add_header('Content-Disposition',
                                'attachment',
                                filename=('gbk', '', "result.zip"))  # 设置附件名
                self.msg.attach(part)
                self.send()  # 发送邮件
                self.result = True
            except Exception as e:
                self.log.error("发送失败 %s" % e)
                self.num += 1
            finally:
                os.remove(self.zip_path)  # 删除zip文件
                self.remove_result()  # 删除之前的结果文件夹

    def with_file(self):
        """附件以单个文件形式发送邮件"""
        while self.result is False and self.num < 3:  # 发送失败后重试3次
            try:
                file_list = os.listdir(self.log_dir)  # 获取时间目录下的文件列表
                for file in file_list:
                    file_name = os.path.splitext(file)[0]  # 文件名
                    file_type = os.path.splitext(file)[1]  # 文件类型

                    # 用正则表达式查找文件名为汉字的文件(负责人对应的错误日志文件),正则表达式为:非汉字的字符用""替换掉
                    if file_name == re.sub("[^\u4e00-\u9fa5]+", "", file_name):
                        self.principal_name_list.append(
                            file_name)  # 添加负责人姓名到错误负责人list中
                        current_file = os.path.join(self.log_dir,
                                                    file)  # 拼接当前的日志路径
                        part = MIMEApplication(
                            open(current_file, 'rb').read())  # 读取当前的日志
                        part.add_header('Content-Disposition',
                                        'attachment',
                                        filename=('gbk', '', file))  # 设置附件名
                        self.msg.attach(part)
                    elif file_type == ".html":  # 查找html文件
                        current_file = os.path.join(self.log_dir,
                                                    file)  # 拼接当前的日志路径
                        part = MIMEApplication(
                            open(current_file, 'rb').read())  # 读取当前的日志
                        part.add_header('Content-Disposition',
                                        'attachment',
                                        filename=('gbk', '', file))  # 设置附件名
                        self.msg.attach(part)
                    elif "error" in file_name:  # 查找错误日志文件
                        current_file = os.path.join(self.log_dir,
                                                    file)  # 拼接当前的日志路径
                        part = MIMEApplication(
                            open(current_file, 'rb').read())  # 读取当前的日志
                        part.add_header('Content-Disposition',
                                        'attachment',
                                        filename=('gbk', '', file))  # 设置附件名
                        self.msg.attach(part)
                self.send()  # 发送邮件
                self.result = True
            except Exception as e:
                self.log.error("发送失败 %s" % e)
                self.num += 1
            finally:
                self.remove_result()  # 删除之前的结果文件夹

    def send(self):
        """发送邮件"""
        try:
            # 从配置文件中读取发件人信息
            sender_name = ""  # 发件人
            sender_email = ""  # 发件箱
            sender_dict = json.loads(self.config.get_email("sender"))
            for key, value in sender_dict.items():
                sender_name = key  # 发件人
                sender_email = value  # 发件箱

            # 从配置文件中读取收件人信息
            # receivers内容为字典时使用(receivers = {"蓝梦":"*****@*****.**", "孟冰":"*****@*****.**")
            receivers_dict = json.loads(self.config.get_email("receivers"))
            name_list = []  # 收件人list
            receivers = []  # 收件箱list
            for key, value in receivers_dict.items():
                if key in self.principal_name_list:
                    name_list.append(key)
                    receivers.append(value)

            # 邮件信息
            name_list_str = ",".join(name_list)  # 收件人姓名,将list转换为str
            mail_host = self.config.get_email("email_host")  # 设置邮箱服务器域名
            mail_port = self.config.get_email("email_port")  # 设置邮箱服务器接口
            mail_user = self.config.get_email("email_user")  # 发件人用户名
            mail_pass = self.config.get_email("email_pass")  # 发件人口令
            subject = self.config.get_email("subject")  # 主题
            content = self.config.get_email("content")  # 正文
            if len(name_list_str) == 0:
                self.log.debug("所有用例都正常通过!")
            else:
                self.log.debug("发件人:%s" % sender_name)
                self.log.debug("收件人:%s" % name_list_str)

                txt = email.mime.text.MIMEText(content, 'plain', 'utf-8')
                self.msg.attach(txt)
                self.msg['Subject'] = Header(subject, 'utf-8')
                self.msg['From'] = Header(sender_name, 'utf-8')
                self.msg['To'] = Header("%s" % name_list_str, 'utf-8')

                # 调用邮箱服务器
                smt_obj = smtplib.SMTP_SSL(mail_host, mail_port)
                # 登录邮箱
                smt_obj.login(mail_user, mail_pass)
                # 发送邮件
                smt_obj.sendmail(sender_email, receivers, self.msg.as_string())
                # 关闭邮箱
                smt_obj.quit()
                self.log.debug("发送成功!")
        except Exception as e:
            self.log.error(e)
            raise Exception("发送email时异常!")

    def remove_result(self):
        """发送报告后删除其他的文件夹"""
        try:
            result_path = os.path.dirname(self.log_dir)  # 获取result目录路径
            result_list = os.listdir(result_path)  # 获取result下的文夹列表
            i = len(result_list)  # 统计文件夹数量
            for file in result_list:
                path = os.path.join(result_path, file)  # 拼接每个文件夹的路径
                if i > 1:  # 保留最新的文件夹
                    shutil.rmtree(path)
                    i -= 1
        except Exception as e:
            self.log.error(e)
            raise Exception("删除result下文件夹时异常!")
コード例 #7
0
class AppOperation(unittest.TestCase):
    """技术操作"""
    def setUp(self):
        try:
            self.base_page = BasePage()
            self.log = MyLog().get_log().logger
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def test_app_operation(self):
        """app技术操作"""
        bottom_menu = ("css_selector", "span.tab-title.ng-binding")  # 底部menu
        operation_tool_menu = ("css_selector", "i.iconfont.nw-tool.mine-icon")  # 操作工具
        operation_exam_menu = ("css_selector", "a.item.item-icon-right")  # 技术操作考核
        prompt_nothing = ("css_selector", "div.nw-nothing-text")  # “暂无内容”提示
        operation_list = ("css_selector", "ion-item.item-remove-animate.item-text-wrap.item")  # 试卷list
        operation_name = ("css_selector", "h1.operate-title.text-center.font-large.ng-binding")  # 试卷名称
        scan_button = ("css_selector", "button.button.button-block.button-calm")  # 扫码考核按钮
        popup_title = ("css_selector", "h3.popup-title.ng-binding")  # 提示框title

        deduction_button = ("xpath", "//android.view.View[@content-desc='扣分']")  # 扣分按钮
        remark = ("class", "android.widget.EditText")  # 扣分备注
        deduction_value = ("xpath", "//android.view.View[@content-desc='0.5分']")  # 扣分值
        determine_button = ("xpath", "//android.view.View[@content-desc='确认']")  # 确认扣分
        remark_value = u"agaa vjvvabaz v测试,./!,。?!1234567890" * 10
        submit_button = ("css_selector", "button.button.button-calm.exam-button")  # 判分零和提交按钮

        try:
            # 用例开始,输入负责人姓名,必须
            self.base_page.case_start("李彬")
            self.assertIs(self.base_page.displayed(bottom_menu), True, "首页异常!")
            self.log.debug("进入[我的]")
            self.base_page.click_elem_tag(bottom_menu, tag=-1)
            self.base_page.screen_shot()

            if self.base_page.displayed(operation_tool_menu):
                self.log.debug("进入[操作工具]")
                self.base_page.click_elem_tag(operation_tool_menu)
                self.base_page.screen_shot()
                if self.base_page.displayed(prompt_nothing):
                    self.log.debug("暂无内容!")
                    self.base_page.case_pass()
                    return
            else:
                self.log.debug("没有[操作工具]选项,结束测试!")
                self.base_page.case_pass()
                return
            self.log.debug("进入[技术操作列表]")
            self.base_page.click_elem_tag(operation_exam_menu)
            self.base_page.screen_shot()
            self.assertIs(self.base_page.displayed(operation_list), True, "进入[技术操作列表]异常!")

            self.log.debug("进入[技术操作详情]")
            operation_count = len(self.base_page.find_elements(operation_list))  # 技术操作试卷数量
            i = random.randint(0, operation_count - 1)
            self.base_page.click_elem_tag(operation_list, tag=i, roll=True)
            self.base_page.screen_shot()
            self.assertIs(self.base_page.displayed(scan_button), True, "进入[技术操作详情]异常!")
            self.base_page.get_text(operation_name, text="考核表名称:")
            self.log.debug("请扫描考生的二维码!")
            self.base_page.click_elem_tag(scan_button)

            i = 0
            while self.base_page.displayed(scan_button):
                self.log.debug("等待扫码!")
                time.sleep(2)
                # 开始考核/重新考核/非本院学员/扫码失败
                if self.base_page.displayed(popup_title):
                    self.base_page.popup()
                    break

                i += 1
                if i == 30:
                    raise Exception("扫码超时!")
            self.assertIs(self.base_page.displayed(submit_button), True, "进入答题页面异常!")
            self.log.debug("扫码完成,进入答题页面!")

            self.base_page.switch_context(tag=0)
            elements = len(self.base_page.find_elements(deduction_button))
            self.log.debug("总题数:%s" % str(elements))
            if elements != 0:
                i = 0
                while i < elements:
                    self.log.debug("点击第%s题的扣分按钮" % (i+1))
                    self.base_page.click_elem_tag(deduction_button, tag=i, roll=True)
                    self.base_page.screen_shot()

                    self.log.debug("选择扣分")
                    self.assertIs(self.base_page.displayed(deduction_value), True, "点击扣分按钮时异常!")
                    tag_id = len(self.base_page.find_elements(deduction_value))
                    self.base_page.click_elem_tag(deduction_value, tag=(tag_id - 1))
                    self.base_page.get_text(deduction_value, text="第%s题扣除:" % (i+1), tag=(tag_id-1))
                    self.base_page.screen_shot()

                    self.base_page.click_elem_tag(determine_button)  # 确认扣分
                    self.base_page.screen_shot()

                    if self.base_page.displayed(remark, tag=i):
                        self.log.debug("输入第%s题的扣分备注" % (i+1))
                        self.base_page.input_tag(remark, remark_value, tag=i, roll=True)
                    self.base_page.screen_shot()
                    i += 1

                    if i >= 5:
                        self.log.debug("中断答题")
                        self.base_page.screen_shot()
                        break

                self.base_page.switch_context()

                self.log.debug("点击[提交]按钮,提交本次考核成绩!")
                self.base_page.click_elem_tag(submit_button, tag=1)

                self.assertIs(self.base_page.displayed(popup_title), True, "点击[提交]按钮后未出现确定提交的提示框!")
                self.base_page.popup()

                self.assertIs(self.base_page.displayed(popup_title), True, "点击[确定]按钮后未出现提交成功的提示框!")
                self.base_page.popup()

                self.assertIs(self.base_page.displayed(scan_button), True, "提交考试结果后未回到技术操作详情页面!")
                self.log.debug("本次考核成绩已提交!")

                # 用例成功,必须
                self.base_page.case_pass()
            else:
                self.base_page.screen_shot()
                raise Exception("页面显示异常!")
        except Exception as e:
            self.log.error(e)
            # 用例失败,必须
            self.base_page.case_failed()
            raise Exception("出现异常!")
        finally:
            self.base_page.back_to()

    def tearDown(self):
        self.base_page.case_end()
コード例 #8
0
class AppLogin(unittest.TestCase):
    """登录"""
    def setUp(self):
        try:
            config = ReadConfig()
            self.base_page = BasePage()
            self.log = MyLog().get_log().logger
            self.user_name = config.get_app_param("user_name")
            self.password = config.get_app_param("password")
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def test_app_login(self):
        """app登录"""
        username_input = ("css_selector", "input[type='text']")  # 用户名输入框定位信息
        password_input = ("css_selector", "input[type='password']"
                          )  # 密码输入框定位信息
        login_button = ("css_selector",
                        "button.button.button-block.button-calm")  # 登录按钮定位信息
        bottom_menu = ("css_selector", "span.tab-title.ng-binding")  # 底部menu
        answer_sheet_elem = ("css_selector",
                             "button.button.button-calm.exam-button"
                             )  # 答题页面的“答题卡”按钮
        submit_button = ("css_selector",
                         "button.button.button-block.button-calm")  # 提交按钮
        # 登录成功提示,有未答题提示,自动提交试卷提示
        popup_title = ("css_selector", "h3.popup-title.ng-binding")  # 提示框title

        try:
            # 用例开始,输入负责人姓名,必须
            self.base_page.case_start("李彬")

            self.log.debug("打开app")
            self.base_page.open_app()

            for i in range(1, 6, +1):
                # 未登录状态
                if self.base_page.displayed(login_button):
                    self.log.debug("输入用户名")
                    self.base_page.input_tag(username_input, self.user_name)
                    self.log.debug("输入密码")
                    self.base_page.input_tag(password_input, self.password)

                    self.base_page.screen_shot()
                    self.log.debug("点击登录按钮")
                    self.base_page.click_elem_tag(login_button)
                    self.base_page.screen_shot()
                    # 用弹框的标题断言
                    self.assertEqual(self.base_page.displayed(login_button),
                                     False, "登录失败!")

                    # 打印弹框上的信息
                    self.base_page.popup()
                    self.log.debug("进入首页!")
                    self.base_page.case_pass()
                    break
                # 有提示框(登录成功提示,自动交卷提示)
                elif self.base_page.displayed(popup_title):
                    # 打印弹框上的信息
                    self.base_page.popup()
                    self.base_page.back_to()  # 返回首页
                    self.log.debug("返回首页!")
                    self.base_page.case_pass()
                    break
                # 处于答题页面
                elif self.base_page.displayed(answer_sheet_elem):
                    self.log.debug("进入app后正处于答题页面,进入答题卡页面提交试卷,结束该次考试!")
                    self.base_page.screen_shot()
                    self.base_page.click_elem_tag(answer_sheet_elem)
                    # 点击提交按钮
                    self.base_page.click_elem_tag(submit_button)

                    # 未答题的提示框
                    self.base_page.popup()
                    self.base_page.back_to()  # 返回首页
                    self.log.debug("返回首页!")
                    self.base_page.case_pass()
                    break
                # 进入首页
                elif self.base_page.displayed(bottom_menu):
                    self.base_page.screen_shot()
                    self.log.debug("进入首页!")
                    self.base_page.case_pass()
                    break
            else:
                raise Exception("打开app时异常!")
        except Exception as e:
            self.log.error(e)
            # 用例失败,必须
            self.base_page.case_failed()
            raise Exception("出现异常!")

    def tearDown(self):
        self.base_page.case_end()
コード例 #9
0
class AppCourseware(unittest.TestCase):
    """课件"""

    def setUp(self):
        try:
            self.base_page = BasePage()
            self.log = MyLog().get_log().logger
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def test_app_courseware(self):
        """app课件"""
        top_menu = ("xpath", "//div[@class='nw-tab']/div")  # 课件类型menu
        search_menu = ("css_selector", "button.button.button-calm.exam-button")  # 搜索按钮
        search_input = ("css_selector", "input[type='text']")  # 搜索内容
        search_button = ("css_selector", "button.button.button-small.button-clear.button-dark.search-button.font-small")  # 搜索按钮
        global text
        text = ""
        try:
            # 用例开始,输入负责人姓名,必须
            self.base_page.case_start("李彬")

            if not self.base_page.home_page_to("课件"):  # 判断待办事项中是否有课件
                if AppCourseware.enter(self) is False:  # 首页进入课件
                    # 如果没有课件就结束用例
                    self.base_page.case_pass()
                    return

            # 开始学习
            self.log.debug("进入全部:")
            AppCourseware.study(self)
            type_count = len(self.base_page.find_elements(top_menu))  # 课件类型数量
            i = 1
            while i < type_count:
                self.base_page.get_text(top_menu, tag=i, text="进入:")
                self.base_page.click_elem_tag(top_menu, tag=i)
                AppCourseware.study(self, tag=i)
                i += 1

            self.log.debug("进入搜索:")
            self.base_page.click_elem_tag(search_menu)
            self.base_page.input_tag(search_input, text)
            self.base_page.screen_shot()

            self.base_page.switch_handle(search_button)
            self.base_page.click_elem_tag(search_button)
            self.base_page.screen_shot()

            self.base_page.switch_handle(search_button)
            AppCourseware.study(self)

            # 用例成功,必须
            self.base_page.case_pass()
        except Exception as e:
            self.log.error(e)
            # 用例失败,必须
            self.base_page.case_failed()
            raise Exception("出现异常!")
        finally:
            self.base_page.back_to()

    def enter(self):
        """进入课件"""
        module = ("css_selector", "img[src='img/courseware.png']")  # 首页“课件”menu
        title = ("css_selector", "div.title.ng-binding")  # “课件”title
        all_list = ("css_selector", "ion-item.item-remove-animate.item-text-wrap.item.item-complex")  # “课件”list

        try:
            self.assertIs(self.base_page.displayed(module), True, "首页异常!")
            self.log.debug("从首页进入课件模块")
            self.base_page.click_elem_tag(module)
            self.base_page.screen_shot()

            self.base_page.switch_handle(title)
            self.assertIs(self.base_page.displayed(title), True, "进入课件模块异常!")
            if self.base_page.displayed(all_list):
                return True
            else:
                self.log.debug("暂无内容!")
                return False
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def study(self, tag=0):
        """学习课件"""
        top_menu = ("xpath", "//div[@class='nw-tab']/div")  # 课件类型menu
        courseware_list = ("css_selector", "ion-item.item-remove-animate.item-complex.item-text-wrap.item")  # 课件list
        courseware_name = ("css_selector", "h2.exam-title.font-large.text-center.ng-binding")  # 课件名称
        start_answer_button = ("xpath", "//a[contains(text(), '开始学习')]")

        try:
            courseware_count = len(self.base_page.find_elements(courseware_list))
            if courseware_count != 0:
                self.base_page.click_elem_tag(courseware_list)
                self.assertIs(self.base_page.displayed(courseware_name), True, "进入课件列表异常!")
                name = self.base_page.get_text(courseware_name, text="进入课件:")
                self.base_page.screen_shot()
                global text
                text = name

                self.base_page.switch_handle(start_answer_button)
                self.assertIs(self.base_page.displayed(start_answer_button), True, "进入课件主页异常!")
                self.log.debug("点击开始学习按钮")
                self.base_page.click_elem_tag(start_answer_button, t=2)
                self.base_page.screen_shot()

                self.base_page.back_to(top_menu)
                self.base_page.click_elem_tag(top_menu, tag=tag)
                self.log.debug("学习完成!")
            else:
                self.log.debug("暂无内容!")
        except Exception as e:
            self.log.error(e)
            raise Exception("出现异常!")

    def tearDown(self):
        self.base_page.case_end()