Python+Selenium+Unittest實現PO模式web自動化框架(2)


1.Common目錄下的具體模塊講解。

 

 2.basepage.py

basepage.py模塊里面是封裝的對元素的操作。例如:查找元素、點擊元素、文本輸入等等。

# --^_^-- coding:utf-8 --^_^--
# @Remark:webdriver的封裝

from Common import logger
import logging
import time
import datetime
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from Common.dir_config import screenshot_dir
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.select import Select
import win32gui
import win32con


class BasePage:
    '''
    包含了PageObjects當中,用到所有的selenium底層方法。
    還可以包含通用的一些元素操作,如alert,iframe,windows...
    還可以自己額外封裝一些web相關的斷言
    實現日志記錄、實現失敗截圖
    '''
    def __init__(self,driver):
        self.driver = driver

    # 實現網頁截圖操作
    def save_web_screenshot(self,img_doc):
        # 頁面_功能_時間.png
        now = time.strftime("%Y-%m-%d %H_%M_%S")
        filepath = "{}-{}.png".format(now,img_doc)
        try:
            self.driver.save_screenshot(screenshot_dir + "/" + filepath)
            logging.info("網頁截圖成功!圖片存儲在:{}!".format(screenshot_dir +"/" + filepath))
        except:
            logging.exception("網頁截圖失敗!")
            raise

    # 等待元素可見
    def wait_eleVisible(self,loc,img_doc="",timeout=30,frequency=0.5):
        logging.info("等待元素{}可見!".format(loc))
        try:
            # 起始等待的時間datetime
            startTime = datetime.datetime.now()
            # 等待元素
            WebDriverWait(self.driver,timeout,frequency).until(EC.visibility_of_element_located)
            # 結束等待時間
            endTime = datetime.datetime.now()
            logging.info("等待元素成功!開始等待時間:{},結束等待時間:{},等待時長為:{}!".format(startTime, endTime, endTime - startTime))
        except:
            # 日志
            logging.exception("等待元素可見失敗!")
            # 截圖-哪一個頁面哪一個操作導致的失敗 + 當前時間
            self.save_web_screenshot(img_doc)
            raise

    # 查找一個元素
    def get_element(self, loc, img_doc=""):
        '''
        :param loc: 元素定位,以元組的形式。(定位類型、定位時間)
        :param img_doc:截圖的說明。例如:登錄頁面_輸入用戶名
        :return:webElement對象。
        '''
        logging.info("查找{}中的元素{}".format(img_doc, loc))
        try:
            ele = self.driver.find_element(*loc)
            logging.info("查找{}元素成功!".format(ele))
            return ele
        except:
            # 日志
            logging.exception("查找元素失敗!")
            # 截圖
            self.save_web_screenshot(img_doc)
            raise

    # 等待元素出現,點擊元素
    def click_element(self, loc, img_doc,timeout=30, frequency=0.5):
        '''
        :param loc:元素定位,以元組的形式。(定位類型、定位時間)
        :param img_doc:截圖的說明。例如:登錄頁面_輸入用戶名
        :param timeout:等待元素的超時上限
        :param frequency:等待元素可見時,輪詢周期
        :return:
        '''
        # 等待元素可見
        self.wait_eleVisible(loc, img_doc, timeout, frequency)
        # 查找元素
        ele = self.get_element(loc, img_doc)
        # 點擊操作
        logging.info("點擊元素{}!".format(loc))
        try:
            ele.click()
            logging.info("點擊元素{}成功!".format(ele))
        except:
            # 日志
            logging.exception("點擊元素失敗!")
            # 截圖
            self.save_web_screenshot(img_doc)
            raise

    # 文本輸入
    def input_text(self, loc, img_doc, *args):
        '''
        等待元素可見,找到元素,並在元素中輸入文本信息
        :param loc:元組形式的元素定位表達式
        :param img_doc:執行失敗時,截圖的文件命名
        :param args:輸入操作中,可以輸入多個值,也可以組合按鍵
        :return:
        '''
        # 等待元素出現
        self.wait_eleVisible(loc, img_doc)
        # 查找元素
        ele = self.get_element(loc, img_doc)
        # 清空輸入框內容
        self.clear_data(loc,img_doc)
        # 文本輸入
        logging.info("給元素{}輸入文本內容:{}".format(loc, *args))
        try:
            ele.send_keys(*args)
            logging.info("文本輸入成功!")
        except:
            # 日志
            logging.exception("文本輸入失敗!")
            # 截圖
            self.save_web_screenshot(img_doc)
            raise

    # 獲取元素的屬性值
    def get_element_attribute(self, loc, attr_name, img_doc):
        '''
        獲取元素標簽的內容
        :param loc:元素定位,以元組的形式。(定位類型、定位時間)
        :param attr_name:屬性名稱
        :param img_doc:執行失敗時,截圖的文件命名
        :return:
        '''
        # 等待元素出現
        self.wait_eleVisible(loc, img_doc)
        # 查找元素
        ele = self.get_element(loc, img_doc)
        # 獲取屬性
        try:
            attr_value = ele.get_attribute(attr_name)
            logging.info("獲取元素{}的屬性{}值為:{}!".format(loc, attr_name, attr_value))
            return attr_value
        except:
            # 日志
            logging.exception("獲取元素屬性失敗!")
            # 截圖
            self.save_web_screenshot(img_doc)
            raise

    # 獲取元素的文本值
    def get_element_text(self, loc, img_doc):
        '''
        :param loc:元素定位,以元組的形式。(定位類型、定位時間)
        :param img_doc:執行失敗時,截圖的文件命名
        :return:
        '''
        # 等待元素出現
        self.wait_eleVisible(loc, img_doc)
        # 查找元素
        ele = self.get_element(loc,img_doc)
        # 獲取文本值
        try:
            text = ele.text
            logging.info("獲取元素{}的文本值為:{}!".format(loc, text))
            return text
        except:
            # 日志
            logging.exception("獲取元素文本值失敗!")
            # 截圖
            self.save_web_screenshot(img_doc)
            raise

    # 鼠標懸浮操作
    def mouse_suspension(self,loc, img_doc):
        # 實例化ActionChains
        ac = ActionChains(self.driver)
        # 等待元素出現
        self.wait_eleVisible(loc, img_doc)
        # 查找元素
        ele = self.get_element(loc)
        # 鼠標懸浮
        try:
            ac.move_to_element(ele).perform()
            time.sleep(1)
            logging.info("鼠標懸浮成功!")
        except:
            # 日志
            logging.exception("鼠標懸浮失敗!")
            # 截圖
            self.save_web_screenshot(img_doc)
            raise

    # 進入到iframe中
    def get_iframe(self,loc,img_doc):
        # 等待元素出現
        self.wait_eleVisible(loc, img_doc)
        # 查找元素
        ele = self.get_element(loc)
        # 進入iframe
        try:
            self.driver.switch_to.frame(ele)
            logging.info("進入iframe中成功!")
        except:
            # 日志
            logging.exception("進入到iframe中失敗!")
            # 截圖
            self.save_web_screenshot(img_doc)
            raise

    # 通過文本選擇下拉選擇框
    def drop_down_select(self,loc,text,img_doc):
        # 等待元素出現
        self.wait_eleVisible(loc, img_doc)
        # 查找select元素
        ele = self.get_element(loc)
        # 下拉選擇
        try:
            Select(ele.select_by_visible_text(text))
            logging.info("選擇select成功!")
        except:
            # 日志
            logging.exception("下拉選擇失敗!")
            # 截圖
            self.save_web_screenshot(img_doc)
            raise

    # 選擇非select的下拉選擇框
    def drop_down_not_select(self,loc1,loc2,img_doc):
        # 先定位到下拉菜單
        # 等待元素出現
        self.wait_eleVisible(loc1, img_doc)
        # 查找下拉菜單元素
        self.click_element(loc1,"下拉菜單輸入框")
        logging.info("查找下拉菜單輸入框成功!")
        time.sleep(2)
        # 在對下拉菜單的選項進行選擇
        try:
            # 選擇下拉菜單選項
            # 等待元素出現
            self.wait_eleVisible(loc2, img_doc)
            self.click_element(loc2,"選擇下拉菜單選項")
            logging.info("選擇下拉菜單成功!")
        except:
            # 日志
            logging.exception("下拉選擇失敗!")
            # 截圖
            self.save_web_screenshot(img_doc)
            raise

    # 清空輸入框中的內容
    def clear_data(self,loc,img_doc):
        # 等待元素出現
        self.wait_eleVisible(loc, img_doc)
        # 查找一個元素
        ele = self.get_element(loc)
        # 清空輸入框
        try:
            ele.clear()
            logging.info("清空輸入框成功!")
        except:
            # 日志
            logging.exception("清空輸入框失敗!")
            # 截圖
            self.save_web_screenshot(img_doc)
            raise

    # 上傳操作(前提 :windows上傳窗口已經出現。sleep1-2秒等待彈出的出現。)
    def upload(filePath, browser_type="chrome"):
        if browser_type == "chrome":
            title = "打開"
        else:
            title = ""

        # 找元素
        # 一級窗口"#32770","打開"
        dialog = win32gui.FindWindow("#32770", title)
        ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, "ComboBoxEx32", None)  # 二級
        comboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, "ComboBox", None)  # 三級
        # 編輯按鈕
        edit = win32gui.FindWindowEx(comboBox, 0, 'Edit', None)  # 四級
        # 打開按鈕
        button = win32gui.FindWindowEx(dialog, 0, 'Button', "打開(&O)")  # 四級

        # 往編輯當中,輸入文件路徑.
        win32gui.SendMessage(edit, win32con.WM_SETTEXT, None, filePath)  # 發送文件路徑
        win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)  # 點擊打開按鈕

3.dir_config.py

dir_config.py模塊里面封裝的是項目當中需要用到的路徑配置,該配置是相對項目來說的相對配置,這樣項目無論放在哪里都能使用而不報錯。

# --^_^-- coding:utf-8 --^_^--
# @Remark:路徑配置

import os

# 框架項目頂層目錄
base_dir = os.path.split(os.path.split(os.path.abspath(__file__))[0])[0]

# 日志目錄
logs_dir = os.path.join(base_dir, "Outputs/logs")

# 截屏目錄
screenshot_dir = os.path.join(base_dir, "Outputs/screenshots")

# 測試數據目錄
testdatas_dir = os.path.join(base_dir, "TestDatas")

# 測試用例目錄
testcases_dir = os.path.join(base_dir, "TestCases")

# 測試報告目錄
htmlreport_dir = os.path.join(base_dir, "Outputs/reports")

4.HTMLTestRunnerNew.py

HTMLTestRunnerNew.py模塊是用於生成HTML的測試報告模塊。(具體的模塊代碼太長,不方便展示。有需要可私聊。)

 5.logger.py

logger.py模塊是自定義的log日志模塊。

# --^_^-- coding:utf-8 --^_^--
# @Remark:日志模塊

import logging
from logging.handlers import TimedRotatingFileHandler
import datetime
from Common import dir_config

fmt = "%(asctime)s  %(levelname)s %(filename)s %(funcName)s [ line:%(lineno)d ] %(message)s"
datefmt = "%Y-%m-%d %H:%M:%S"
# 獲取當前時間
now_time = datetime.datetime.now().strftime('%Y-%m-%d')
# 把當前時間轉換成str
now_time_str = str(now_time)

handler_1 = logging.StreamHandler()
handler_2 = TimedRotatingFileHandler(dir_config.logs_dir + "/" + now_time_str + "_Web.log", when='D', interval=10,backupCount=0, encoding='utf-8')

# 設置rootlogger 的輸出內容形式,輸出渠道
logging.basicConfig(format=fmt, datefmt=datefmt, level=logging.INFO, handlers=[handler_1, handler_2])

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM