實戰二:智慧校園web測試
阿新 • • 發佈:2020-10-23
一、common->公共方法
1 import datetime 2 import os 3 4 from selenium.webdriver import ActionChains 5 from selenium.webdriver.support import expected_conditions 6 from selenium.webdriver.support.wait import WebDriverWait 7 from middleware.MiddleHandler import MidInitHandler 8 9 10basepage.pyclass BasePage: 11 handler = MidInitHandler() 12 title = None 13 14 def __init__(self,driver): 15 self.driver = driver 16 # 等待某個頁面載入完成,顯示等待 17 # title_contains 頁面標題包含什麼內容 18 try: 19 WebDriverWait(self.driver,timeout=10,poll_frequency=0.5).until(20 expected_conditions.title_contains(self.title) 21 ) 22 except: 23 print("你的頁面可能沒有進入{}頁面,可能引發異常!".format(self.title)) 24 25 def find_element(self,locator): 26 """查詢元素""" 27 try: 28 elem = self.driver.find_element(*locator)29 return elem 30 except: 31 # 如果找不到元素,截圖 32 self.screen_shot() 33 self.handler.logger.error("元素找不到{}".format(locator)) 34 35 def screen_shot(self): 36 """截圖""" 37 # log/img/2020-08-01-12-10-20.png 38 path = self.handler.conf.IMG_PATH 39 ts = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") 40 filename = os.path.join(path, ts + ".png") 41 self.driver.save_screenshot(filename) 42 43 def wait_element_visible(self,locator,timeout=20,poll=0.5): 44 """等待某個元素可見""" 45 try: 46 elem = WebDriverWait(self.driver,timeout=timeout,poll_frequency=poll).until( 47 expected_conditions.visibility_of_element_located(locator) 48 ) 49 return elem 50 except: 51 self.handler.logger.error("元素找不到{}".format(locator)) 52 53 def wait_element_clickable(self,locator,timeout=20,poll=0.5): 54 """等待某個元素可以被點選""" 55 try: 56 elem = WebDriverWait(self.driver,timeout=timeout,poll_frequency=poll).until( 57 expected_conditions.element_to_be_clickable(locator) 58 ) 59 return elem 60 except: 61 self.handler.logger.error("元素找不到{}".format(locator)) 62 63 def wait_element_presence(self,locator,timeout=20,poll=0.5): 64 """等待某個元素是否出現""" 65 try: 66 elem = WebDriverWait(self.driver,timeout=timeout, poll_frequency=poll).until( 67 expected_conditions.presence_of_element_located(locator) 68 ) 69 return elem 70 except: 71 self.handler.logger.error("元素找不到{}".format(locator)) 72 73 def click(self,locator): 74 """點選某個元素""" 75 self.wait_element_clickable(locator).click() 76 return self 77 78 def send_keys(self,locator,value=""): 79 """輸入資訊""" 80 self.wait_element_visible(locator).send_keys(value) 81 return self 82 83 def clear(self,locator): 84 """清空輸入""" 85 self.wait_element_visible(locator).clear() 86 return self 87 88 def window_scroll(self,height=None,width=None): 89 """視窗滾動""" 90 if not height: 91 height = 0 92 if not width: 93 width = 0 94 js_code = "window.scrollTo({},{})".format(width, height) 95 self.driver.execute_script(js_code) 96 return self 97 98 def move_to(self,locator): 99 """移動某個元素""" 100 elem = self.driver.find_element(*locator) 101 ActionChains(self.driver).move_to_element(elem).perform() 102 return self 103 104 def switch_iframe(self,locator,timeout=20): 105 """進入iframe""" 106 WebDriverWait(self.driver,timeout=timeout).until( 107 expected_conditions.frame_to_be_available_and_switch_to_it(locator) 108 ) 109 return self 110 111 def quit_iframe(self): 112 self.driver.switch_to.default_content() 113 return self 114 115 def upload_file(self,file_path): 116 from pywinauto import Desktop 117 app = Desktop() 118 dialog = app['開啟'] 119 dialog['Edit'].type_keys(file_path) 120 dialog['Button'].click()
1 import openpyxl 2 3 class ExcelHandler: 4 '''excel操作''' 5 6 def __init__(self,file_path): 7 self.file_path = file_path 8 self.workbook = None 9 10 def open_file(self): 11 """開啟檔案""" 12 self.workbook = openpyxl.load_workbook(self.file_path) 13 return self.workbook 14 15 def get_sheet(self,name): 16 """獲取表格""" 17 workbook = self.open_file() 18 return workbook[name] 19 20 def read_data(self,name): 21 """讀取資料""" 22 sheet = self.get_sheet(name) 23 rows = list(sheet.rows) 24 data = [] 25 # 獲取標題 26 headers = [] 27 for title in rows[0]: 28 headers.append(title.value) 29 # 新增資料 30 for row in rows[1:]: 31 row_data = {} 32 for idx,cell in enumerate(row): 33 row_data[headers[idx]] = cell.value 34 data.append(row_data) 35 return data 36 37 def write_data(self,sheet_name,row,column,data): 38 """寫入單元格資料""" 39 sheet = self.get_sheet(sheet_name) 40 sheet.cell(row,column).value = data 41 self.save() 42 self.close() 43 44 def save(self): 45 """儲存""" 46 self.workbook.save(self.file_path) 47 48 def close(self): 49 """關閉""" 50 self.workbook.close()excel_handler.py
1 import logging 2 3 def get_logger( 4 name=None, 5 file=None, 6 logger_level="DEBUG", 7 stream_level="DEBUG", 8 file_level="INFO"): 9 # 獲取收集器 10 logger = logging.getLogger(name) 11 # 設定收集器的級別 12 logger.setLevel(logger_level) 13 # 設定輸入管理器 14 stream_handler = logging.StreamHandler() 15 stream_handler.setLevel(stream_level) 16 logger.addHandler(stream_handler) 17 # 設定格式 18 fmt_value = '%(asctime)s--%(filename)s--%(lineno)d--%(levelname)s--%(message)s' 19 fmt = logging.Formatter(fmt_value) 20 stream_handler.setFormatter(fmt) 21 22 if file: 23 file_handler = logging.FileHandler(file,encoding='utf-8') 24 file_handler.setLevel(file_level) 25 logger.addHandler(file_handler) 26 file_handler.setFormatter(fmt) 27 28 return loggerlogging_handler.py
1 import pymysql 2 from pymysql.cursors import DictCursor 3 4 5 class MysqlHandler(): 6 """資料庫操作""" 7 8 def __init__( 9 self, 10 host=None, 11 port=3306, 12 user=None, 13 password=None, 14 charset="utf8", 15 cursorclass=DictCursor): 16 self.conn = pymysql.connect( 17 host=host, 18 port=port, 19 user=user, 20 password=password, 21 charset=charset, 22 cursorclass=cursorclass) 23 self.cursor = self.conn.cursor() 24 25 def query(self,sql,one=True): 26 """查詢資料庫""" 27 self.conn.commit() # 把最新的資料進行更新(提交事務) 28 self.cursor.execute(sql) 29 if one: 30 return self.cursor.fetchone() 31 return self.cursor.fetchall() 32 33 def close(self): 34 self.cursor.close() 35 self.conn.close()mysql_handler.py
1 import logging 2 import requests 3 4 # 訪問介面封裝 5 def visit( 6 url, 7 params=None, 8 data=None, 9 json=None, 10 method='get', 11 **kwargs): 12 '''訪問介面,返回字典 res.json()''' 13 res = requests.request(method,url,params=params, data=data,json=json,**kwargs) 14 try: 15 return res.json() 16 except Exception as e: 17 logging.error("返回資料不是json格式:{}".format(e)) 18 return Nonerequests_handler.py
1 import logging 2 import requests 3 4 # 訪問介面封裝 5 def visit( 6 url, 7 params=None, 8 data=None, 9 json=None, 10 method='get', 11 **kwargs): 12 '''訪問介面,返回字典 res.json()''' 13 res = requests.request(method,url,params=params, data=data,json=json,**kwargs) 14 try: 15 return res.json() 16 except Exception as e: 17 logging.error("返回資料不是json格式:{}".format(e)) 18 return Noneyaml_handler.py
二、config->配置檔案
1 import os 2 3 # 配置檔案路徑 4 CONFIG_PATH = os.path.dirname(os.path.abspath(__file__)) 5 # 專案路徑 6 ROOT_PATH = os.path.dirname(CONFIG_PATH) 7 # 測試用例路徑 8 CASES_PATH = os.path.join(ROOT_PATH,'tests') 9 # 測試報告路徑 10 REPORTS_PATH = os.path.join(ROOT_PATH,'reports') 11 # 測試資料路徑 12 DATA_PATH = os.path.join(ROOT_PATH,'data') 13 # log資料路徑 14 LOG_PATH = os.path.join(ROOT_PATH,'logs') 15 # img路徑 16 IMG_PATH = os.path.join(LOG_PATH,'img')config.py
1 excel: 2 file: cases.xlsx 3 4 logger: 5 name: "smartcampus" 6 file: "smartcampuslog.txt" 7 logger_level: "DEBUG" 8 stream_level: "DEBUG" 9 file_level: "INFO" 10 11 db: 12 host: "120.78.128.25" 13 port: 3306 14 user: "future" 15 password: "123456" 16 charset: "utf8" 17 18 selenium: 19 wait_time: 20 20 21 host: "http://172.31.21.148:40099/#"config.yaml
三、data->測試資料
1 login_error = [ 2 {"title":"賬號、密碼均為空","username": "", "password": "", "expected": "伺服器內部錯誤"}, 3 {"title":"賬號為空,密碼正確","username": "", "password": "123456", "expected": "伺服器內部錯誤"}, 4 {"title":"賬號正確,密碼為空","username": "admin", "password": "", "expected": "密碼不正確"}, 5 {"title":"賬號正確,密碼錯誤","username": "admin", "password": "987654", "expected": "密碼不正確"}, 6 {"title":"賬號錯誤,密碼正確","username": "admin111", "password": "123456", "expected": "伺服器內部錯誤"} 7 ] 8 9 login_success = [ 10 {"title":"賬號、密碼均正確","username": "admin", "password": "123456", "expected": "歡迎您"} 11 ]login_data.py
1 open_org_page = [ 2 {"title":"開啟機構管理頁面","expected": "機構名稱"} 3 ] 4 5 add_data_normal = [ 6 {"title":"新增機構名稱合法","org_name":"測試機構"} 7 ] 8 9 add_data_abnormal = [ 10 {"title":"新增機構名稱為空","org_name":"","expected":"請輸入名稱"}, 11 {"title":"新增機構名稱超過20字元","org_name":"測試機構@12345測試機構@123456","expected":"請勿超過20個字元"}, 12 ] 13 14 edit_data_normal = [ 15 {"title":"編輯機構名稱合法","org_name":"測試機構"} 16 ]org_manage_data.py
1 open_role_page = [ 2 {"title":"開啟角色管理頁面","expected": "角色名"} 3 ] 4 5 add_role_normal = [ 6 {"title":"新增角色名稱合法","role_name":"測試角色","describe":"角色描述資訊"} 7 ] 8 9 add_role_abnormal = [ 10 {"title":"新增角色名稱為空","role_name":"","describe":"角色描述資訊","expected":"請輸入名稱"}, 11 {"title":"新增角色名稱超過20字元","role_name":"測試角色@12345測試角色@123456","describe":"角色描述資訊","expected":"請勿超過20個字元"}, 12 ] 13 edit_role_normal = [ 14 {"title":"編輯角色名稱合法","role_name":"測試角色","describe":"角色描述資訊"} 15 ] 16 17 search_normal = [ 18 {"title":"搜尋系統存在的角色名","role_name":"測試角色"} 19 ] 20 21 search_abnormal = [ 22 {"title":"搜尋系統不存在的角色名","role_name":"小章","expected":"暫無資料"} 23 ] 24 25 assign_menu = [ 26 {"title":"為角色分配選單","expected":"操作成功"} 27 ] 28 29 assign_auth = [ 30 {"title":"為角色分配許可權","expected":"操作成功"} 31 ] 32 33 del_role = [ 34 {"title":"刪除角色"} 35 ]role_manage_data.py
1 open_menu_page = [ 2 {"title":"開啟選單管理頁面","expected": "選單URL"} 3 ] 4 5 add_menu_normal = [ 6 {"title":"成功新增選單","menu_name":"測試選單","menu_url":"/test/add/index","menu_icon":"el-icon-position"} 7 ] 8 9 add_menu_abnormal = [ 10 {"title":"新增選單名稱為空","menu_name":"","menu_url":"/test/add/index","menu_icon":"el-icon-position","expected":"請輸入名稱"}, 11 {"title":"新增選單名稱超過20字元","menu_name":"測試選單@12345測試選單@123456","menu_url":"/test/add/index","menu_icon":"el-icon-position","expected":"請勿超過20個字元"}, 12 ] 13 14 edit_menu_normal = [ 15 {"title":"成功編輯選單","menu_name":"測試選單","menu_url":"/test/edit/index","menu_icon":"el-icon-position"} 16 ] 17 18 search_normal = [ 19 {"title":"搜尋系統存在的選單名","menu_name":"測試選單"} 20 ] 21 22 search_abnormal = [ 23 {"title":"搜尋系統不存在的選單名","menu_name":"小章","expected":"暫無資料"} 24 ] 25 26 del_menu= [ 27 {"title":"刪除選單"} 28 ]menu_manage_data.py
1 open_dict_page = [ 2 {"title":"開啟字典管理頁面","expected": "字典列表"} 3 ] 4 5 add_dict_normal = [ 6 {"title":"成功新增字典","dict_name":"測試字典","describe":"測試字典描述"} 7 ] 8 9 add_dict_abnormal = [ 10 {"title":"新增字典名稱為空","dict_name":"","describe":"測試字典描述","expected":"請輸入名稱"}, 11 {"title":"新增字典名稱超過20字元","dict_name":"測試字典@12345測試字典@123456","describe":"測試字典描述","expected":"請勿超過20個字元"}, 12 ] 13 14 edit_dict_normal = [ 15 {"title":"成功編輯字典","dict_name":"測試選單","describe":"測試字典描述"} 16 ] 17 18 search_dictname_normal = [ 19 {"title":"搜尋系統存在的字典名","dict_name":"測試選單"} 20 ] 21 22 search_dictdescribe_normal = [ 23 {"title":"搜尋系統存在的字典描述","describe":"測試字典描述"} 24 ] 25 26 search_dictname_abnormal = [ 27 {"title":"搜尋系統不存在的字典名","dict_name":"小章","expected":"暫無資料"} 28 ] 29 30 del_dict= [ 31 {"title":"刪除字典"} 32 ] 33 34 add_dictdetails_normal = [ 35 {"title":"成功新增字典詳情","dict_label":"測試字典詳情標籤","value":"測試字典詳情值"} 36 ] 37 38 add_dictdetails_abnormal = [ 39 {"title":"新增字典標籤為空","dict_label":"","value":"測試字典詳情值","expected":"請輸入字典標籤"}, 40 {"title":"新增字典標籤超過20字元","dict_label":"測試字典@12345測試字典@123456","value":"測試字典詳情值","expected":"請勿超過20個字元"}, 41 ] 42 43 edit_dictdetails_normal = [ 44 {"title":"成功編輯字典詳情","dict_label":"測試字典詳情標籤","value":"測試字典詳情值"} 45 ] 46 47 search_dict_label_normal = [ 48 {"title":"搜尋系統存在的字典標籤","dict_label":"測試字典詳情標籤"} 49 ] 50 51 search_dict_label_abnormal = [ 52 {"title":"搜尋系統不存在的字典標籤","dict_label":"小章","expected":"暫無資料"} 53 ] 54 55 del_dictdetails= [ 56 {"title":"刪除字典詳情"} 57 ]dict_manage_data.py
1 open_auth_page = [ 2 {"title":"開啟許可權管理頁面","expected": "授權標識"} 3 ] 4 5 add_auth_normal = [ 6 {"title":"成功新增許可權","auth_name":"測試許可權","auth_mark":"add.auth.mark"} 7 ] 8 9 add_auth_abnormal = [ 10 {"title":"新增許可權名稱為空","auth_name":"","auth_mark":"add.auth.mark","expected":"請輸入名稱"}, 11 {"title":"新增許可權名稱超過20字元","auth_name":"測試許可權@12345測試許可權@123456","auth_mark":"add.auth.mark","expected":"請勿超過20個字元"}, 12 ] 13 14 edit_auth_normal = [ 15 {"title":"成功編輯許可權","auth_name":"測試許可權","auth_mark":"edit.auth.mark"} 16 ] 17 18 search_normal = [ 19 {"title":"搜尋系統存在的許可權名","auth_name":"測試許可權"} 20 ] 21 22 search_abnormal = [ 23 {"title":"搜尋系統不存在的許可權名","auth_name":"小章","expected":"暫無資料"} 24 ] 25 26 del_auth = [ 27 {"title":"刪除許可權"} 28 ]auth_manage_data.py
1 open_send_email = [ 2 {"title":"打開發布郵件頁面","expected": "釋出郵件"} 3 ] 4 5 send_email_normal =[ 6 {"title":"釋出郵件","theme": "自動化測試","content":"自動化測試內容","expected": "釋出郵件"} 7 ] 8 9 send_email_abnormal =[ 10 {"title":"釋出郵件-主題為空","theme": "","content":"自動化測試內容","expected": "標題不能為空!"}, 11 {"title":"釋出郵件-正文為空","theme": "自動化測試","content":"","expected": "正文不能為空!"} 12 ] 13 14 search_email_normal= [ 15 {"title":"按標題查詢列表存在的郵件標題","theme": "自動化測試"} 16 ] 17 18 search_email_abnormal= [ 19 {"title":"按標題查詢列表不存在的郵件標題","theme": "小章"} 20 ]send_email.py
四、libs->第三方包
1 1 #coding=utf-8 2 2 """ 3 3 A連線資訊 TestRunner for use with the Python unit testing framework. It 4 4 generates a HTML report to show the result at a glance. 5 5 The simplest way to use this is to invoke its main method. E列表.g. 6 6 import unittest 7 7 import HTMLTestRunner 8 8 ... define your tests ... 9 9 if __name__ == '__main__': 10 10 HTMLTestRunner.main() 11 11 For more customization options, instantiates a HTMLTestRunner object. 12 12 HTMLTestRunner is a counterpart to unittest's TextTestRunner. E列表.g. 13 13 # output to a file 14 14 fp = file('my_report.html', 'wb') 15 15 common = HTMLTestRunner.HTMLTestRunner( 16 16 stream=fp, 17 17 title='My unit test', 18 18 description='This demonstrates the report output by HTMLTestRunner.' 19 19 ) 20 20 # Use an external stylesheet. 21 21 # See the Template_mixin class for more customizable options 22 22 common.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">' 23 23 # run the test 24 24 common.run(my_test_suite) 25 25 ------------------------------------------------------------------------ 26 26 Copyright (c) 2004-2007, Wai Yip Tung 27 27 All rights reserved. 28 28 Redistribution and use in source and binary forms, with or without 29 29 modification, are permitted provided that the following conditions are 30 30 met: 31 31 * Redistributions of source code must retain the above copyright notice, 32 32 this list of conditions and the following disclaimer. 33 33 * Redistributions in binary form must reproduce the above copyright 34 34 notice, this list of conditions and the following disclaimer in the 35 35 documentation and/or other materials provided with the distribution. 36 36 * Neither the name Wai Yip Tung nor the names of its contributors may be 37 37 used to endorse or promote products derived from this software without 38 38 specific prior written permission. 39 39 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 40 40 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 41 41 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A連線資訊 42 42 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 43 43 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 44 44 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 45 45 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 46 46 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 47 47 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 48 48 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 49 49 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 50 """ 51 51 52 52 # URL: http://tungwaiyip.info/software/HTMLTestRunner.html 53 53 54 54 __author__ = "Wai Yip Tung, Findyou" 55 55 __version__ = "0.8.2.2" 56 56 57 57 58 58 """ 59 59 Change History 60 60 Version 0.8.2.1 -Findyou 61 61 * 改為支援python3 62 62 Version 0.8.2.1 -Findyou 63 63 * 支援中文,漢化 64 64 * 調整樣式,美化(需要連入網路,使用的百度的Bootstrap.js) 65 65 * 增加 通過分類顯示、測試人員、通過率的展示 66 66 * 優化“詳細”與“收起”狀態的變換 67 67 * 增加返回頂部的錨點 68 68 Version 0.8.2 69 69 * Show output inline instead of popup window (Viorel Lupu). 70 70 Version in 0.8.1 71 71 * Validated XHTML (Wolfgang Borgert). 72 72 * Added description of test classes and test cases. 73 73 Version in 0.8.0 74 74 * Define Template_mixin class for customization. 75 75 * Workaround a IE 6 bug that it does not treat <script> block as CDATA. 76 76 Version in 0.7.1 77 77 * Back port to Python 2.3 (Frank Horowitz). 78 78 * Fix missing scroll bars in detail log (Podi). 79 79 """ 80 80 81 81 # TODO: color stderr 82 82 # TODO: simplify javascript using ,ore than 1 class in the class attribute? 83 83 84 84 import datetime 85 85 import io 86 86 import sys 87 87 import time 88 88 import unittest 89 89 from xml.sax import saxutils 90 90 91 91 92 92 # ------------------------------------------------------------------------ 93 93 # The redirectors below are used to capture output during testing. Output 94 94 # sent to sys.stdout and sys.stderr are automatically captured. However 95 95 # in some cases sys.stdout is already cached before HTMLTestRunner is 96 96 # invoked (e.g. calling logging.basicConfig). In order to capture those 97 97 # output, use the redirectors for the cached stream. 98 98 # 99 99 # e.g. 100 100 # >>> logging.basicConfig(stream=HTMLTestRunner.stdout_redirector) 101 101 # >>> 102 102 103 103 class OutputRedirector(object): 104 104 """ Wrapper to redirect stdout or stderr """ 105 105 def __init__(self, fp): 106 106 self.fp = fp 107 107 108 108 def write(self, s): 109 109 self.fp.write(s) 110 110 111 111 def writelines(self, lines): 112 112 self.fp.writelines(lines) 113 113 114 114 def flush(self): 115 115 self.fp.flush() 116 116 117 117 stdout_redirector = OutputRedirector(sys.stdout) 118 118 stderr_redirector = OutputRedirector(sys.stderr) 119 119 120 120 # ---------------------------------------------------------------------- 121 121 # Template 122 122 123 123 class Template_mixin(object): 124 124 """ 125 125 Define a HTML template for report customerization and generation. 126 126 Overall structure of an HTML report 127 127 HTML 128 128 +------------------------+ 129 129 |<html> | 130 130 | <head> | 131 131 | | 132 132 | STYLESHEET | 133 133 | +----------------+ | 134 134 | | | | 135 135 | +----------------+ | 136 136 | | 137 137 | </head> | 138 138 | | 139 139 | <body> | 140 140 | | 141 141 | HEADING | 142 142 | +----------------+ | 143 143 | | | | 144 144 | +----------------+ | 145 145 | | 146 146 | REPORT | 147 147 | +----------------+ | 148 148 | | | | 149 149 | +----------------+ | 150 150 | | 151 151 | ENDING | 152 152 | +----------------+ | 153 153 | | | | 154 154 | +----------------+ | 155 155 | | 156 156 | </body> | 157 157 |</html> | 158 158 +------------------------+ 159 159 """ 160 160 161 161 STATUS = { 162 162 0: '通過', 163 163 1: '失敗', 164 164 2: '錯誤', 165 165 } 166 166 167 167 DEFAULT_TITLE = '2019年的自動化測試報告' 168 168 DEFAULT_DESCRIPTION = '' 169 169 DEFAULT_TESTER='lemon' 170 170 171 171 # ------------------------------------------------------------------------ 172 172 # HTML Template 173 173 174 174 HTML_TMPL = r"""<?xml version="1.0" encoding="UTF-8"?> 175 175 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 176 176 <html xmlns="http://www.w3.org/1999/xhtml"> 177 177 <head> 178 178 <title>%(title)s</title> 179 179 <meta name="generator" content="%(generator)s"/> 180 180 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 181 181 <link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> 182 182 <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> 183 183 <script src="http://libs.baidu.com/bootstrap/3.0.3/js/bootstrap.min.js"></script> 184 184 %(stylesheet)s 185 185 </head> 186 186 <body > 187 187 <script language="javascript" type="text/javascript"> 188 188 output_list = Array(); 189 189 /*level 調整增加只顯示通過用例的分類 --Findyou 190 190 0:Summary //all hiddenRow 191 191 1:Failed //pt hiddenRow, ft none 192 192 2:Pass //pt none, ft hiddenRow 193 193 3:All //pt none, ft none 194 194 */ 195 195 function showCase(level) { 196 196 trs = document.getElementsByTagName("tr"); 197 197 for (var i = 0; i < trs.length; i++) { 198 198 tr = trs[i]; 199 199 id = tr.id; 200 200 if (id.substr(0,2) == 'ft') { 201 201 if (level == 2 || level == 0 ) { 202 202 tr.className = 'hiddenRow'; 203 203 } 204 204 else { 205 205 tr.className = ''; 206 206 } 207 207 } 208 208 if (id.substr(0,2) == 'pt') { 209 209 if (level < 2) { 210 210 tr.className = 'hiddenRow'; 211 211 } 212 212 else { 213 213 tr.className = ''; 214 214 } 215 215 } 216 216 } 217 217 //加入【詳細】切換文字變化 --Findyou 218 218 detail_class=document.getElementsByClassName('detail'); 219 219 //console.log(detail_class.length) 220 220 if (level == 3) { 221 221 for (var i = 0; i < detail_class.length; i++){ 222 222 detail_class[i].innerHTML="收起" 223 223 } 224 224 } 225 225 else{ 226 226 for (var i = 0; i < detail_class.length; i++){ 227 227 detail_class[i].innerHTML="詳細" 228 228 } 229 229 } 230 230 } 231 231 function showClassDetail(cid, count) { 232 232 var id_list = Array(count); 233 233 var toHide = 1; 234 234 for (var i = 0; i < count; i++) { 235 235 //ID修改 點 為 下劃線 -Findyou 236 236 tid0 = 't' + cid.substr(1) + '_' + (i+1); 237 237 tid = 'f' + tid0; 238 238 tr = document.getElementById(tid); 239 239 if (!tr) { 240 240 tid = 'p' + tid0; 241 241 tr = document.getElementById(tid); 242 242 } 243 243 id_list[i] = tid; 244 244 if (tr.className) { 245 245 toHide = 0; 246 246 } 247 247 } 248 248 for (var i = 0; i < count; i++) { 249 249 tid = id_list[i]; 250 250 //修改點選無法收起的BUG,加入【詳細】切換文字變化 --Findyou 251 251 if (toHide) { 252 252 document.getElementById(tid).className = 'hiddenRow'; 253 253 document.getElementById(cid).innerText = "詳細" 254 254 } 255 255 else { 256 256 document.getElementById(tid).className = ''; 257 257 document.getElementById(cid).innerText = "收起" 258 258 } 259 259 } 260 260 } 261 261 function html_escape(s) { 262 262 s = s.replace(/&/g,'&'); 263 263 s = s.replace(/</g,'<'); 264 264 s = s.replace(/>/g,'>'); 265 265 return s; 266 266 } 267 267 </script> 268 268 %(heading)s 269 269 %(report)s 270 270 %(ending)s 271 271 </body> 272 272 </html> 273 273 """ 274 274 # variables: (title, generator, stylesheet, heading, report, ending) 275 275 276 276 277 277 # ------------------------------------------------------------------------ 278 278 # Stylesheet 279 279 # 280 280 # alternatively use a <link> for external style sheet, e.g. 281 281 # <link rel="stylesheet" href="$url" type="text/css"> 282 282 283 283 STYLESHEET_TMPL = """ 284 284 <style type="text/css" media="screen"> 285 285 body { font-family: Microsoft YaHei,Tahoma,arial,helvetica,sans-serif;padding: 20px; font-size: 120%; } 286 286 table { font-size: 100%; } 287 287 /* -- heading ---------------------------------------------------------------------- */ 288 288 .heading { 289 289 margin-top: 0ex; 290 290 margin-bottom: 1ex; 291 291 } 292 292 .heading .description { 293 293 margin-top: 4ex; 294 294 margin-bottom: 6ex; 295 295 } 296 296 /* -- report ------------------------------------------------------------------------ */ 297 297 #total_row { font-weight: bold; } 298 298 .passCase { color: #5cb85c; } 299 299 .failCase { color: #d9534f; font-weight: bold; } 300 300 .errorCase { color: #f0ad4e; font-weight: bold; } 301 301 .hiddenRow { display: none; } 302 302 .testcase { margin-left: 2em; } 303 303 </style> 304 304 """ 305 305 306 306 # ------------------------------------------------------------------------ 307 307 # Heading 308 308 # 309 309 310 310 HEADING_TMPL = """<div class='heading'> 311 311 <h1 style="font-family: Microsoft YaHei">%(title)s</h1> 312 312 %(parameters)s 313 313 <p class='description'>%(description)s</p> 314 314 </div> 315 315 """ # variables: (title, parameters, description) 316 316 317 317 HEADING_ATTRIBUTE_TMPL = """<p class='attribute'><strong>%(name)s : </strong> %(value)s</p> 318 318 """ # variables: (name, value) 319 319 320 320 321 321 322 322 # ------------------------------------------------------------------------ 323 323 # Report 324 324 # 325 325 # 漢化,加美化效果 --Findyou 326 326 REPORT_TMPL = """ 327 327 <p id='show_detail_line'> 328 328 <a class="btn btn-primary" href='javascript:showCase(0)'>概要{ %(passrate)s }</a> 329 329 <a class="btn btn-danger" href='javascript:showCase(1)'>失敗{ %(fail)s }</a> 330 330 <a class="btn btn-success" href='javascript:showCase(2)'>通過{ %(Pass)s }</a> 331 331 <a class="btn btn-info" href='javascript:showCase(3)'>所有{ %(count)s }</a> 332 332 </p> 333 333 <table id='result_table' class="table table-condensed table-bordered table-hover"> 334 334 <colgroup> 335 335 <col align='left' /> 336 336 <col align='right' /> 337 337 <col align='right' /> 338 338 <col align='right' /> 339 339 <col align='right' /> 340 340 <col align='right' /> 341 341 </colgroup> 342 342 <tr id='header_row' class="text-center success" style="font-weight: bold;font-size: 16px;"> 343 343 <td>用例集/測試用例</td> 344 344 <td>總計</td> 345 345 <td>通過</td> 346 346 <td>失敗</td> 347 347 <td>錯誤</td> 348 348 <td>詳細</td> 349 349 </tr> 350 350 %(test_list)s 351 351 <tr id='total_row' class="text-center active"> 352 352 <td>總計</td> 353 353 <td>%(count)s</td> 354 354 <td>%(Pass)s</td> 355 355 <td>%(fail)s</td> 356 356 <td>%(error)s</td> 357 357 <td>通過率:%(passrate)s</td> 358 358 </tr> 359 359 </table> 360 360 """ # variables: (test_list, count, Pass, fail, error ,passrate) 361 361 362 362 REPORT_CLASS_TMPL = r""" 363 363 <tr class='%(style)s warning'> 364 364 <td>%(desc)s</td> 365 365 <td class="text-center">%(count)s</td> 366 366 <td class="text-center">%(Pass)s</td> 367 367 <td class="text-center">%(fail)s</td> 368 368 <td class="text-center">%(error)s</td> 369 369 <td class="text-center"><a href="javascript:showClassDetail('%(cid)s',%(count)s)" class="detail" id='%(cid)s'>詳細</a></td> 370 370 </tr> 371 371 """ # variables: (style, desc, count, Pass, fail, error, cid) 372 372 373 373 #失敗 的樣式,去掉原來JS效果,美化展示效果 -Findyou 374 374 REPORT_TEST_WITH_OUTPUT_TMPL = r""" 375 375 <tr id='%(tid)s' class='%(Class)s'> 376 376 <td class='%(style)s'><div class='testcase'>%(desc)s</div></td> 377 377 <td colspan='5' align='center'> 378 378 <!--預設收起錯誤資訊 -Findyou 379 379 <button id='btn_%(tid)s' type="button" class="btn btn-danger btn-xs collapsed" data-toggle="collapse" data-target='#div_%(tid)s'>%(status)s</button> 380 380 <div id='div_%(tid)s' class="collapse"> --> 381 381 <!-- 預設展開錯誤資訊 -Findyou --> 382 382 <button id='btn_%(tid)s' type="button" class="btn btn-danger btn-xs" data-toggle="collapse" data-target='#div_%(tid)s'>%(status)s</button> 383 383 <div id='div_%(tid)s' class="collapse in" align="left"> 384 384 <pre> 385 385 %(script)s 386 386 </pre> 387 387 </div> 388 388 </td> 389 389 </tr> 390 390 """ # variables: (tid, Class, style, desc, status) 391 391 392 392 # 通過 的樣式,加標籤效果 -Findyou 393 393 REPORT_TEST_NO_OUTPUT_TMPL = r""" 394 394 <tr id='%(tid)s' class='%(Class)s'> 395 395 <td class='%(style)s'><div class='testcase'>%(desc)s</div></td> 396 396 <td colspan='5' align='center'><span class="label label-success success">%(status)s</span></td> 397 397 </tr> 398 398 """ # variables: (tid, Class, style, desc, status) 399 399 400 400 REPORT_TEST_OUTPUT_TMPL = r""" 401 401 %(id)s: %(output)s 402 402 """ # variables: (id, output) 403 403 404 404 # ------------------------------------------------------------------------ 405 405 # ENDING 406 406 # 407 407 # 增加返回頂部按鈕 --Findyou 408 408 ENDING_TMPL = """<div id='ending'></div> 409 409 <div style=" position:fixed;right:50px; bottom:30px; width:20px; height:20px;cursor:pointer"> 410 410 <a href="#"><span class="glyphicon glyphicon-eject" style = "font-size:30px;" aria-hidden="true"> 411 411 </span></a></div> 412 412 """ 413 413 414 414 # -------------------- The end of the Template class ------------------- 415 415 416 416 417 417 TestResult = unittest.TestResult 418 418 419 419 class _TestResult(TestResult): 420 420 # note: _TestResult is a pure representation of results. 421 421 # It lacks the output and reporting ability compares to unittest._TextTestResult. 422 422 423 423 def __init__(self, verbosity=1): 424 424 TestResult.__init__(self) 425 425 self.stdout0 = None 426 426 self.stderr0 = None 427 427 self.success_count = 0 428 428 self.failure_count = 0 429 429 self.error_count = 0 430 430 self.verbosity = verbosity 431 431 432 432 # result is a list of result in 4 tuple 433 433 # ( 434 434 # result code (0: success; 1: fail; 2: error), 435 435 # TestCase object, 436 436 # Test output (byte string), 437 437 # stack trace, 438 438 # ) 439 439 self.result = [] 440 440 #增加一個測試通過率 --Findyou 441 441 self.passrate=float(0) 442 442 443 443 444 444 def startTest(self, test): 445 445 print("{0} - Start Test:{1}".format(time.asctime(),str(test))) 446 446 TestResult.startTest(self, test) 447 447 # just one buffer for both stdout and stderr 448 448 self.outputBuffer = io.StringIO() 449 449 stdout_redirector.fp = self.outputBuffer 450 450 stderr_redirector.fp = self.outputBuffer 451 451 self.stdout0 = sys.stdout 452 452 self.stderr0 = sys.stderr 453 453 sys.stdout = stdout_redirector 454 454 sys.stderr = stderr_redirector 455 455 456 456 457 457 def complete_output(self): 458 458 """ 459 459 Disconnect output redirection and return buffer. 460 460 Safe to call multiple times. 461 461 """ 462 462 if self.stdout0: 463 463 sys.stdout = self.stdout0 464 464 sys.stderr = self.stderr0 465 465 self.stdout0 = None 466 466 self.stderr0 = None 467 467 return self.outputBuffer.getvalue() 468 468 469 469 470 470 def stopTest(self, test): 471 471 # Usually one of addSuccess, addError or addFailure would have been called. 472 472 # But there are some path in unittest that would bypass this. 473 473 # We must disconnect stdout in stopTest(), which is guaranteed to be called. 474 474 self.complete_output() 475 475 476 476 477 477 def addSuccess(self, test): 478 478 self.success_count += 1 479 479 TestResult.addSuccess(self, test) 480 480 output = self.complete_output() 481 481 self.result.append((0, test, output, '')) 482 482 if self.verbosity > 1: 483 483 sys.stderr.write('ok ') 484 484 sys.stderr.write(str(test)) 485 485 sys.stderr.write('\n') 486 486 else: 487 487 sys.stderr.write('.') 488 488 489 489 def addError(self, test, err): 490 490 self.error_count += 1 491 491 TestResult.addError(self, test, err) 492 492 _, _exc_str = self.errors[-1] 493 493 output = self.complete_output() 494 494 self.result.append((2, test, output, _exc_str)) 495 495 if self.verbosity > 1: 496 496 sys.stderr.write('E列表 ') 497 497 sys.stderr.write(str(test)) 498 498 sys.stderr.write('\n') 499 499 else: 500 500 sys.stderr.write('E列表') 501 501 502 502 def addFailure(self, test, err): 503 503 self.failure_count += 1 504 504 TestResult.addFailure(self, test, err) 505 505 _, _exc_str = self.failures[-1] 506 506 output = self.complete_output() 507 507 self.result.append((1, test, output, _exc_str)) 508 508 if self.verbosity > 1: 509 509 sys.stderr.write('F ') 510 510 sys.stderr.write(str(test)) 511 511 sys.stderr.write('\n') 512 512 else: 513 513 sys.stderr.write('F') 514 514 515 515 516 516 class HTMLTestRunner(Template_mixin): 517 517 """ 518 518 """ 519 519 def __init__(self, stream=sys.stdout, verbosity=2,title=None,description=None,tester=None): 520 520 self.stream = stream 521 521 self.verbosity = verbosity 522 522 if title is None: 523 523 self.title = self.DEFAULT_TITLE 524 524 else: 525 525 self.title = title 526 526 if description is None: 527 527 self.description = self.DEFAULT_DESCRIPTION 528 528 else: 529 529 self.description = description 530 530 if tester is None: 531 531 self.tester = self.DEFAULT_TESTER 532 532 else: 533 533 self.tester = tester 534 534 535 535 self.startTime = datetime.datetime.now() 536 536 537 537 538 538 def run(self, test): 539 539 "Run the given test case or test suite." 540 540 result = _TestResult(self.verbosity) 541 541 test(result) 542 542 self.stopTime = datetime.datetime.now() 543 543 self.generateReport(test, result) 544 544 print('\nTime Elapsed: %s' % (self.stopTime-self.startTime), file=sys.stderr) 545 545 return result 546 546 547 547 548 548 def sortResult(self, result_list): 549 549 # unittest does not seems to run in any particular order. 550 550 # Here at least we want to group them together by class. 551 551 rmap = {} 552 552 classes = [] 553 553 for n,t,o,e in result_list: 554 554 cls = t.__class__ 555 555 if cls not in rmap: 556 556 rmap[cls] = [] 557 557 classes.append(cls) 558 558 rmap[cls].append((n,t,o,e)) 559 559 r = [(cls, rmap[cls]) for cls in classes] 560 560 return r 561 561 562 562 #替換測試結果status為通過率 --Findyou 563 563 def getReportAttributes(self, result): 564 564 """ 565 565 Return report attributes as a list of (name, value). 566 566 Override this to add custom attributes. 567 567 """ 568 568 startTime = str(self.startTime)[:19] 569 569 duration = str(self.stopTime - self.startTime) 570 570 status = [] 571 571 status.append('共 %s' % (result.success_count + result.failure_count + result.error_count)) 572 572 if result.success_count: status.append('通過 %s' % result.success_count) 573 573 if result.failure_count: status.append('失敗 %s' % result.failure_count) 574 574 if result.error_count: status.append('錯誤 %s' % result.error_count ) 575 575 if status: 576 576 status = ','.join(status) 577 577 self.passrate = str("%.2f%%" % (float(result.success_count) / float(result.success_count + result.failure_count + result.error_count) * 100)) 578 578 else: 579 579 status = 'none' 580 580 return [ 581 581 ('測試人員', self.tester), 582 582 ('開始時間',startTime), 583 583 ('合計耗時',duration), 584 584 ('測試結果',status + ",通過率= "+self.passrate), 585 585 ] 586 586 587 587 588 588 def generateReport(self, test, result): 589 589 report_attrs = self.getReportAttributes(result) 590 590 generator = 'HTMLTestRunner %s' % __version__ 591 591 stylesheet = self._generate_stylesheet() 592 592 heading = self._generate_heading(report_attrs) 593 593 report = self._generate_report(result) 594 594 ending = self._generate_ending() 595 595 output = self.HTML_TMPL % dict( 596 596 title = saxutils.escape(self.title), 597 597 generator = generator, 598 598 stylesheet = stylesheet, 599 599 heading = heading, 600 600 report = report, 601 601 ending = ending, 602 602 ) 603 603 self.stream.write(output.encode('utf8')) 604 604 605 605 606 606 def _generate_stylesheet(self): 607 607 return self.STYLESHEET_TMPL 608 608 609 609 #增加Tester顯示 -Findyou 610 610 def _generate_heading(self, report_attrs): 611 611 a_lines = [] 612 612 for name, value in report_attrs: 613 613 line = self.HEADING_ATTRIBUTE_TMPL % dict( 614 614 name = saxutils.escape(name), 615 615 value = saxutils.escape(value), 616 616 ) 617 617 a_lines.append(line) 618 618 heading = self.HEADING_TMPL % dict( 619 619 title = saxutils.escape(self.title), 620 620 parameters = ''.join(a_lines), 621 621 description = saxutils.escape(self.description), 622 622 tester= saxutils.escape(self.tester), 623 623 ) 624 624 return heading 625 625 626 626 #生成報告 --Findyou添加註釋 627 627 def _generate_report(self, result): 628 628 rows = [] 629 629 sortedResult = self.sortResult(result.result) 630 630 for cid, (cls, cls_results) in enumerate(sortedResult): 631 631 # subtotal for a class 632 632 np = nf = ne = 0 633 633 for n,t,o,e in cls_results: 634 634 if n == 0: np += 1 635 635 elif n == 1: nf += 1 636 636 else: ne += 1 637 637 638 638 # format class description 639 639 if cls.__module__ == "__main__": 640 640 name = cls.__name__ 641 641 else: 642 642 name = "%s.%s" % (cls.__module__, cls.__name__) 643 643 doc = cls.__doc__ and cls.__doc__.split("\n")[0] or "" 644 644 desc = doc and '%s: %s' % (name, doc) or name 645 645 646 646 row = self.REPORT_CLASS_TMPL % dict( 647 647 style = ne > 0 and 'errorClass' or nf > 0 and 'failClass' or 'passClass', 648 648 desc = desc, 649 649 count = np+nf+ne, 650 650 Pass = np, 651 651 fail = nf, 652 652 error = ne, 653 653 cid = 'c%s' % (cid+1), 654 654 ) 655 655 rows.append(row) 656 656 657 657 for tid, (n,t,o,e) in enumerate(cls_results): 658 658 self._generate_report_test(rows, cid, tid, n, t, o, e) 659 659 660 660 report = self.REPORT_TMPL % dict( 661 661 test_list = ''.join(rows), 662 662 count = str(result.success_count+result.failure_count+result.error_count), 663 663 Pass = str(result.success_count), 664 664 fail = str(result.failure_count), 665 665 error = str(result.error_count), 666 666 passrate =self.passrate, 667 667 ) 668 668 return report 669 669 670 670 671 671 def _generate_report_test(self, rows, cid, tid, n, t, o, e): 672 672 # e.g. 'pt1.1', 'ft1.1', etc 673 673 has_output = bool(o or e) 674 674 # ID修改點為下劃線,支援Bootstrap摺疊展開特效 - Findyou 675 675 tid = (n == 0 and 'p' or 'f') + 't%s_%s' % (cid+1,tid+1) 676 676 name = t.id().split('.')[-1] 677 677 doc = t.shortDescription() or "" 678 678 desc = doc and ('%s: %s' % (name, doc)) or name 679 679 tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL 680 680 681 681 # utf-8 支援中文 - Findyou 682 682 # o and e should be byte string because they are collected from stdout and stderr? 683 683 if isinstance(o, str): 684 684 # TODO: some problem with 'string_escape': it escape \n and mess up formating 685 685 # uo = unicode(o.encode('string_escape')) 686 686 # uo = o.decode('latin-1') 687 687 uo = o 688 688 else: 689 689 uo = o 690 690 if isinstance(e, str): 691 691 # TODO: some problem with 'string_escape': it escape \n and mess up formating 692 692 # ue = unicode(e.encode('string_escape')) 693 693 # ue = e.decode('latin-1') 694 694 ue = e 695 695 else: 696 696 ue = e 697 697 698 698 script = self.REPORT_TEST_OUTPUT_TMPL % dict( 699 699 id = tid, 700 700 output = saxutils.escape(uo+ue), 701 701 ) 702 702 703 703 row = tmpl % dict( 704 704 tid = tid, 705 705 Class = (n == 0 and 'hiddenRow' or 'none'), 706 706 style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'passCase'), 707 707 desc = desc, 708 708 script = script, 709 709 status = self.STATUS[n], 710 710 ) 711 711 rows.append(row) 712 712 if not has_output: 713 713 return 714 714 715 715 def _generate_ending(self): 716 716 return self.ENDING_TMPL 717 717 718 718 719 719 ############################################################################## 720 720 # Facilities for running tests from the command line 721 721 ############################################################################## 722 722 723 723 # Note: Reuse unittest.TestProgram to launch test. In the future we may 724 724 # build our own launcher to support more specific command line 725 725 # parameters like test title, CSS, etc. 726 726 class TestProgram(unittest.TestProgram): 727 727 """ 728 728 A連線資訊 variation of the unittest.TestProgram. Please refer to the base 729 729 class for command line parameters. 730 730 """ 731 731 def runTests(self): 732 732 # Pick HTMLTestRunner as the default test common. 733 733 # base class's testRunner parameter is not useful because it means 734 734 # we have to instantiate HTMLTestRunner before we know self.verbosity. 735 735 if self.testRunner is None: 736 736 self.testRunner = HTMLTestRunner(verbosity=self.verbosity) 737 737 unittest.TestProgram.runTests(self) 738 738 739 739 main = TestProgram 740 740 741 741 ############################################################################## 742 742 # Executing this module from the command line 743 743 ############################################################################## 744 744 745 745 if __name__ == "__main__": 746 746 main(module=None) 747 748 HTMLTestRunnerHTMLTestRunner
五、logs->日誌檔案
執行後自動生成日誌檔案
六、middleware->中間層
1 import os 2 3 from pymysql.cursors import DictCursor 4 from commom.mysql_handler import MysqlHandler 5 from config import config 6 from commom import yaml_handler,excel_handler 7 from commom.logging_handler import get_logger 8 9 class MidMysqlHandler(MysqlHandler): 10 """初始化資料庫""" 11 def __init__(self): 12 db_config = MidInitHandler.yaml["db"] 13 super().__init__( 14 host=db_config["host"], 15 port=db_config["port"], 16 user=db_config["user"], 17 password=db_config["password"], 18 charset=db_config["charset"], 19 cursorclass=DictCursor) 20 21 class MidInitHandler: 22 """初始化所有的資料""" 23 # 載入python配置項 24 conf = config 25 # 讀取yaml資料 26 yaml = yaml_handler.read_yaml(os.path.join(config.CONFIG_PATH, "config.yaml")) 27 # Excel資料 28 __excel_path = conf.DATA_PATH 29 __excel_file = yaml["excel"]["file"] 30 excel = excel_handler.ExcelHandler(os.path.join(__excel_path, __excel_file)) 31 # logger 32 __logger_config = yaml['logger'] 33 logger = get_logger( 34 name=__logger_config['name'], 35 file=os.path.join(config.LOG_PATH, __logger_config['file']), 36 logger_level=__logger_config['logger_level'], 37 stream_level=__logger_config['stream_level'], 38 file_level=__logger_config['file_level'] 39 ) 40 # 儲存MidMysqlHandler類 41 db_class = MidMysqlHandler 42 43 def random_data(self): 44 """隨機生成4位數字""" 45 import random 46 random_data = '' 47 for i in range(4): 48 num = random.randint(1, 9) 49 random_data += str(num) 50 return random_dataMiddleHandler.py
pages:
1 import time 2 3 from selenium.webdriver.common.by import By 4 from commom.basepage import BasePage 5 from middleware.MiddleHandler import MidInitHandler 6 from middleware.pages.index import IndexPage 7 8 9 class LoginPage(BasePage): 10 """登入頁面""" 11 handler = MidInitHandler 12 title = "智慧校園管理平臺" 13 url = handler.yaml["host"] + "/login" 14 username_locator = (By.XPATH,'//*[@class="el-form el-form--label-left"]/div[1]/div/div/input') 15 password_locator = (By.XPATH,'//*[@class="el-form el-form--label-left"]/div[2]/div/div/input') 16 login_btn_locator = (By.CLASS_NAME,"el-image") 17 error_msg_locator = (By.CLASS_NAME,"el-message__content") 18 19 def get(self): 20 """訪問頁面""" 21 self.driver.get(self.url) 22 return self 23 24 def login_fail(self,username,password): 25 """登入失敗""" 26 self.clear(self.username_locator).send_keys(self.username_locator,username) 27 self.clear(self.password_locator).send_keys(self.password_locator,password) 28 time.sleep(1) 29 self.click(self.login_btn_locator) 30 return self 31 32 def login_success(self, username, password): 33 """登入成功""" 34 self.clear(self.username_locator).send_keys(self.username_locator,username) 35 self.clear(self.password_locator).send_keys(self.password_locator,password) 36 self.click(self.login_btn_locator) 37 return IndexPage(self.driver) 38 39 def get_error_message(self): 40 """獲取登入不成功錯誤資訊""" 41 elem = self.wait_element_visible(self.error_msg_locator) 42 return elem.textlogin.py
1 from selenium.webdriver.common.by import By 2 from selenium.webdriver.common.keys import Keys 3 from commom.basepage import BasePage 4 5 class OrgManagePage(BasePage): 6 """系統管理-機構管理""" 7 # 機構管理列表(定位列表最後一條資料) 8 add_btn_loc = (By.XPATH, '//*[@class="head-container"]/div[1]/button') 9 edit_btn_loc = (By.XPATH,'//*[@id="main-container"]/div[2]/div/div/div[2]/div[2]/div[1]/div[4]/div[2]/table/tbody/tr[last()]/td[4]/div/button[1]') 10 del_btn_loc = (By.XPATH,'//*[@id="main-container"]/div[2]/div/div/div[2]/div[2]/div[1]/div[4]/div[2]/table/tbody/tr[last()]/td[4]/div/button[2]') 11 org_name_loc = (By.XPATH,'//*[@id="main-container"]/div[2]/div/div/div[2]/div[2]/div[1]/div[3]/table/tbody/tr[last()]/td[2]') 12 org_total_data_loc = (By.XPATH, '//*[@class="el-pagination__total"]') # 共x條 13 org_name_title_loc = (By.XPATH, '//*[@class="has-gutter"]/tr[1]/th[2]') # 列表標題:機構名稱 14 jump_page_loc = (By.XPATH, '//*[@class="el-pagination__jump"]/div[1]/input') # 跳轉頁面 15 16 17 # 新增機構 18 add_title_loc =(By.XPATH, '//span[contains(text(),"新增機構")]') 19 add_name_loc = (By.XPATH, '//*[@class="el-form-item__content"]/div[1]/input') 20 add_class_loc = (By.XPATH, '//*[@class="el-form-item__content"]/div[1]/div[1]/input[@placeholder="請選擇"]') 21 add_classlist_loc = (By.XPATH, '//*[@class="el-scrollbar__view el-select-dropdown__list"]/li[1]') 22 add_uporg_input_loc= (By.XPATH,'//input[@placeholder="點選選擇內容"]') 23 add_toporg_loc = (By.XPATH, '//*[@class="el-tree-node__content"]/span[contains(text(),"頂級機構")]') 24 add_ok_loc = (By.XPATH, '//*[@class="el-popup-parent--hidden"]/div[2]/div/div[3]/div/button[2]') 25 add_cancel_loc = (By.XPATH, '//*[@class="el-popup-parent--hidden"]/div[2]/div/div[3]/div/button[1]') 26 add_name_error_loc = (By.XPATH,'//*[@class="el-form-item__error"]') 27 28 # 編輯機構 29 edit_title_loc = (By.XPATH, '//span[contains(text(),"編輯機構")]') 30 edit_name_loc = (By.XPATH, '//*[@class="el-form-item__content"]/div[1]/input') 31 edit_class_loc = (By.XPATH, '//*[@class="el-form-item__content"]/div[1]/div[1]/input[@placeholder="請選擇"]') 32 edit_classlist_loc = (By.XPATH, '//*[@class="el-scrollbar__view el-select-dropdown__list"]/li[1]') 33 edit_uporg_input_loc= (By.XPATH,'//input[@placeholder="點選選擇內容"]') 34 edit_toporg_loc = (By.XPATH, '//*[@class="el-tree-node__content"]/span[contains(text(),"頂級機構")]') 35 edit_ok_loc = (By.XPATH, '//*[@class="el-popup-parent--hidden"]/div[2]/div/div[3]/div/button[2]') 36 edit_cancel_loc = (By.XPATH, '//*[@class="el-popup-parent--hidden"]/div[2]/div/div[3]/div/button[1]') 37 edit_name_error_loc = (By.XPATH, '//*[@class="el-form-item__error"]') 38 39 # 刪除機構 40 del_text_loc = (By.XPATH, '//*[@class="el-message-box__message"]') 41 del_cancel_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[1]') 42 del_ok_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[2]') 43 44 # 機構搜尋 45 search_input_loc = (By.XPATH, '//*[@class="head-container"]/div[1]/input') 46 search_noresult_loc = (By.XPATH, '//span[contains(text(),"暫無資料")]') 47 48 49 def get_org_name_title(self): 50 """獲取列表標題:機構名稱 """ 51 return self.find_element(self.org_name_title_loc).text 52 53 def get_total_data(self): 54 """獲取列表共X條資料""" 55 elem = self.find_element(self.org_total_data_loc) 56 return elem.text[1:-1] 57 58 def get_last_orgname(self): 59 """獲取列表最後一條資料的機構名稱""" 60 elem = self.find_element(self.org_name_loc) 61 return elem.text 62 63 def get_name_error_msg(self): 64 """獲取機構名稱錯誤時提示資訊""" 65 elem = self.find_element(self.add_name_error_loc) 66 return elem.text 67 68 def add_org(self,org_name): 69 """新增頂級機構資料""" 70 self.click(self.add_btn_loc) 71 self.send_keys(self.add_name_loc,org_name) 72 self.click(self.add_class_loc) 73 self.click(self.add_classlist_loc) 74 self.click(self.add_uporg_input_loc) 75 self.click(self.add_toporg_loc) 76 self.click(self.add_ok_loc) 77 return self 78 79 def edit_org(self,org_name): 80 """編輯機構資料""" 81 self.click(self.edit_btn_loc) 82 self.clear(self.edit_name_loc).send_keys(self.edit_name_loc,org_name) 83 self.click(self.edit_class_loc) 84 self.click(self.edit_classlist_loc) 85 self.click(self.edit_uporg_input_loc) 86 self.click(self.edit_toporg_loc) 87 self.click(self.edit_ok_loc) 88 return self 89 90 def del_last_org(self): 91 """成功刪除機構資料""" 92 self.click(self.del_btn_loc) 93 self.click(self.del_ok_loc) 94 return self 95 96 def cancel_del_last_org(self): 97 """取消刪除機構資料""" 98 self.click(self.del_btn_loc) 99 self.click(self.del_cancel_loc) 100 return self 101 102 def jump_page(self,page_num): 103 """跳轉到指定頁面""" 104 self.clear(self.jump_page_loc) 105 self.send_keys(self.jump_page_loc,page_num) 106 self.driver.find_element(*self.jump_page_loc).send_keys(Keys.ENTER) 107 return self 108 109 def last_page(self): 110 """跳轉到列表最後一頁""" 111 del_before_num = self.get_total_data() 112 if int(del_before_num) % 10 == 0: 113 self.jump_page(int(del_before_num) % 10) 114 else: 115 self.jump_page(int(del_before_num) % 10 + 1) 116 return selforg_manage.py
1 import time 2 3 from selenium.webdriver.common.by import By 4 from selenium.webdriver.common.keys import Keys 5 from commom.basepage import BasePage 6 7 class RoleManagePage(BasePage): 8 """系統管理-角色管理""" 9 add_btn_loc = (By.XPATH,'//*[@class="head-container"]/div[2]/button[1]') 10 total_data_loc = (By.XPATH, '//*[@class="el-pagination__total"]') 11 edit_btn_loc = (By.XPATH,'//*[@id="main-container"]/div[2]/div/div[2]/div[1]/div/div[2]/div/div[1]/div[4]/div[2]/table/tbody/tr[last()]/td[4]/div/button[1]') 12 del_btn_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[1]/div/div[2]/div/div[1]/div[4]/div[2]/table/tbody/tr[last()]/td[4]/div/button[2]') 13 role_name_list_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[1]/div/div[2]/div/div[1]/div[3]/table/tbody/tr[last()]/td[2]') 14 role_name_title_loc = (By.XPATH, '//*[@class="has-gutter"]/tr[1]/th[2]') # 列表標題:角色名 15 jump_page_loc = (By.XPATH, '//*[@class="el-pagination__jump"]/div[1]/input') # 跳轉頁面 16 menu_btn_loc = (By.XPATH, '//*[@class="el-radio-group"]/label[1]/span') # 選單分配 17 menu_one_loc = (By.XPATH, '//*[@class="el-tree"]/div[1]/div[1]/label/span/span') # 第一個選單 18 menu_save_loc = (By.XPATH, '//*[@class="clearfix"]/button[1]') # 選單分配儲存 19 auth_btn_loc = (By.XPATH, '//*[@class="el-radio-group"]/label[2]/span') # 許可權分配 20 auth_one_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[2]/div[2]/div[2]/div/div[1]/div/label/span/span') 21 auth_save_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[2]/div[2]/div[1]/div/button') 22 save_msg_loc = (By.XPATH,'//*[@class="el-message__content"]') 23 24 25 # 新增/編輯角色頁面 26 add_title_loc = (By.XPATH, "//span[contains(text(),'新增角色')]") 27 edit_title_loc = (By.XPATH, "//span[contains(text(),'編輯角色')]") 28 role_name_loc = (By.XPATH, '//*[@class="el-form-item__content"]/div/input') 29 role_describe_loc = (By.XPATH, '//*[@class="el-textarea__inner"]') 30 role_ok_loc = (By.XPATH, '//*[@class="el-popup-parent--hidden"]/div[2]/div/div[3]/div/button[2]') 31 role_cancel_loc = (By.XPATH, "//*[@class='el-popup-parent--hidden']/div[2]/div/div[3]/div/button[1]") 32 tip_text_loc = (By.XPATH, '//*[@class="el-message-box__message"]') 33 tip_ok_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[2]') 34 tip_cancel_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[1]') 35 name_error_loc = (By.XPATH, '//*[@class="el-form-item__error"]') 36 37 # 刪除提示 38 del_text_loc = (By.XPATH, '//*[@class="el-message-box__message"]') 39 del_cancel_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[1]') 40 del_ok_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[2]') 41 42 # 搜尋許可權 43 search_input_loc = (By.XPATH, '//*[@class="head-container"]/div[1]/input') 44 search_btn_loc = (By.XPATH, '//*[@class="head-container"]/button') 45 search_null_loc = (By.XPATH, '//*[@class="el-table__empty-text"]') 46 47 def get_role_name_title(self): 48 """獲取列表標題:角色名 """ 49 return self.find_element(self.role_name_title_loc).text 50 51 def get_total_data(self): 52 """獲取列表共X條資料""" 53 elem = self.find_element(self.total_data_loc) 54 return elem.text[1:-1] 55 56 def get_last_rolename(self): 57 """獲取列表最後一條資料的角色名""" 58 elem = self.find_element(self.role_name_list_loc) 59 return elem.text 60 61 def get_name_error_msg(self): 62 """獲取角色名稱錯誤時提示資訊""" 63 elem = self.find_element(self.name_error_loc) 64 return elem.text 65 66 def get_save_sueess_msg(self): 67 elem = self.wait_element_visible(self.save_msg_loc) 68 return elem.text 69 70 def add_role(self, role_name,role_describe=None): 71 """新增角色""" 72 self.click(self.add_btn_loc) 73 self.send_keys(self.role_name_loc,role_name) 74 self.send_keys(self.role_describe_loc,role_describe) 75 self.click(self.role_ok_loc) 76 self.click(self.tip_ok_loc) 77 return self 78 79 def assgin_menu(self): 80 """選單分配""" 81 self.click(self.role_name_list_loc) 82 self.click(self.menu_btn_loc) 83 self.click(self.menu_one_loc) 84 self.click(self.menu_save_loc) 85 return self 86 87 def assgin_auth(self): 88 """選單許可權""" 89 self.click(self.role_name_list_loc) 90 self.click(self.auth_btn_loc) 91 self.click(self.auth_one_loc) 92 self.click(self.auth_save_loc) 93 return self 94 95 def add_role_fail(self, role_name,role_describe=None): 96 """新增角色失敗""" 97 self.click(self.add_btn_loc) 98 self.send_keys(self.role_name_loc,role_name) 99 self.send_keys(self.role_describe_loc,role_describe) 100 self.click(self.role_ok_loc) 101 return self 102 103 def edit_role(self,role_name,role_describe=None): 104 """編輯列表最後一條角色資料""" 105 self.click(self.edit_btn_loc) 106 self.clear(self.role_name_loc).send_keys(self.role_name_loc,role_name) 107 self.clear(self.role_describe_loc).send_keys(self.role_describe_loc,role_describe) 108 self.click(self.role_ok_loc) 109 self.click(self.tip_ok_loc) 110 return self 111 112 def search_role(self,role_name): 113 """搜尋角色""" 114 self.send_keys(self.search_input_loc,role_name) 115 self.click(self.search_btn_loc) 116 return self 117 118 def get_search_null_msg(self): 119 """搜尋結果暫無資料""" 120 elem = self.find_element(self.search_null_loc) 121 return elem.text 122 123 def get_search_result(self): 124 """搜尋結果有資料""" 125 elem = self.find_element(self.role_name_list_loc) 126 return elem.text 127 128 def del_last_role(self): 129 """刪除列表最後一條資料""" 130 self.click(self.del_btn_loc) 131 self.click(self.del_ok_loc) 132 return self 133 134 def cancel_del_last_role(self): 135 """取消刪除列表最後一條資料""" 136 self.click(self.del_btn_loc) 137 self.click(self.del_cancel_loc) 138 return self 139 140 def jump_page(self,page_num): 141 """跳轉到指定頁面""" 142 self.clear(self.jump_page_loc).send_keys(self.jump_page_loc,page_num) 143 self.driver.find_element(*self.jump_page_loc).send_keys(Keys.ENTER) 144 return self 145 146 def last_page(self): 147 """跳轉到列表最後一頁""" 148 page_num = self.get_total_data() 149 if int(page_num) % 10 == 0: 150 self.jump_page(int(page_num) % 10) 151 else: 152 self.jump_page(int(page_num) % 10 + 1) 153 time.sleep(2) 154 return selfrole_manage.py
1 import time 2 from selenium.webdriver.common.by import By 3 from commom.basepage import BasePage 4 5 class MenuManagePage(BasePage): 6 """系統管理-選單管理""" 7 add_btn_loc = (By.XPATH, '//*[@class="head-container"]/div[2]/button[1]') 8 edit_btn_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[4]/div[2]/table/tbody/tr[last()]/td[7]/div/div/button') 9 del_btn_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[4]/div[2]/table/tbody/tr[last()]/td[7]/div/button') 10 menu_url_title_loc = (By.XPATH, '//*[@class="has-gutter"]/tr/th[3]/div') 11 menu_url_list_loc= (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[4]/div[2]/table/tbody/tr[last()]/td[3]/div') 12 menu_name_list_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[4]/div[2]/table/tbody/tr[last()]/td[2]/div') 13 search_input_loc = (By.XPATH, '//*[@class="head-container"]/div[1]/input') 14 search_btn_loc = (By.XPATH, '//*[@class="head-container"]/button') 15 search_null_loc = (By.XPATH, '//*[@class="el-table__empty-text"]') 16 17 # 新增/編輯頁面 18 menu_type_catalog_loc = (By.XPATH, '//*[@class="el-form"]/div[1]/div/div/label[1]/span[1]/span') 19 menu_type_menu_loc = (By.XPATH, '//*[@class="el-form"]/div[1]/div/div/label[2]/span[1]/span') 20 menu_name_loc = (By.XPATH, '//*[@class="el-form"]/div[2]/div[1]/div[1]/input[1]') 21 superior_menu_loc = (By.XPATH,'//*[@class="vue-treeselect__control"]/div[1]/div[3]/input[1]') 22 top_org_loc = (By.XPATH,'//*[@class="el-input-number__increase"]') 23 sort_num_loc = (By.XPATH,'//*[@class="el-input-number__increase"]') 24 menu_url_loc = (By.XPATH,'//*[@class="el-form"]/div[4]/div/div/div[1]/div/input') 25 menu_icon_loc = (By.XPATH, '//*[@class="el-form"]/div[6]/div/div/div[1]/div/input') 26 catalog_menu_icon_loc = (By.XPATH, '//*[@class="el-form"]/div[5]/div/div/div[1]/div/input') 27 ok_btn_loc = (By.XPATH,'//*[@class="el-dialog__wrapper"]/div[1]/div[3]/span/button[2]') 28 cancel_btn_loc = (By.XPATH, '//*[@class="el-dialog__wrapper"]/div[1]/div[3]/span/button[1]') 29 name_error_loc = (By.XPATH, '//*[@class="el-form-item__error"]') 30 save_msg_loc = (By.XPATH, '//*[@class="el-message__content"]') 31 32 # 刪除提示 33 del_text_loc = (By.XPATH, '//*[@class="el-message-box__message"]') 34 del_cancel_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[1]') 35 del_ok_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[2]') 36 37 def get_menu_url_title(self): 38 """獲取列表標題:選單url""" 39 return self.find_element(self.menu_url_title_loc).text 40 41 def get_last_menu_url(self): 42 """獲取列表最後一條資料的選單url""" 43 elem = self.find_element(self.menu_url_list_loc) 44 return elem.text 45 46 def get_last_menu_name(self): 47 """獲取列表最後一條資料選單名稱""" 48 elem = self.find_element(self.menu_name_list_loc) 49 return elem.text 50 51 def get_name_error_msg(self): 52 """獲取選單名稱錯誤時提示資訊""" 53 elem = self.find_element(self.name_error_loc) 54 return elem.text 55 56 def get_save_sueess_msg(self): 57 elem = self.wait_element_visible(self.save_msg_loc) 58 return elem.text 59 60 def add_menu_menu(self,menu_name,menu_url=None,menu_icon=None): 61 """新增選單(選單型別為選單)""" 62 self.click(self.add_btn_loc) 63 self.click(self.menu_type_menu_loc) 64 self.send_keys(self.menu_name_loc,menu_name) 65 self.click(self.sort_num_loc) 66 self.send_keys(self.menu_url_loc,menu_url) 67 self.send_keys(self.menu_icon_loc, menu_icon) 68 self.click(self.ok_btn_loc) 69 return self 70 71 def add_menu_catalog(self,menu_name,menu_icon=None): 72 """新增選單(選單型別為目錄)""" 73 self.click(self.add_btn_loc) 74 self.click(self.menu_type_catalog_loc) 75 self.send_keys(self.menu_name_loc,menu_name) 76 self.click(self.sort_num_loc) 77 self.send_keys(self.catalog_menu_icon_loc, menu_icon) 78 self.click(self.ok_btn_loc) 79 return self 80 81 def edit_menu_menu(self,menu_name,menu_url=None,menu_icon=None): 82 """編輯選單(選單型別為選單)""" 83 self.click(self.edit_btn_loc) 84 self.click(self.menu_type_menu_loc) 85 self.clear(self.menu_name_loc).send_keys(self.menu_name_loc,menu_name) 86 self.click(self.sort_num_loc) 87 self.clear(self.menu_url_loc).send_keys(self.menu_url_loc,menu_url) 88 self.clear(self.menu_icon_loc).send_keys(self.menu_icon_loc, menu_icon) 89 self.click(self.ok_btn_loc) 90 return self 91 92 def edit_menu_catalog(self,menu_name,menu_icon=None): 93 """新增選單(選單型別為目錄)""" 94 self.click(self.add_btn_loc) 95 self.click(self.menu_type_catalog_loc) 96 self.clear(self.menu_name_loc).send_keys(self.menu_name_loc,menu_name) 97 self.click(self.sort_num_loc) 98 self.clear(self.catalog_menu_icon_loc).send_keys(self.catalog_menu_icon_loc, menu_icon) 99 self.click(self.ok_btn_loc) 100 return self 101 102 def search_menu(self,menu_name): 103 """搜尋系統中存在的選單名""" 104 self.send_keys(self.search_input_loc,menu_name) 105 self.click(self.search_btn_loc) 106 return self 107 108 def get_search_null_msg(self): 109 """搜尋結果暫無資料""" 110 elem = self.find_element(self.search_null_loc) 111 return elem.text 112 113 def get_search_result(self): 114 """搜尋結果有資料""" 115 elem = self.find_element(self.menu_name_list_loc) 116 return elem.text 117 118 def del_last_menu(self): 119 """成功刪除最後一條資料""" 120 self.click(self.del_btn_loc) 121 self.click(self.del_ok_loc) 122 return self 123 124 def cancel_del_last_menu(self): 125 """取消刪除列表最後一條資料""" 126 self.click(self.del_btn_loc) 127 self.click(self.del_cancel_loc) 128 return selfmenu_manage.py
1 import time 2 3 from selenium.webdriver.common.by import By 4 from selenium.webdriver.common.keys import Keys 5 6 from commom.basepage import BasePage 7 8 9 class DictManagePage(BasePage): 10 """系統管理-字典管理""" 11 # 字典列表 12 add_dict_btn = (By.XPATH, '//*[@class="el-row"]/div[1]/div[1]/div[1]/div[1]/button[1]') 13 edit_dict_btn = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div/div[1]/div/div[2]/div[2]/div[1]/div[4]/div[2]/table/tbody/tr[last()]/td[4]/div/button[1]') 14 del_dict_btn = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div/div[1]/div/div[2]/div[2]/div[1]/div[4]/div[2]/table/tbody/tr[last()]/td[4]/div/button[2]') 15 dict_list_title_loc = (By.XPATH, '//*[@class="el-row"]/div[1]/div/div[1]/div/span') 16 dict_name_list_loc =(By.XPATH,'//*[@id="main-container"]/div[2]/div/div/div[1]/div/div[2]/div[2]/div[1]/div[3]/table/tbody/tr[last()]/td[2]/div') 17 dict_describe_list_loc =(By.XPATH,'//*[@id="main-container"]/div[2]/div/div/div[1]/div/div[2]/div[2]/div[1]/div[3]/table/tbody/tr[last()]/td[3]/div') 18 search_dict_input_loc = (By.XPATH, '//*[@class="el-card__body"]/div[1]/div[1]/input') 19 search_dict_type_loc = (By.XPATH, '//*[@class="el-card__body"]/div[1]/div[2]/div/input') 20 dict_type_name_loc = (By.XPATH, '//*[@class="el-scrollbar"]/div[1]/ul/li[1]') 21 dict_type_describe_loc = (By.XPATH, '//*[@class="el-scrollbar"]/div[1]/ul/li[2]') 22 search_dict_btn_loc = (By.XPATH, '//*[@class="el-card__body"]/div[1]/button') 23 dict_total_loc = (By.XPATH, '//*[@class="el-row"]/div[1]/div/div[2]/div[2]/div[2]/div/span[1]') 24 dict_jump_loc = (By.XPATH, '//*[@class="el-row"]/div[1]/div/div[2]/div[2]/div[2]/div/span[2]/div/input') 25 dict_search_null_msg = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div/div[2]/div/div[2]/div/div/div[2]/div[1]/div[4]/div[2]') 26 27 # 字典詳情 28 add_details_btn = (By.XPATH, '//*[@class="el-row"]/div[2]/div/div[1]/div/button') 29 edit_details_btn = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div/div[2]/div/div[2]/div/div/div[2]/div[1]/div[4]/div[2]/table/tbody/tr[last()]/td[4]/div/button[1]') 30 del_details_btn = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div/div[2]/div/div[2]/div/div/div[2]/div[1]/div[4]/div[2]/table/tbody/tr[last()]/td[4]/div/button[2]') 31 details_list_title_loc = (By.XPATH, '//*[@class="el-row"]/div[2]/div/div[1]/div/span') 32 details_label_list_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div/div[2]/div/div[2]/div/div/div[2]/div[1]/div[3]/table/tbody/tr[last()]/td[2]/div') 33 search_details_input_loc = (By.XPATH, '//*[@class="el-card__body"]/div[1]/div[1]/div[1]/div[1]/input') 34 search_details_btn_loc = (By.XPATH, '//*[@class="el-card__body"]/div[1]/div[1]/div[1]/button') 35 details_total_loc = (By.XPATH, '//*[@class="el-row"]/div[2]/div/div[2]/div/div/div[2]/div[2]/div/span[1]') 36 details_jump_loc = (By.XPATH, '//*[@class="el-row"]/div[2]/div/div[2]/div/div/div[2]/div[2]/div/span[2]/div/input') 37 details_search_null_msg = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div/div[2]/div/div[2]/div/div/div[2]/div[1]/div[3]/div/span') 38 39 40 # 新增/編輯字典 41 dict_name_loc = (By.XPATH,'//label[contains(text(),"字典名稱")]//following-sibling::div//child::input') 42 dict_describe_loc = (By.XPATH, '//label[contains(text(),"描述")]//following-sibling::div//child::input') 43 dict_ok_btn = (By.XPATH,'//*[@class="el-dialog"]/div[3]/div[1]/button[2]') 44 dict_cancel_btn = (By.XPATH, '//*[@class="el-dialog"]/div[3]/div[1]/button[1]') 45 name_error_loc = (By.XPATH, '//*[@class="el-form-item__error"]') 46 tip_msg_loc = (By.XPATH, '//*[@class="el-message__content"]') 47 # 新增/編輯字典詳情 48 dict_label_loc = (By.XPATH, '//label[contains(text(),"字典標籤")]//following-sibling::div//child::input') 49 dict_value_loc = (By.XPATH, '//label[contains(text(),"字典值")]//following-sibling::div//child::input') 50 details_ok_btn = (By.XPATH, '//*[@class="el-dialog"]/div[3]/div[1]/button[2]') 51 details_cancel_btn = (By.XPATH, '//*[@class="el-dialog"]/div[3]/div[1]/button[1]') 52 53 # 刪除提示 54 del_text_loc = (By.XPATH, '//*[@class="el-message-box__message"]') 55 del_cancel_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[1]') 56 del_ok_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[2]') 57 58 def get_last_dict_name(self): 59 """獲取字典列表最後一條資料的字典名稱""" 60 elem = self.find_element(self.dict_name_list_loc) 61 return elem.text 62 63 def open_dict_details(self): 64 """點選字典列表最後一頁最後一條資料""" 65 self.click(self.dict_name_list_loc) 66 return self 67 68 def get_dict_details_title(self): 69 """獲取字典詳情標題:字典詳情""" 70 elem = self.find_element(self.details_list_title_loc) 71 return elem.text 72 73 def get_last_dict_describe(self): 74 """獲取字典列表最後一條資料的字典描述""" 75 elem = self.find_element(self.dict_describe_list_loc) 76 return elem.text 77 78 def get_last_dict_label(self): 79 """獲取字典詳情最後一條資料字典標籤""" 80 elem = self.find_element(self.details_label_list_loc) 81 return elem.text 82 83 def get_name_error_msg(self): 84 """獲取字典名稱/標籤錯誤時提示資訊""" 85 elem = self.find_element(self.name_error_loc) 86 return elem.text 87 88 def get_tip_msg(self): 89 """獲取頁面的提示資訊""" 90 elem = self.wait_element_visible(self.tip_msg_loc) 91 return elem.text 92 93 def get_dict_list_title(self): 94 """獲取字典列表標題:字典列表 """ 95 return self.find_element(self.dict_list_title_loc).text 96 97 def get_dict_total_data(self): 98 """獲取字典列表共X條資料""" 99 time.sleep(2) 100 elem = self.find_element(self.dict_total_loc) 101 return elem.text[1:-1] 102 103 def get_details_total_data(self): 104 """獲取字典詳情共X條資料""" 105 elem = self.find_element(self.details_total_loc) 106 return elem.text[1:-1] 107 108 def add_dict(self,dict_name,describe=None): 109 """新增字典列表""" 110 self.click(self.add_dict_btn) 111 self.send_keys(self.dict_name_loc,dict_name) 112 self.send_keys(self.dict_describe_loc,describe) 113 self.click(self.dict_ok_btn) 114 return self 115 116 def edit_dict(self,dict_name,describe=None): 117 """編輯字典列表最後一條資料""" 118 self.click(self.edit_dict_btn) 119 self.clear(self.dict_name_loc).send_keys(self.dict_name_loc,dict_name) 120 self.clear(self.dict_describe_loc).send_keys(self.dict_describe_loc,describe) 121 self.click(self.dict_ok_btn) 122 return self 123 124 def search_dict_name(self,dict_name): 125 """按字典名稱搜尋""" 126 self.send_keys(self.search_dict_input_loc,dict_name) 127 self.click(self.search_dict_type_loc).click(self.dict_type_name_loc) 128 self.click(self.search_dict_btn_loc) 129 return self 130 131 def search_dict_describe(self,describe): 132 """按字典描述搜尋""" 133 self.send_keys(self.search_dict_input_loc,describe) 134 self.click(self.search_dict_type_loc).click(self.dict_type_describe_loc) 135 self.click(self.search_dict_btn_loc) 136 return self 137 138 def get_search_null_msg(self): 139 """搜尋字典列表結果暫無資料""" 140 elem = self.find_element(self.dict_search_null_msg) 141 return elem.text 142 143 def get_search_result(self): 144 """搜尋字典列表結果有資料""" 145 elem = self.find_element(self.dict_name_list_loc) 146 return elem.text 147 148 def cacel_del_last_dict(self): 149 """取消刪除字典列表最後一條資料""" 150 self.click(self.del_dict_btn) 151 self.click(self.del_cancel_loc) 152 return self 153 154 def del_last_dict(self): 155 """成功刪除字典列表最後一條資料""" 156 self.click(self.del_dict_btn) 157 self.click(self.del_ok_loc) 158 return self 159 160 def dict_jump_page(self,page_num): 161 """字典列表跳轉到指定頁面""" 162 self.clear(self.dict_jump_loc).send_keys(self.dict_jump_loc,page_num) 163 self.driver.find_element(*self.dict_jump_loc).send_keys(Keys.ENTER) 164 return self 165 166 def dict_last_page(self): 167 """字典列表跳轉到列表最後一頁""" 168 page_num = self.get_dict_total_data() 169 if int(page_num) % 10 == 0: 170 self.dict_jump_page(int(page_num) % 10) 171 else: 172 self.dict_jump_page(int(page_num) % 10 + 1) 173 time.sleep(2) 174 return self 175 176 # 字典詳情 177 178 179 def add_dict_details(self, dict_label, value=None): 180 """新增字典詳情""" 181 self.click(self.add_details_btn) 182 self.send_keys(self.dict_label_loc, dict_label) 183 self.send_keys(self.dict_value_loc, value) 184 self.click(self.details_ok_btn) 185 return self 186 187 def edit_dict_details(self,dict_label, value=None): 188 """編輯字典詳情最後一條資料""" 189 self.click(self.edit_details_btn) 190 self.clear(self.dict_label_loc).send_keys(self.dict_label_loc, dict_label) 191 self.clear(self.dict_value_loc).send_keys(self.dict_value_loc, value) 192 self.click(self.details_ok_btn) 193 return self 194 195 def search_dict_label(self, dict_label): 196 """按字典標籤搜尋""" 197 self.send_keys(self.search_details_input_loc, dict_label) 198 self.click(self.search_details_btn_loc) 199 return self 200 201 def search_details_null_msg(self): 202 """搜尋字典標籤結果暫無資料""" 203 elem = self.find_element(self.details_search_null_msg) 204 return elem.text 205 206 def search_details_result(self): 207 """搜尋字典標籤結果有資料""" 208 elem = self.find_element(self.details_label_list_loc) 209 return elem.text 210 211 def cacel_del_last_details(self): 212 """取消刪除字典詳情最後一條資料""" 213 self.click(self.del_details_btn) 214 self.click(self.del_cancel_loc) 215 return self 216 217 def del_last_details(self): 218 """成功刪除字典詳情最後一條資料""" 219 self.click(self.del_details_btn) 220 self.click(self.del_ok_loc) 221 return self 222 223 def details_jump_page(self, page_num): 224 """字典詳情跳轉到指定頁面""" 225 self.clear(self.details_jump_loc).send_keys(self.details_jump_loc, page_num) 226 self.driver.find_element(*self.details_jump_loc).send_keys(Keys.ENTER) 227 return self 228 229 def details_last_page(self): 230 """字典列表跳轉到列表最後一頁""" 231 page_num = self.get_details_total_data() 232 if int(page_num) % 10 == 0: 233 self.details_jump_page(int(page_num) % 10) 234 else: 235 self.details_jump_page(int(page_num) % 10 + 1) 236 time.sleep(2) 237 return selfdict_manage.py
1 import time 2 from selenium.webdriver.common.by import By 3 from commom.basepage import BasePage 4 5 class AuthManagePage(BasePage): 6 """系統管理-許可權管理""" 7 add_btn_loc = (By.XPATH, '//*[@class="head-container"]/div[2]/button[1]') 8 edit_btn_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[4]/div[2]/table/tbody/tr[last()]/td[6]/div/div') 9 del_btn_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[4]/div[2]/table/tbody/tr[last()]/td[6]/div/button') 10 auth_mark_title_loc = (By.XPATH, '//*[@class="has-gutter"]/tr/th[3]/div') 11 auth_mark_list_loc= (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[4]/div[2]/table/tbody/tr[last()]/td[3]/div') 12 auth_name_list_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[2]/div[4]/div[2]/table/tbody/tr[last()]/td[2]/div') 13 search_input_loc = (By.XPATH, '//*[@class="head-container"]/div[1]/input') 14 search_btn_loc = (By.XPATH, '//*[@class="head-container"]/button') 15 search_null_loc = (By.XPATH, '//*[@class="el-table__empty-text"]') 16 17 # 新增/編輯頁面 18 auth_name_loc = (By.XPATH, '//*[@class="el-form"]/div[2]/div[1]/div[1]/input[1]') 19 superior_menu_loc = (By.XPATH,'//*[@class="vue-treeselect__control"]/div[1]/div[3]/input[1]') 20 top_org_loc = (By.XPATH,'//*[@class="el-input-number__increase"]') 21 sort_num_loc = (By.XPATH,'//*[@class="el-input-number__increase"]') 22 auth_mark_loc = (By.XPATH,'//*[@class="el-form"]/div[5]/div[1]/div[1]/input[1]') 23 ok_btn_loc = (By.XPATH,'//*[@class="el-dialog__wrapper"]/div[1]/div[3]/span/button[2]') 24 cancel_btn_loc = (By.XPATH, '//*[@class="el-dialog__wrapper"]/div[1]/div[3]/span/button[1]') 25 name_error_loc = (By.XPATH, '//*[@class="el-form-item__error"]') 26 save_msg_loc = (By.XPATH, '//*[@class="el-message__content"]') 27 28 # 刪除提示 29 del_text_loc = (By.XPATH, '//*[@class="el-message-box__message"]') 30 del_cancel_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[1]') 31 del_ok_loc = (By.XPATH, '//*[@class="el-message-box__btns"]/button[2]') 32 33 def get_auth_mark_title(self): 34 """獲取列表標題:授權標識 """ 35 return self.find_element(self.auth_mark_title_loc).text 36 37 def get_last_auth_mark(self): 38 """獲取列表最後一條資料的授權標識""" 39 elem = self.find_element(self.auth_mark_list_loc) 40 return elem.text 41 42 def get_name_error_msg(self): 43 """獲取許可權名稱錯誤時提示資訊""" 44 elem = self.find_element(self.name_error_loc) 45 return elem.text 46 47 def get_save_sueess_msg(self): 48 elem = self.wait_element_visible(self.save_msg_loc) 49 return elem.text 50 51 def add_auth(self,auth_name,auth_mark=None): 52 """新增許可權""" 53 self.click(self.add_btn_loc) 54 self.send_keys(self.auth_name_loc,auth_name) 55 self.click(self.sort_num_loc) 56 self.send_keys(self.auth_mark_loc,auth_mark) 57 self.click(self.ok_btn_loc) 58 return self 59 60 def edit_auth(self,auth_name,auth_mark=None): 61 """編輯最後一條資料許可權""" 62 self.click(self.edit_btn_loc) 63 self.send_keys(self.auth_name_loc,auth_name) 64 self.click(self.sort_num_loc) 65 self.send_keys(self.auth_mark_loc,auth_mark) 66 self.click(self.ok_btn_loc) 67 return self 68 69 def search_auth(self,auth_name): 70 """搜尋系統中存在的許可權名""" 71 self.send_keys(self.search_input_loc,auth_name) 72 self.click(self.search_btn_loc) 73 return self 74 75 def get_search_null_msg(self): 76 """搜尋結果暫無資料""" 77 elem = self.find_element(self.search_null_loc) 78 return elem.text 79 80 def get_search_result(self): 81 """搜尋結果有資料""" 82 elem = self.find_element(self.auth_name_list_loc) 83 return elem.text 84 85 def del_auth(self): 86 """成功刪除最後一條資料""" 87 self.click(self.del_btn_loc) 88 self.click(self.del_ok_loc) 89 return self 90 91 def cancel_del_last_auth(self): 92 """取消刪除列表最後一條資料""" 93 self.click(self.del_btn_loc) 94 self.click(self.del_cancel_loc) 95 return selfauth_manage.py
1 from selenium.webdriver.common.by import By 2 from commom.basepage import BasePage 3 from middleware.pages.auth_manage import AuthManagePage 4 from middleware.pages.dict_manage import DictManagePage 5 from middleware.pages.menu_manage import MenuManagePage 6 from middleware.pages.org_manage import OrgManagePage 7 from middleware.pages.role_manage import RoleManagePage 8 from middleware.pages.send_mail import SendEmailPage 9 10 11 class IndexPage(BasePage): 12 """登入後首頁""" 13 title = "智慧校園管理平臺" 14 account_locator = (By.XPATH,"//span[contains(text(),'歡迎您')]") 15 sys_manage_loc = (By.XPATH, '//span[contains(text(),"系統管理")]') 16 org_manage_loc = (By.XPATH, '//*[@class="menu-bar-container"]/ul/li[2]/ul/li[2]') 17 role_manage_loc = (By.XPATH, '//*[@class="menu-bar-container"]/ul/li[2]/ul/li[3]') 18 auth_manage_loc = (By.XPATH, '//*[@class="menu-bar-container"]/ul/li[2]/ul/li[4]') 19 menu_manage_loc = (By.XPATH, '//*[@class="menu-bar-container"]/ul/li[2]/ul/li[5]') 20 dict_manage_loc = (By.XPATH, '//*[@class="menu-bar-container"]/ul/li[2]/ul/li[6]') 21 office_oa_loc = (By.XPATH, '//span[contains(text(),"辦公OA")]') 22 work_email_loc = (By.XPATH, '//span[contains(text(),"工作郵箱")]') 23 send_email_loc = (By.XPATH, '//*[@class="container"]/div[2]/ul/li[1]/ul/li[1]/ul/li[2]/span') 24 25 def get_account_name(self): 26 """獲取使用者名稱""" 27 return self.find_element(self.account_locator).text 28 29 def open_org_page(self): 30 """開啟機構管理頁面""" 31 self.click(self.sys_manage_loc) 32 self.click(self.org_manage_loc) 33 return OrgManagePage(self.driver) 34 35 def open_role_page(self): 36 """開啟角色管理頁面""" 37 self.click(self.sys_manage_loc) 38 self.click(self.role_manage_loc) 39 return RoleManagePage(self.driver) 40 41 def open_auth_page(self): 42 """開啟許可權管理頁面""" 43 self.click(self.sys_manage_loc) 44 self.click(self.auth_manage_loc) 45 return AuthManagePage(self.driver) 46 47 def open_menu_page(self): 48 """開啟選單管理頁面""" 49 self.click(self.sys_manage_loc) 50 self.click(self.menu_manage_loc) 51 return MenuManagePage(self.driver) 52 53 def open_dict_page(self): 54 """開啟字典管理頁面""" 55 self.click(self.sys_manage_loc) 56 self.click(self.dict_manage_loc) 57 return DictManagePage(self.driver) 58 59 def open_send_email(self): 60 """打開發送郵件頁面""" 61 self.click(self.office_oa_loc) 62 self.click(self.work_email_loc) 63 self.click(self.send_email_loc) 64 return SendEmailPage(self.driver)index.py
1 import time 2 3 from selenium.webdriver.common.by import By 4 from selenium.webdriver.common.keys import Keys 5 6 from commom.basepage import BasePage 7 8 9 class SendEmailPage(BasePage): 10 """辦公OA-傳送郵件""" 11 add_btn_loc = (By.XPATH,'//*[@class="main-content"]/div/div[1]/button[2]') 12 title_list_loc = (By.XPATH,'//*[@class="main-content"]/div/div[2]/div[1]/div[4]/div[2]/table/tbody/tr[last()]/td[1]') 13 search_btn_loc = (By.XPATH,'//*[@class="main-content"]/div/div[1]/button[1]') 14 total_data_loc = (By.XPATH, '//*[@class="el-pagination__total"]') 15 jump_page_loc = (By.XPATH, '//*[@class="el-pagination__jump"]/div[1]/input') # 跳轉頁面 16 tab_loc = (By.XPATH, '//*[@id="tab-釋出郵件"]') 17 tip_msg_loc = (By.XPATH, '//*[@class="el-message__content"]') 18 search_null_loc = (By.XPATH, '//*[@class="el-table__empty-text"]') 19 20 # 新增頁面 21 test_school_loc = (By.XPATH, '//*[@class="address-book-tree"]/div[1]/div[3]/div[1]/span[1]') 22 name_one_loc = (By.XPATH, '//*[@class="address-book-tree"]/div[1]/div[3]/div[2]/div[1]/div[1]/label/span') 23 search_name_loc = (By.XPATH, '//*[@class="index"]/div[2]/div[1]/input') 24 name_sure_loc = (By.XPATH, '//*[@class="address-book-tree"]/div[1]/div[3]/div[2]/div[1]/div[1]/label/span/span') 25 save_btn_loc = (By.XPATH, '//*[@class="header"]/div[1]/button') 26 send_input_loc = (By.XPATH, '//*[@class="main-container"]/div[1]/div[2]/div[2]/div[1]/div[2]/input') 27 cc_input_loc = (By.XPATH, '//*[@class="main-container"]/div[1]/div[3]/div[2]/div[1]/div[2]/input') 28 theme_input_loc = (By.XPATH, '//*[@class="main-container"]/div[1]/div[4]/div[2]/div[1]/input') 29 level_btn_loc = (By.XPATH, '//*[@class="main-container"]/div[1]/div[5]/div[2]/div[1]/label[last()]') 30 attach_btn_loc = (By.XPATH, '//*[@class="upload-demo"]/div[1]/button/span') 31 iframe_loc = (By.XPATH, '//*[@class="tinymce-container"]/div[1]/div[1]/div[2]/iframe') 32 rich_text_loc = (By.XPATH, '//*[@id="tinymce"]') # 需進入iframe 33 send_btn_loc = (By.XPATH, '//*[@class="main-container"]/div[1]/div[1]/button') 34 # 檢視郵件 35 title_dialog_loc = (By.XPATH, '//*[@id="main-container"]/div[2]/div/div[3]/div[1]/div[1]/span') 36 37 38 def get_tab(self): 39 """獲取釋出郵件的tab""" 40 elem = self.find_element(self.tab_loc) 41 return elem.text 42 43 def get_total_data(self): 44 """獲取列表共X條資料""" 45 elem = self.find_element(self.total_data_loc) 46 return elem.text[1:-1] 47 48 def get_tip_msg(self): 49 """獲取頁面的提示資訊""" 50 elem = self.wait_element_visible(self.tip_msg_loc) 51 return elem.text 52 53 def get_title_dialog(self): 54 elem = self.find_element(self.title_dialog_loc) 55 return elem.text 56 57 def get_last_list(self): 58 """獲取列表第一條資料標題""" 59 elem = self.wait_element_visible(self.title_list_loc) 60 return elem.text 61 62 def jump_page(self,page_num): 63 """跳轉到指定頁面""" 64 self.clear(self.jump_page_loc).send_keys(self.jump_page_loc,page_num) 65 self.driver.find_element(*self.jump_page_loc).send_keys(Keys.ENTER) 66 return self 67 68 def last_page(self): 69 """跳轉到列表最後一頁""" 70 page_num = self.get_total_data() 71 if int(page_num) % 10 == 0: 72 self.jump_page(int(page_num) % 10) 73 else: 74 self.jump_page(int(page_num) % 10 + 1) 75 time.sleep(2) 76 return self 77 78 def send_email(self,theme,content): 79 """傳送郵件""" 80 self.click(self.add_btn_loc) 81 self.click(self.test_school_loc) 82 self.click(self.name_one_loc) 83 self.click(self.save_btn_loc) 84 self.click(self.cc_input_loc) 85 # self.click(self.test_school_loc) 86 self.click(self.name_one_loc) 87 self.click(self.save_btn_loc) 88 self.send_keys(self.theme_input_loc,theme) 89 self.click(self.level_btn_loc) 90 # self.click(self.attach_btn_loc) 91 # self.upload_file("E:\\test.txt") 92 self.switch_iframe(self.iframe_loc) 93 self.send_keys(self.rich_text_loc,content) 94 self.quit_iframe() 95 self.click(self.send_btn_loc) 96 return self 97 98 def search_email_theme(self,theme): 99 """按標題查詢郵件""" 100 self.send_keys(self.search_name_loc,theme) 101 self.click(self.search_btn_loc) 102 return self 103 104 def get_serach_resule(self): 105 """返回查詢結果的列表最後一條資料標題""" 106 elem = self.find_element(self.title_list_loc) 107 return elem.text 108 109 def get_serach_null(self): 110 """返回查詢結果的暫無資料""" 111 elem = self.find_element(self.search_null_loc) 112 return elem.text 113 114 def click_last_list(self): 115 """點選列表最後一條資料標題""" 116 return self.click(self.title_list_loc)send_mail.py
七、allureout->測試報告
執行後自動生成測試報告
八、tests->測試用例
1 import pytest 2 from data.login_data import login_success,login_error 3 from middleware.pages.login import LoginPage 4 from middleware.MiddleHandler import MidInitHandler 5 6 7 class TestLogin: 8 """登入""" 9 handler = MidInitHandler() 10 11 @pytest.mark.parametrize("test_info", login_error) 12 def test_login_fail(self,test_info,driver): 13 """登入失敗""" 14 login_page = LoginPage(driver) 15 actual = login_page.get().login_fail( 16 username=test_info["username"], 17 password=test_info["password"], 18 ).get_error_message() 19 try: 20 assert test_info["expected"] in actual 21 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 22 except Exception as e: 23 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 24 raise e 25 26 @pytest.mark.parametrize("test_info", login_success) 27 def test_login_success(self,test_info,driver): 28 """登入成功""" 29 login_page = LoginPage(driver) 30 actual = login_page.get().login_success( 31 username=test_info["username"], 32 password=test_info["password"], 33 ).get_account_name() 34 35 try: 36 assert test_info["expected"] in actual 37 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 38 except Exception as e: 39 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 40 raise etest_login.py
1 import time 2 import pytest 3 from data.org_manage_data import add_data_normal,edit_data_normal,add_data_abnormal,open_org_page 4 from middleware.MiddleHandler import MidInitHandler 5 from middleware.pages.index import IndexPage 6 from middleware.pages.org_manage import OrgManagePage 7 8 class TestOrgManage: 9 """機構管理""" 10 handler = MidInitHandler() 11 12 13 @pytest.mark.parametrize("test_info", open_org_page) 14 def test_view_org(self,test_info,login): 15 """開啟機構管理頁面""" 16 driver = login 17 actual = IndexPage(driver).open_org_page().get_org_name_title() 18 try: 19 assert test_info["expected"] in actual 20 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 21 except Exception as e: 22 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 23 raise e 24 25 @pytest.mark.parametrize("test_info", add_data_normal) 26 def test_add_org_normal(self,test_info,login): 27 """正常新增機構""" 28 org_name = test_info["org_name"]+self.handler.random_data() 29 driver = login 30 add_before = IndexPage(driver).open_org_page().get_total_data() 31 add_org = IndexPage(driver).open_org_page().add_org(org_name) 32 time.sleep(2) 33 add_after =add_org.get_total_data() 34 try: 35 assert int(add_before) + 1 == int(add_after) 36 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 37 except Exception as e: 38 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 39 raise e 40 41 @pytest.mark.parametrize("test_info", add_data_abnormal) 42 def test_add_org_abnormal(self,test_info,login): 43 """新增機構異常""" 44 org_name = test_info["org_name"] 45 driver = login 46 actual = IndexPage(driver).open_org_page().add_org(org_name).get_name_error_msg() 47 try: 48 assert test_info["expected"] == actual 49 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 50 except Exception as e: 51 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 52 raise e 53 54 @pytest.mark.parametrize("test_info", edit_data_normal) 55 def test_edit_org_normal(self,test_info,login): 56 """正常編輯列表最後一頁的最後一條機構資料""" 57 org_name = test_info["org_name"]+self.handler.random_data() 58 driver = login 59 last_page = IndexPage(driver).open_org_page().last_page() 60 time.sleep(1) 61 edit_org = last_page.edit_org(org_name) 62 time.sleep(2) 63 org_name_after = edit_org.get_last_orgname() 64 try: 65 assert org_name == org_name_after 66 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 67 except Exception as e: 68 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 69 raise e 70 71 def test_cancel_del_org(self,login): 72 """取消刪除列表最後一條機構資料""" 73 driver = login 74 cancel_del_before = IndexPage(driver).open_org_page().get_total_data() 75 cancel_del = IndexPage(driver).open_org_page().last_page().cancel_del_last_org() 76 time.sleep(2) 77 cancel_del_after = cancel_del.get_total_data() 78 try: 79 assert cancel_del_before == cancel_del_after 80 self.handler.logger.info("測試用例通過:取消刪除") 81 except Exception as e: 82 self.handler.logger.error("測試用例不通過:取消刪除") 83 raise e 84 85 def test_del_org(self,login): 86 """刪除列表最後一頁的第一條機構資料""" 87 driver = login 88 del_before_num = IndexPage(driver).open_org_page().get_total_data() 89 del_org = IndexPage(driver).open_org_page().last_page().del_last_org() 90 time.sleep(2) 91 del_after_num = del_org.get_total_data() 92 try: 93 assert int(del_before_num)-1 == int(del_after_num) 94 self.handler.logger.info("測試用例通過:刪除列表最後一頁的第一條機構資料") 95 except Exception as e: 96 self.handler.logger.error("測試用例不通過:刪除列表最後一頁的第一條機構資料") 97 raise etest_org_manage.py
1 import time 2 import pytest 3 from data.role_manage_data import open_role_page,add_role_normal,add_role_abnormal,edit_role_normal,assign_menu,assign_auth,search_normal,search_abnormal 4 from middleware.MiddleHandler import MidInitHandler 5 from middleware.pages.index import IndexPage 6 7 8 class TestRoleManage: 9 """角色管理""" 10 handler = MidInitHandler() 11 12 @pytest.mark.parametrize("test_info", open_role_page) 13 def test_view_role(self,test_info,login): 14 """開啟角色管理頁面""" 15 driver = login 16 actual = IndexPage(driver).open_role_page().get_role_name_title() 17 try: 18 assert test_info["expected"] in actual 19 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 20 except Exception as e: 21 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 22 raise e 23 24 @pytest.mark.parametrize("test_info",add_role_normal) 25 def test_add_role_normal(self,test_info,login): 26 """正常新增角色""" 27 role_name = test_info["role_name"] + self.handler.random_data() 28 role_describe = '新增角色描述' 29 driver = login 30 add_before = IndexPage(driver).open_role_page().get_total_data() 31 add_role = IndexPage(driver).open_role_page().add_role(role_name,role_describe) 32 time.sleep(2) 33 add_after = add_role.get_total_data() 34 try: 35 assert int(add_before) + 1 == int(add_after) 36 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 37 except Exception as e: 38 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 39 raise e 40 41 @pytest.mark.parametrize("test_info", assign_menu) 42 def test_assign_menu(self,test_info,login): 43 """為最後一條角色分配第一個選單""" 44 driver = login 45 actual = IndexPage(driver).open_role_page().last_page().assgin_menu().get_save_sueess_msg() 46 try: 47 assert test_info["expected"] in actual 48 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 49 except Exception as e: 50 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 51 raise e 52 53 @pytest.mark.parametrize("test_info", assign_auth) 54 def test_assign_auth(self,test_info,login): 55 """為最後一條角色分配第一個許可權""" 56 driver = login 57 actual = IndexPage(driver).open_role_page().last_page().assgin_auth().get_save_sueess_msg() 58 try: 59 assert test_info["expected"] in actual 60 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 61 except Exception as e: 62 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 63 raise e 64 65 @pytest.mark.parametrize("test_info", add_role_abnormal) 66 def test_add_role_abnormal(self,test_info,login): 67 """新增角色異常""" 68 role_name = test_info["role_name"] 69 role_describe = '新增角色描述' 70 driver = login 71 actual = IndexPage(driver).open_role_page().add_role_fail(role_name,role_describe).get_name_error_msg() 72 try: 73 assert test_info["expected"] == actual 74 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 75 except Exception as e: 76 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 77 raise e 78 79 @pytest.mark.parametrize("test_info", edit_role_normal) 80 def test_edit_role_normal(self, test_info, login): 81 """正常編輯列表最後一頁的最後一條角色資料""" 82 role_name = test_info["role_name"] + self.handler.random_data() 83 role_describe = '編輯角色描述' 84 driver = login 85 last_page = IndexPage(driver).open_role_page().last_page() 86 time.sleep(1) 87 edit_role = last_page.edit_role(role_name,role_describe) 88 time.sleep(2) 89 role_name_after = edit_role.get_last_rolename() 90 try: 91 assert role_name == role_name_after 92 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 93 except Exception as e: 94 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 95 raise e 96 97 @pytest.mark.parametrize("test_info", search_normal) 98 def test_search_normal(self,test_info,login): 99 """搜尋系統中存在的角色名""" 100 driver = login 101 actual = IndexPage(driver).open_role_page().search_role(test_info["role_name"]).get_search_result() 102 try: 103 assert test_info["role_name"] == actual 104 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 105 except Exception as e: 106 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 107 raise e 108 109 @pytest.mark.parametrize("test_info", search_abnormal) 110 def test_search_abnormal(self,test_info,login): 111 """搜尋系統中不存在的角色名""" 112 driver = login 113 actual = IndexPage(driver).open_role_page().search_role(test_info["role_name"]).get_search_null_msg() 114 try: 115 assert test_info["expected"] == actual 116 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 117 except Exception as e: 118 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 119 raise e 120 121 122 def test_cancel_del_role(self,login): 123 """取消刪除列表最後一條角色資料""" 124 driver = login 125 cancel_del_before = IndexPage(driver).open_role_page().get_total_data() 126 cancel_del = IndexPage(driver).open_role_page().last_page().cancel_del_last_role() 127 time.sleep(2) 128 cancel_del_after = cancel_del.get_total_data() 129 try: 130 assert cancel_del_before == cancel_del_after 131 self.handler.logger.info("測試用例通過:取消刪除") 132 except Exception as e: 133 self.handler.logger.error("測試用例不通過:取消刪除") 134 raise e 135 136 def test_del_role(self,login): 137 """刪除列表最後一頁的第一條角色資料""" 138 driver = login 139 del_before_num = IndexPage(driver).open_role_page().get_total_data() 140 del_role = IndexPage(driver).open_role_page().last_page().del_last_role() 141 time.sleep(2) 142 del_after_num = del_role.get_total_data() 143 try: 144 assert int(del_before_num)-1 == int(del_after_num) 145 self.handler.logger.info("測試用例通過:刪除列表最後一頁的第一條機構資料") 146 except Exception as e: 147 self.handler.logger.error("測試用例不通過:刪除列表最後一頁的第一條機構資料") 148 raise etest_role_manage.py
1 import time 2 import pytest 3 from data.menu_manage_data import open_menu_page, add_menu_normal, add_menu_abnormal, search_normal, search_abnormal, \ 4 del_menu, edit_menu_normal 5 from middleware.MiddleHandler import MidInitHandler 6 from middleware.pages.index import IndexPage 7 from middleware.pages.menu_manage import MenuManagePage 8 9 10 class TestMenuManage: 11 """許可權管理""" 12 handler = MidInitHandler() 13 14 @pytest.mark.parametrize("test_info", open_menu_page) 15 def test_view_menu(self,test_info,login): 16 """開啟選單管理頁面""" 17 driver = login 18 actual = IndexPage(driver).open_menu_page().get_menu_url_title() 19 try: 20 assert test_info["expected"] in actual 21 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 22 except Exception as e: 23 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 24 raise e 25 26 @pytest.mark.parametrize("test_info",add_menu_normal) 27 def test_add_menu_normal(self,test_info,login): 28 """正常新增選單(選單型別為選單)""" 29 menu_name = test_info["menu_name"] + self.handler.random_data() 30 driver = login 31 add_menu = IndexPage(driver).open_menu_page().add_menu_menu(menu_name,test_info["menu_url"],test_info["menu_icon"]) 32 actual = add_menu.get_last_menu_name() 33 try: 34 assert menu_name in actual 35 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 36 except Exception as e: 37 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 38 raise e 39 40 @pytest.mark.parametrize("test_info",edit_menu_normal) 41 def test_edit_menu_normal(self,test_info,login): 42 """正常編輯選單(選單型別為選單)""" 43 menu_name = test_info["menu_name"] + self.handler.random_data() 44 driver = login 45 edit_menu = IndexPage(driver).open_menu_page().edit_menu_menu(menu_name,test_info["menu_url"],test_info["menu_icon"]) 46 actual = edit_menu.get_last_menu_name() 47 try: 48 assert menu_name in actual 49 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 50 except Exception as e: 51 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 52 raise e 53 54 @pytest.mark.parametrize("test_info",add_menu_normal) 55 def test_add_catalog_normal(self,test_info,login): 56 """正常新增選單(選單型別為目錄)""" 57 menu_name = test_info["menu_name"] + self.handler.random_data() 58 driver = login 59 add_menu = IndexPage(driver).open_menu_page().add_menu_catalog(menu_name,test_info["menu_icon"]) 60 actual = add_menu.get_last_menu_name() 61 try: 62 assert menu_name in actual 63 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 64 except Exception as e: 65 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 66 raise e 67 68 @pytest.mark.parametrize("test_info", add_menu_abnormal) 69 def test_add_menu_abnormal(self, test_info, login): 70 """新增選單名稱異常(選單型別為選單)""" 71 menu_name = test_info["menu_name"] 72 driver = login 73 actual = IndexPage(driver).open_menu_page().add_menu_menu(menu_name, test_info["menu_url"],test_info["menu_icon"]).get_name_error_msg() 74 try: 75 assert test_info["expected"] == actual 76 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 77 except Exception as e: 78 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 79 raise e 80 81 @pytest.mark.parametrize("test_info", search_normal) 82 def test_search_normal(self, test_info, login): 83 """搜尋系統中存在的選單名""" 84 driver = login 85 search_menu = IndexPage(driver).open_menu_page().search_menu(test_info["menu_name"]) 86 time.sleep(5) 87 actual = search_menu.get_search_result() 88 try: 89 assert test_info["menu_name"] in actual 90 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 91 except Exception as e: 92 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 93 raise e 94 95 @pytest.mark.parametrize("test_info", search_abnormal) 96 def test_search_abnormal(self, test_info, login): 97 """搜尋系統中不存在的選單名""" 98 driver = login 99 actual = IndexPage(driver).open_menu_page().search_menu(test_info["menu_name"]).get_search_null_msg() 100 try: 101 assert test_info["expected"] == actual 102 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 103 except Exception as e: 104 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 105 raise e 106 107 @pytest.mark.parametrize("test_info", del_menu) 108 def test_cancel_del_menu(self,test_info,login): 109 """取消刪除列表最後一條資料""" 110 driver = login 111 del_before = IndexPage(driver).open_menu_page().get_last_menu_name() 112 MenuManagePage(driver).cancel_del_last_menu() 113 after_before = MenuManagePage(driver).get_last_menu_name() 114 try: 115 assert del_before == after_before 116 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 117 except Exception as e: 118 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 119 raise e 120 121 @pytest.mark.parametrize("test_info", del_menu) 122 def test_del_menu(self,test_info,login): 123 """成功刪除列表最後一條資料""" 124 driver = login 125 del_before = IndexPage(driver).open_menu_page().get_last_menu_name() 126 MenuManagePage(driver).del_last_menu() 127 after_before = MenuManagePage(driver).get_last_menu_name() 128 try: 129 assert del_before != after_before 130 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 131 except Exception as e: 132 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 133 raise etest_menu_manage.py
1 import time 2 3 import pytest 4 5 from data.dict_manage_data import open_dict_page, add_dict_normal, add_dict_abnormal, edit_dict_normal, \ 6 search_dictname_normal, search_dictdescribe_normal, search_dictname_abnormal, del_dict 7 from data.dict_manage_data import add_dictdetails_normal,add_dictdetails_abnormal,edit_dictdetails_normal,\ 8 search_dict_label_normal,search_dict_label_abnormal,del_dictdetails 9 from middleware.MiddleHandler import MidInitHandler 10 from middleware.pages.dict_manage import DictManagePage 11 from middleware.pages.index import IndexPage 12 13 14 class TestDictManage: 15 """系統管理-字典管理""" 16 handler = MidInitHandler() 17 18 @pytest.mark.parametrize("test_info", open_dict_page) 19 def test_view_dict(self,test_info,login): 20 """開啟字典管理頁面""" 21 driver = login 22 actual = IndexPage(driver).open_dict_page().get_dict_list_title() 23 try: 24 assert test_info["expected"] in actual 25 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 26 except Exception as e: 27 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 28 raise e 29 30 @pytest.mark.parametrize("test_info",add_dict_normal) 31 def test_add_dict_normal(self,test_info,login): 32 """正常新增字典列表""" 33 dict_name = test_info["dict_name"] + self.handler.random_data() 34 driver = login 35 add_dict = IndexPage(driver).open_dict_page().add_dict(dict_name,test_info["describe"]) 36 actual = add_dict.dict_last_page().get_last_dict_name() 37 try: 38 assert dict_name in actual 39 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 40 except Exception as e: 41 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 42 raise e 43 44 @pytest.mark.parametrize("test_info", add_dict_abnormal) 45 def test_add_dict_abnormal(self, test_info, login): 46 """異常新增字典列表""" 47 driver = login 48 add_dict = IndexPage(driver).open_dict_page().add_dict(test_info["dict_name"], test_info["describe"]) 49 actual = add_dict.get_name_error_msg() 50 try: 51 assert test_info["expected"] == actual 52 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 53 except Exception as e: 54 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 55 raise e 56 57 @pytest.mark.parametrize("test_info", edit_dict_normal) 58 def test_edit_dict_normal(self, test_info, login): 59 """編輯最後一頁最後字典列表""" 60 dict_name = test_info["dict_name"] + self.handler.random_data() 61 driver = login 62 edit_dict = IndexPage(driver).open_dict_page().dict_last_page().edit_dict(dict_name, test_info["describe"]) 63 actual = edit_dict.dict_last_page().get_last_dict_name() 64 try: 65 assert dict_name == actual 66 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 67 except Exception as e: 68 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 69 raise e 70 71 @pytest.mark.parametrize("test_info", search_dictname_normal) 72 def test_search_dictname_normal(self, test_info, login): 73 """按字典名稱搜尋系統中存在的字典名稱""" 74 driver = login 75 search_dict = IndexPage(driver).open_dict_page().search_dict_name(test_info["dict_name"]) 76 actual = search_dict.get_last_dict_name() 77 try: 78 assert test_info["dict_name"] in actual 79 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 80 except Exception as e: 81 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 82 raise e 83 84 @pytest.mark.parametrize("test_info", search_dictdescribe_normal) 85 def test_search_dictname_normal(self, test_info, login): 86 """按字典描述搜尋系統中存在的字典描述""" 87 driver = login 88 search_dict = IndexPage(driver).open_dict_page().search_dict_describe(test_info["describe"]) 89 actual = search_dict.get_last_dict_describe() 90 try: 91 assert test_info["describe"] in actual 92 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 93 except Exception as e: 94 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 95 raise e 96 97 @pytest.mark.parametrize("test_info", search_dictname_abnormal) 98 def test_search_dictname_abnormal(self, test_info, login): 99 """按字典名稱搜尋系統中不存在的字典名稱""" 100 driver = login 101 search_dict = IndexPage(driver).open_dict_page().search_dict_name(test_info["dict_name"]) 102 actual = search_dict.get_search_null_msg() 103 try: 104 assert test_info["dict_name"] in actual 105 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 106 except Exception as e: 107 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 108 raise e 109 110 111 @pytest.mark.parametrize("test_info", del_dict) 112 def test_cancel_del_dict(self, test_info, login): 113 """取消刪除最後一頁最後一條資料""" 114 driver = login 115 del_before = IndexPage(driver).open_dict_page().dict_last_page().get_last_dict_name() 116 del_dict = DictManagePage(driver).dict_last_page().cacel_del_last_dict() 117 actual = del_dict.get_last_dict_name() 118 try: 119 assert del_before == actual 120 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 121 except Exception as e: 122 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 123 raise e 124 125 def test_open_details(self,login): 126 """開啟字典列表最後一頁最後一條資料的字典詳情""" 127 driver = login 128 open_details = IndexPage(driver).open_dict_page().dict_last_page().open_dict_details() 129 actual = open_details.get_dict_details_title() 130 try: 131 assert "字典詳情" == actual 132 self.handler.logger.info("測試用例通過:開啟字典列表最後一頁最後一條資料的字典詳情") 133 except Exception as e: 134 self.handler.logger.error("測試用例不通過:{}開啟字典列表最後一頁最後一條資料的字典詳情") 135 raise e 136 137 @pytest.mark.parametrize("test_info",add_dictdetails_normal) 138 def test_add_details_normal(self,test_info,login): 139 """正常新增字典詳情""" 140 dict_label = test_info["dict_label"] + self.handler.random_data() 141 driver = login 142 open_details = IndexPage(driver).open_dict_page().dict_last_page().open_dict_details() 143 add_details = open_details.add_dict_details(dict_label,test_info["value"]) 144 actual = add_details.get_last_dict_label() 145 try: 146 assert dict_label in actual 147 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 148 except Exception as e: 149 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 150 raise e 151 152 @pytest.mark.parametrize("test_info",add_dictdetails_abnormal) 153 def test_add_details_abnormal(self,test_info,login): 154 """異常新增字典詳情""" 155 dict_label = test_info["dict_label"] 156 driver = login 157 open_details = IndexPage(driver).open_dict_page().dict_last_page().open_dict_details() 158 add_details = open_details.add_dict_details(dict_label,test_info["value"]) 159 actual = add_details.get_name_error_msg() 160 try: 161 assert test_info["expected"] in actual 162 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 163 except Exception as e: 164 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 165 raise e 166 167 @pytest.mark.parametrize("test_info",edit_dictdetails_normal) 168 def test_edit_details_normal(self,test_info,login): 169 """正常編輯字典詳情""" 170 dict_label = test_info["dict_label"] + self.handler.random_data() 171 driver = login 172 open_details = IndexPage(driver).open_dict_page().dict_last_page().open_dict_details() 173 edit_details = open_details.edit_dict_details(dict_label,test_info["value"]) 174 actual = edit_details.details_last_page().get_last_dict_label() 175 try: 176 assert dict_label in actual 177 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 178 except Exception as e: 179 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 180 raise e 181 182 @pytest.mark.parametrize("test_info",search_dict_label_normal) 183 def test_search_dict_label_normal(self,test_info,login): 184 """搜尋系統中存在的字典標籤""" 185 dict_label = test_info["dict_label"] 186 driver = login 187 open_details = IndexPage(driver).open_dict_page().dict_last_page().open_dict_details() 188 search_details = open_details.search_dict_label(dict_label) 189 actual = search_details.search_details_result() 190 try: 191 assert dict_label in actual 192 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 193 except Exception as e: 194 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 195 raise e 196 197 198 @pytest.mark.parametrize("test_info",search_dict_label_abnormal) 199 def test_search_dict_label_abnormal(self,test_info,login): 200 """搜尋系統中不存在的字典標籤""" 201 dict_label = test_info["dict_label"] 202 driver = login 203 open_details = IndexPage(driver).open_dict_page().dict_last_page().open_dict_details() 204 search_details = open_details.search_dict_label(dict_label) 205 time.sleep(1) 206 actual = search_details.search_details_null_msg() 207 try: 208 assert test_info["expected"] in actual 209 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 210 except Exception as e: 211 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 212 raise e 213 214 @pytest.mark.parametrize("test_info", del_dict) 215 def test_fail_del_dict(self, test_info, login): 216 """刪除最後一頁最後一條字典列表資料(有字典詳情)""" 217 driver = login 218 del_dict = IndexPage(driver).open_dict_page().dict_last_page().del_last_dict() 219 del_after = del_dict.get_tip_msg() 220 try: 221 assert "操作失敗" in del_after 222 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 223 except Exception as e: 224 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 225 raise e 226 227 @pytest.mark.parametrize("test_info",del_dictdetails) 228 def test_cacel_del_dict_details(self, test_info, login): 229 """取消刪除最後一頁最後一列字典標籤""" 230 driver = login 231 open_details = IndexPage(driver).open_dict_page().dict_last_page().open_dict_details() 232 time.sleep(2) 233 del_before = open_details.get_details_total_data() 234 del_details = open_details.cacel_del_last_details() 235 del_after = del_details.get_details_total_data() 236 try: 237 assert int(del_before) == int(del_after) 238 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 239 except Exception as e: 240 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 241 raise e 242 243 @pytest.mark.parametrize("test_info",del_dictdetails) 244 def test_del_dict_details(self, test_info, login): 245 """成功刪除最後一頁最後一列字典標籤""" 246 driver = login 247 open_details = IndexPage(driver).open_dict_page().dict_last_page().open_dict_details() 248 time.sleep(1) 249 del_before = open_details.get_details_total_data() 250 del_details = open_details.del_last_details() 251 time.sleep(1) 252 del_after = del_details.get_details_total_data() 253 try: 254 assert int(del_before)-1 == int(del_after) 255 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 256 except Exception as e: 257 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 258 raise e 259 260 @pytest.mark.parametrize("test_info", del_dict) 261 def test_del_dict(self, test_info, login): 262 """成功刪除最後一頁最後一條字典列表""" 263 driver = login 264 del_before = IndexPage(driver).open_dict_page().get_dict_total_data() 265 del_dict = DictManagePage(driver).dict_last_page().del_last_dict() 266 time.sleep(1) 267 del_after = del_dict.get_dict_total_data() 268 try: 269 assert int(del_before)-1 == int(del_after) 270 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 271 except Exception as e: 272 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 273 raise etest_dict_manage.py
1 import time 2 import pytest 3 from data.auth_manage_data import open_auth_page,add_auth_normal,add_auth_abnormal,search_normal,search_abnormal,del_auth 4 from middleware.MiddleHandler import MidInitHandler 5 from middleware.pages.index import IndexPage 6 7 8 class TestAuthManage: 9 """許可權管理""" 10 handler = MidInitHandler() 11 12 @pytest.mark.parametrize("test_info", open_auth_page) 13 def test_view_auth(self,test_info,login): 14 """開啟許可權管理頁面""" 15 driver = login 16 actual = IndexPage(driver).open_auth_page().get_auth_mark_title() 17 try: 18 assert test_info["expected"] in actual 19 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 20 except Exception as e: 21 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 22 raise e 23 24 @pytest.mark.parametrize("test_info",add_auth_normal) 25 def test_add_auth_normal(self,test_info,login): 26 """正常新增許可權""" 27 auth_name = test_info["auth_name"] + self.handler.random_data() 28 auth_mark = test_info["auth_mark"] 29 driver = login 30 try: 31 IndexPage(driver).open_auth_page().add_auth(auth_name,auth_mark) 32 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 33 except Exception as e: 34 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 35 raise e 36 37 @pytest.mark.parametrize("test_info", add_auth_abnormal) 38 def test_add_auth_abnormal(self, test_info, login): 39 """新增許可權異常""" 40 auth_name = test_info["auth_name"] 41 auth_mark = test_info["auth_mark"] 42 driver = login 43 actual = IndexPage(driver).open_auth_page().add_auth(auth_name, auth_mark).get_name_error_msg() 44 try: 45 assert test_info["expected"] == actual 46 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 47 except Exception as e: 48 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 49 raise e 50 51 @pytest.mark.parametrize("test_info", search_normal) 52 def test_search_normal(self, test_info, login): 53 """搜尋系統中存在的許可權名""" 54 driver = login 55 search_auth = IndexPage(driver).open_auth_page().search_auth(test_info["auth_name"]) 56 time.sleep(5) 57 actual = search_auth.get_search_result() 58 try: 59 assert test_info["auth_name"] in actual 60 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 61 except Exception as e: 62 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 63 raise e 64 65 @pytest.mark.parametrize("test_info", search_abnormal) 66 def test_search_abnormal(self, test_info, login): 67 """搜尋系統中不存在的許可權名""" 68 driver = login 69 actual = IndexPage(driver).open_auth_page().search_auth(test_info["auth_name"]).get_search_null_msg() 70 try: 71 assert test_info["expected"] == actual 72 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 73 except Exception as e: 74 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 75 raise e 76 77 78 @pytest.mark.parametrize("test_info", del_auth) 79 def test_cancel_del_auth(self,test_info,login): 80 """取消刪除列表最後一條許可權資料""" 81 driver = login 82 try: 83 IndexPage(driver).open_auth_page().cancel_del_last_auth() 84 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 85 except Exception as e: 86 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 87 raise e 88 89 # @pytest.mark.parametrize("test_info", del_auth) 90 # def test_cancel_del_auth(self,test_info,login): 91 # """成功刪除列表最後一條許可權資料""" 92 # driver = login 93 # try: 94 # IndexPage(driver).open_auth_page().del_auth() 95 # self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 96 # except Exception as e: 97 # self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 98 # raise etest_auth_manage.py
1 import time 2 import pytest 3 from data.send_email import open_send_email, send_email_normal, search_email_normal, search_email_abnormal, \ 4 send_email_abnormal 5 from middleware.MiddleHandler import MidInitHandler 6 from middleware.pages.index import IndexPage 7 8 9 class TestSendEmail: 10 """傳送郵件""" 11 handler = MidInitHandler() 12 13 @pytest.mark.parametrize("test_info", open_send_email) 14 def test_view_send_email(self,test_info,login): 15 """開啟工作郵箱-傳送郵件頁面""" 16 driver = login 17 actual = IndexPage(driver).open_send_email().get_tab() 18 try: 19 assert test_info["expected"] in actual 20 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 21 except Exception as e: 22 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 23 raise e 24 25 @pytest.mark.parametrize("test_info", send_email_normal) 26 def test_send_email_normal(self,test_info,login): 27 """傳送郵件""" 28 driver = login 29 theme = test_info["theme"] + self.handler.random_data() 30 send_email = IndexPage(driver).open_send_email().send_email(theme,test_info["content"]) 31 time.sleep(1) 32 actual = send_email.last_page().get_last_list() 33 try: 34 assert theme in actual 35 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 36 except Exception as e: 37 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 38 raise e 39 40 @pytest.mark.parametrize("test_info", send_email_abnormal) 41 def test_send_email_abnormal(self,test_info,login): 42 """傳送郵件異常""" 43 driver = login 44 send_email = IndexPage(driver).open_send_email().send_email(test_info["theme"],test_info["content"]) 45 actual = send_email.get_tip_msg() 46 try: 47 assert test_info["expected"] in actual 48 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 49 except Exception as e: 50 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 51 raise e 52 53 @pytest.mark.parametrize("test_info", search_email_normal) 54 def test_search_email(self,test_info,login): 55 """搜尋已存在的郵件標題""" 56 driver = login 57 theme = test_info["theme"] 58 search_email = IndexPage(driver).open_send_email().search_email_theme(theme) 59 time.sleep(1) 60 actual = search_email.last_page().get_serach_resule() 61 try: 62 assert theme in actual 63 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 64 except Exception as e: 65 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 66 raise e 67 68 @pytest.mark.parametrize("test_info", search_email_abnormal) 69 def test_search_email(self,test_info,login): 70 """搜尋不存在的郵件標題""" 71 driver = login 72 theme = test_info["theme"] 73 search_email = IndexPage(driver).open_send_email().search_email_theme(theme) 74 time.sleep(1) 75 actual = search_email.get_serach_null() 76 try: 77 assert test_info["expected"] == actual 78 self.handler.logger.info("測試用例通過:{}".format(test_info["title"])) 79 except Exception as e: 80 self.handler.logger.error("測試用例不通過:{}".format(test_info["title"])) 81 raise e 82 83 def test_view_email_content(self,login): 84 """檢視郵件內容""" 85 driver = login 86 last_page = IndexPage(driver).open_send_email().last_page() 87 title_list = last_page.get_last_list() 88 title_dialog = last_page.click_last_list().get_title_dialog() 89 try: 90 assert title_list == title_dialog 91 self.handler.logger.info("測試用例通過:檢視郵件") 92 except Exception as e: 93 self.handler.logger.error("測試用例不通過:檢視郵件") 94 raise etest_send_email.py
九、conftest->前置條件
1 """ 2 固定檔名 conftest.py. 3 儲存所有的測試夾具。fixture 4 """ 5 import pytest 6 7 from data.login_data import login_success 8 from middleware.MiddleHandler import MidInitHandler 9 from selenium import webdriver 10 from middleware.pages.login import LoginPage 11 12 13 @pytest.fixture(scope="function") 14 def driver(): 15 """管理瀏覽器""" 16 handler = MidInitHandler() 17 driver = webdriver.Chrome() 18 driver.maximize_window() 19 driver.implicitly_wait(handler.yaml["selenium"]["wait_time"]) 20 yield driver 21 driver.quit() 22 23 @pytest.fixture(scope="function") 24 def login(driver): 25 """登入""" 26 user_info = login_success[0] 27 LoginPage(driver).get().login_success( 28 username=user_info["username"], 29 password=user_info["password"] 30 ) 31 yield driverconftest.py
十、pytest.ini->標籤註冊
1 [pytest] 2 markers = 3 success 4 error 5 smoke 6 debugpytest.ini
十一、run->執行
1 import datetime 2 import pytest 3 4 ts = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") 5 6 if __name__ == "__main__": 7 # 生成html報告,樣式比較醜 8 # pytest.main(["--html={}.html".format(ts)]) 9 # 檢視allure的測試報告 10 # D:\Program Files (x86)\PyCharm\workspace\SmartCampus_web>allure serve allureout 11 pytest.main(["--alluredir=allureout".format(ts),"-m debug"]) 12 # pytest.main(["--alluredir=allureout".format(ts)])run.py