1. 程式人生 > 實用技巧 >實戰二:智慧校園web測試

實戰二:智慧校園web測試

一、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 
 10
class 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()
basepage.py
 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 logger
logging_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 None
requests_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 None
yaml_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 HTMLTestRunner
HTMLTestRunner

五、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_data
MiddleHandler.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.text
login.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 self
org_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 self
role_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 self
menu_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 self
dict_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 self
auth_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 e
test_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 e
test_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 e
test_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 e
test_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 e
test_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 e
test_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 e
test_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 driver
conftest.py

十、pytest.ini->標籤註冊

1 [pytest]
2 markers =
3     success
4     error
5     smoke
6     debug
pytest.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