国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

selenium UI自動化PO模式測試框架搭建

這篇具有很好參考價值的文章主要介紹了selenium UI自動化PO模式測試框架搭建。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

1、UI自動化規(guī)劃

熟悉業(yè)務(wù)-》確定方案-》選取場景-》了解前端-》定位元素-》編寫腳本-》運(yùn)行優(yōu)化-》回歸報告-》項目匯總
價值意義:
自動化執(zhí)行需要:模塊化
需要可制定化執(zhí)行
可復(fù)用性
PO模式:
將頁面定位和業(yè)務(wù)分開,元素的定位單獨(dú)處理,執(zhí)行腳本單獨(dú)封裝。維護(hù)方便。
封裝BasePage類,在基類中具有webdriver的實(shí)例的屬性,把每個頁面繼承BasePage,通過driver管理每個頁面的元素,將頁面再細(xì)分一個個方法。Testcase依賴page類,進(jìn)行組織化的測試步驟。
維護(hù):
元素變化了:維護(hù)每個page
測試步驟變化:維護(hù)Testcase
每個page的常規(guī)操作封裝基類:
點(diǎn)擊動作、輸入、文本處理、滑動、彈窗……
業(yè)務(wù)分類:
登錄模塊(登錄、注冊新用戶)、
首頁模塊(菜單欄、主頁顯示)、
管理模塊(數(shù)據(jù)列表展示、新增、分類、……)、
用戶模糊(用戶數(shù)據(jù)信息展示)……
功能測試用例依據(jù)以此分類設(shè)計

2、PageObject設(shè)計模式

系統(tǒng)梳理分類

代碼層面分類:
系統(tǒng)System:
ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
其中:
pageObjects
testCase
common
configs
utils
outFiles文件夾(logs/reports/screenshoot
docs文件夾
data文件夾
ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
PO模式從下往上,從底層開始寫:driver-》BasePage-》pages-》test執(zhí)行-》報告
python+selenium+pytest+allure .

3、PO模式封裝

1、驅(qū)動模塊(固定寫法)

封裝驅(qū)動寫在:common包下
新建myDriver.py文件,建一個兼容瀏覽器的驅(qū)動類,就是dirver

"""
驅(qū)動模塊
    1、考慮到瀏覽器的兼容性,可以分為主流的幾個瀏覽器驅(qū)動
        1、谷歌
        2、火狐
        3、其他
"""

from selenium import webdriver
from configs.config import implicitly_wait_time

# 設(shè)置單例模式
'''
類創(chuàng)建實(shí)例:
    1、先調(diào)用—__new__()創(chuàng)建方法,一般類中不寫,自動調(diào)用
    2、再調(diào)用初始化方法__init__()
  判斷一個類是否有實(shí)例,如果有,就不會創(chuàng)建新的實(shí)例  
'''

# 哪一個類的實(shí)例需要使用單例模式,就直接繼承這個類(`固定寫法`)
class Single(object):
	#new方法創(chuàng)建對象
	def __new__(cls, *args, **kwargs):
	# 判斷當(dāng)前的類是否已經(jīng)實(shí)例化
		if not hassttr(cls, '_instance'):
			cls._instance = super().__new__(cls)# super是父類的new方法
		return cls._instance
	

class Driver(Single):
    # 新建一個初始值
    _driver = None

    # 判斷使用瀏覽器,---------默認(rèn)指定谷歌瀏覽器
    def get_driver(self, browser_name='chrome'):
        if self._driver is None:
            if browser_name == "chrome":
                self._driver = webdriver.Chrome()
            elif browser_name == "firefox":
                self._driver = webdriver.Firefox()
            else:
                raise (f"沒有這個{browser_name}瀏覽器,請使用可用瀏覽器打開")
            # 設(shè)置隱式等等時間---設(shè)置`**全局變量`**等等時間5s
            self._driver.implicitly_wait(implicitly_wait_time)
            # 瀏覽器對大化
            self._driver.maximize_window()
        return self._driver  # 返回瀏覽器對象


if __name__ == '__main__':
    Driver().get_driver('chrome')# 創(chuàng)建實(shí)例對象,調(diào)用對應(yīng)的方法,傳什么瀏覽器使用什么瀏覽器

驅(qū)動模塊封裝完畢,后續(xù)只需要調(diào)用Driver().get_driver('chrome')就可以使用webdriver進(jìn)行元素定位
等同于對driver= webdriver.Chrome()的封裝,方便兼容不同瀏覽器。

1、隱式等待時間全局變量參數(shù)化
configs包下創(chuàng)建config文件,設(shè)置隱式等待時間參數(shù)5s或者10s,自定義

implicitly_wait_time = 5

2、基類封裝(基本框架固定寫法)

基類寫在:common包下,新建一個文件basePage.py

  • 創(chuàng)建基類basePage
    作用:1、把基本的頁面操作封裝好,給其他頁面繼承使用
    包含:2、點(diǎn)擊操作(click)、輸入框輸入(input_text)、獲取元素屬性值(get_attrbute)、元素可見(visibility)、截圖(save_screenshot)、清除(clear),獲取文本內(nèi)容(get_text)、顯示等待presence_of(元素可見(visibility_of),可操作點(diǎn)擊(clickable))……等操作指令的封裝
from common.myDriver import Driver
import time
import os.path
from utils.handle_logs import logger
from utils.handle_path import screenshot_path, config_path
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from utils.handle_yaml import get_yaml_data
from common.myDriver import Driver
from configs_delivery.config import wait_timeout, wait_poll_frequency

class BasePage:
    def __init__(self):  # 調(diào)用basepage 需要的瀏覽器對象,默認(rèn)谷歌瀏覽器
        self._driver = Driver().get_driver()

    # ------------------------封裝截圖方法---------------------------
    # 截圖操作:可以使用瀏覽器對象去調(diào)用,也可以使用元素調(diào)用
    def get_page_screenshot(self, action=None):
        # 注意截圖的描述:哪個動作+時間
        curTime = time.strftime('%Y%m%d%H%M%S', time.localtime())
        filepath = os.path.join(screenshot_path, f'{action}_{curTime}.png')
        # 截圖操作
        self._driver.save_screenshot(filepath)

    # ----------------------封裝頁面操作------------------------
    # 1、封裝-輸入-操作
    def input_text(self, locator, text, action=None):
        '''

        :param locator: 元素定位: locator定義為包含-元素定位方法-和-定位方式-的包 ----['id','name']
        :param text: 輸入文本的內(nèi)容
        :param action: 執(zhí)行的動作描述,缺省參數(shù)
        
        '''
        # 1、元素定位
        # find_element(定位方式,定位表達(dá)式)
        element = self._driver.find_element(*locator)  # "*"號解包
        # 2、很多輸入框有默認(rèn)提示文本,需要先清除
        element.clear()
        # 3、輸入值
        element.send_keys(text)
    # 2、封裝-點(diǎn)擊-操作
    def click(self, locator, action=None):
        # 1、元素定位
        # find_element(定位方式,定位表達(dá)式)
        element = self._driver.find_element(*locator)  # "*"號解包
        # 2、點(diǎn)擊
        element.click()
    # 3、封裝-清空-操作
    def clear(self, locator, action=None):
        # 1/元素定位
        element = self._driver.find_element(*locator)
        # 2/清空
        element.clear()    
	# 4、封裝 -獲取文本內(nèi)容-操作
    def get_text(self, locator, action=None):
        return WebDriverWait(
            self._driver,
            timeout=wait_timeout,
            poll_frequency=wait_poll_frequency).until(
            EC.visibility_of_element_located(locator)).text 
  
   # ----封裝顯式等待---判斷元素是否存在,如果沒有獲取到元素,使用顯示等待判斷----日志及截圖-------
    def element_is_presence(
            self,
            locator,
            action=None,
            timeout=5,
            poll_frequency=0.5):
        '''

        :param locator: 定位元素和定位方法和表達(dá)式,包('','')
        :param action: 動作描述,
        :param timeout: 等待時間設(shè)置
        :param poll_frequency: 等待頻率
        '''
        # 1/設(shè)置顯式等待時間
        try:
            WebDriverWait(
                self._driver,
                timeout=timeout,
                poll_frequency=poll_frequency).until(
                EC.presence_of_element_located(locator))
        except BaseException:
            # 1/打印log信息
            log.error(action)
            # 2/截圖
            self.get_page_screenshot(action)
            # 3/元素不存在返回False
            return False
        # 如果存在返回True
        return True

---------------------------------------------------

  • 1、路徑配置
    上述:screenshot_path,在公共方法utils中封裝,新建handle_path.py
    ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
    需要的路徑都可以提前封裝好:(固定寫法
import os

# 1、工程路徑
# os.path.obspath(__file__)  當(dāng)前文件路徑
# os.path.dirname()------獲取上一層路徑
project_path = os.path.dirname(os.path.dirname(__file__))
# 2、截圖路徑
screenshot_path = os.path.join(project_path, r'outFiles\screenshot')
# 3、日志路徑
logs_path = os.path.join(project_path, r'outFiles\logs')
# 4、測試數(shù)據(jù)路徑
testcase_path = os.path.join(project_path, 'data')
# 5、測試報告路徑
reports_path = os.path.join(project_path, r'outFiles\reports\tmp')
# 6、配置路徑
config_path = os.path.join(project_path, 'configs')

if __name__ == '__main__':
    # print(project_path)
    # print(screenshot_path)
    # print(logs_path)
    # print(reports_path)
    # print(testcase_path)
    print(config_path)
  • 2、log的封裝(固定方法)
    utils包下新建handle_logs.py
    基類中封裝顯示等待的時間需要截圖、并抓取log。
"""
日志相關(guān)內(nèi)容
    1、日志的輸出渠道:文件xxx.logs        控制臺輸出
    2、日志級別:CRITICAL-ERROR-WARNING-INFO-DEBUG
    3、日志內(nèi)容:2023-03-30 18:42:12, 234 INFO XXXXXXXX
        年月日.時分秒.級別-哪行代碼出錯-具體內(nèi)容
"""
import logging
import datetime
from utils.handle_path import logs_path


def logger(file_Log=True, name=__name__):
    logDir = f'{logs_path}-{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}.txt'
    # 1/創(chuàng)建日志收集器對象
    logObject = logging.getLogger()
    # 2/ 設(shè)置日志的級別
    logObject.setLevel(logging.DEBUG)
    # 3/ 日志內(nèi)容格式
    fmt = '%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s'
    formater = logging.Formatter(fmt)

    if file_Log:  # log文件模式
        # 設(shè)置日志渠道 -文件輸出
        handle = logging.FileHandler(logDir, encoding='utf-8')
        # 日志內(nèi)容與渠道綁定
        handle.setFormatter(formater)
        # 把日志對象與渠道綁定
        logObject.addHandler(handle)
    else:
        # 設(shè)置日志渠道控制臺 控制臺輸出
        handle2 = logging.StreamHandler()
        # 日志內(nèi)容與渠道綁定
        handle2.setFormatter(formater)
        # 把日志對象與渠道綁定
        logObject.addHandler(handle2)
    return logObject


log = logger()  # 控臺輸出日志

if __name__ == '__main__':
    log = logger()  # 控制臺輸出日志
    log.debug('日志信息:')
  • 3、
    locator的定義:
    selenium4 升級后定位方式變化為:driver.find_element(By.定位方法, '定位方式')格式
    例如:ID定位某個元素:

    login = driver.find_element(By.ID, 'btnLogin')
    

    locator即是By.定位方法, '定位方式'這個包

  • 4、封裝頁面操作:后續(xù)需要自行添加函數(shù)封裝即可

    • 顯示等待如上封裝,可見元素定位的封裝方法如下
 def element_is_presence(
            self,
            locator,
            action=None,
            timeout=5,
            poll_frequency=0.5):
        '''
   def element_is_visibility(
            self,
            locator,
            action=None,
            timeout=5,
            poll_frequency=0.5):
        # 1/設(shè)置顯式等待可見元素定位時間
        try:
            ele = WebDriverWait(
                self._driver,
                timeout=timeout,
                poll_frequency=poll_frequency).until(
                #判斷元素是否可見再執(zhí)行定位
                EC.visibility_of_element_located(locator))
        except BaseException:
            # 1/打印log信息
            log.error(action)
            # 2/截圖
            self.get_page_screenshot(f'{action}-元素定位不到')
            # 3/元素不存在直接拋出異常信息
            raise
        # 如果存在返回元素本身
        return ele 

而封裝的頁面操作使用可見元素定位的方法修改為:

 # 2、輸入操作
    def click(self, locator, action=None):
        # 1、元素定位
        # element_is_visibility(定位方式,定位表達(dá)式)。元素是可見的再進(jìn)行定位
        element = self.element_is_visibility(locator)
        # 2、點(diǎn)擊
        element.click()
  • 封裝定位元素是可點(diǎn)擊的方法
    # ----------------------可見元素且是可點(diǎn)擊的-----------------
    def element_is_clickable(
            self,
            locator,
            action=None,
            timeout=5,
            poll_frequency=0.5):
        # 1/設(shè)置顯式等待可見元素定位時間
        try:
            ele = WebDriverWait(
                self._driver,
                timeout=timeout,
                poll_frequency=poll_frequency).until(
                # 判斷元素是否可點(diǎn)擊執(zhí)行定位
                EC.element_to_be_clickable(locator))
        except BaseException:
            # 1/打印log信息
            log.error(action)
            # 2/截圖
            self.get_page_screenshot(f'{action}-元素定位不到')
            # 3/元素不可點(diǎn)擊直接拋出異常信息
            raise
        # 如果存在返回元素本身
        return ele

相應(yīng)頁面的操作封裝方法:

 # 2、輸入操作
    def click(self, locator, action=None):
        # 1、元素定位
        # element_is_visibility(定位方式,定位表達(dá)式)。元素是可見的再進(jìn)行定位
        element = self.element_is_clickable(locator)
        # 2、點(diǎn)擊
        element.click()
  • 5、wait_timeout, wait_poll_frequency在config中提前配置號
    ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
    ---------------------------------.----------------------------------------

3、設(shè)置yaml定位元素(固定寫法)

config包下新建一個文件locator.yaml 寫定位配置數(shù)據(jù)

  • 【”定位方法“,”定位方式“】的寫法即:.find_element_by_id('username '),取id和對應(yīng)的屬性值,八大元素定位法之一。
  • 若采用css或者xpath寫法:message_text: [‘css selector’,‘.el-message--error’] #登錄錯誤消息文本:css selector即定位方法,.el-message--error定位方式。構(gòu)成了字典格式{xxx:{ss:['v','v'],ss:['v','v'],ss:['v','v']},{[],[]},{[],[]}},后續(xù)通過字典的鍵獲取值執(zhí)行操作
LoginPage:
  username_input: ['id','username']#登錄賬戶
  pwd_input: ['id','pwd']#登錄密碼
  login_btn: ['id','btnLogin']#登錄按鈕
  message_text: ['css selector','.el-message--error'] #登錄錯誤消息文本
OtherPage:
  home_button: ['xpath','//*[text()="首頁"]'] #首頁按鈕
  logout_button: ['xpath',"http://span[text()='退出']"] #退出按鈕
  personal_button: ['xpath','//img']  #個人中心按鈕
  

4、讀取yaml定位數(shù)據(jù)(固定寫法)

utils包下新建一個文件,handle_yanl.py 處理獲取yaml數(shù)據(jù)

import yaml
from  utils.handle_path import config_path

def get_yaml_data(fileDir):
    #方法一
    # # 1、打開文件
    # fo = open(fileDir, 'r', encoding='utf-8')
    # # 2、讀取文件
    # yaml_data = yaml.load(fo, Loader=yaml.FullLoader)
    # return yamldata
    #方法二
    with open(fileDir, encoding='utf-8') as fo:
        return yaml.safe_load(fo.read())


if __name__ == '__main__':
    print(get_yaml_data(f'{config_path}\locator.yaml'))

5、寫PO頁面-繼承基類

先寫個基礎(chǔ)常規(guī)的頁面:后續(xù)還有優(yōu)化的方法

在pageObject新建操作模塊頁面:比如:login_page.py,繼承basePage
登錄頁面:

from  utils.handle_path import config_path
from common.basePage import BasePage
from configs.config import url
from time import sleep
from utils.handle_yaml import get_yaml_data


class LoginPage(BasePage): # 繼承基類
    def to_login_page(self):
        self._driver.get(url)  # 打開登錄頁面,url在config包中配置
        return self		#登錄網(wǎng)址返回self本身,方便后續(xù)調(diào)用

    # 1、登錄
    def login(self, username, pwd):
    	#讀取yaml定位參數(shù)locator['LoginPage']提取鍵值數(shù)據(jù)
        locator = get_yaml_data(f'{config_path}\locator.yaml')['LoginPage']
        # 輸入賬號,locator['username_input']獲取定位方法和定位方式,xxx填寫容
        self.input_text(locator['username_input'], 'username', action='輸入賬號')
        # 輸入密碼
        self.input_text(locator['pwd_input'], 'pwd', action="輸入密碼")
        # 點(diǎn)擊登錄按鈕
        self.click(locator['login_btn'], action="點(diǎn)擊登錄按鈕")
        sleep(5)


if __name__ == '__main__':
    # 登錄頁面
    LoginPage().to_login_page().login('uername','pwd' )

------------------------**注**---------------------------------

  • 1、urlconfigs中配置后再調(diào)用
    ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
    定位獲取優(yōu)化方法:

locator = get_yaml_data(f’{config_path}\locator.yaml’)[‘LoginPage’]
self.input_text(locator[‘username_input’], ‘username’, action=‘輸入賬號’)
一個項目上百個定位元素,每次都通過get_yaml_data文件處理數(shù)據(jù),然后再通locator
一個獲取定位方法和定位方式比較繁瑣。
so:設(shè)計了巧妙的定位調(diào)用方法,腳本中對于定位不可見,但是卻省事省力的方法:

在設(shè)計locator.yaml文件是,把字典的鍵設(shè)計成語po頁面的類同名即可。
ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
在基類中封裝一下:

import time
import os.path
from utils.handle_logs import logger
from utils.handle_path import screenshot_path, config_path
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from utils.handle_yaml import get_yaml_data
from common.myDriver import Driver

class BasePage:
    def __init__(self):  # 調(diào)用basepage 需要的瀏覽器對象,默認(rèn)谷歌瀏覽器
        self._driver = Driver().get_driver()
        # --------------獲取所有需要的定位的元素參數(shù),且實(shí)現(xiàn)對號入座
        # loginpage-----只獲取loginPage
        # [self.__class__.__name__]獲取到對應(yīng)的類的名字,yaml定位元素時命名與后續(xù)頁面操作類的名字保持一樣
        locator = get_yaml_data(
            config_path + r'\locator.yaml')[self.__class__.__name__]  # 字典
        # print(locator)
        for k, v in locator.items():  # k自定義鍵名,v(定位方法,定位表達(dá)式)
            setattr(self, k, v)
            """
            setattr(self, k, v)
                1、self是頁面的實(shí)例
                2、使用set attrbute--setattr
                3、創(chuàng)建self這個實(shí)例的新的屬性,將v賦值給她,self.k = v
                例子:
                class Test:
                    pass
                test = Test()  創(chuàng)建實(shí)例
                #對實(shí)例再創(chuàng)建屬性,并將對應(yīng)屬性的值賦給它
                setattr(test, 'name', '123')
                print(test.name)
                結(jié)果就是test.name = 123
            """

------------------------**注**-----------------------------
上述locator的封裝方式就是通過[self.__class__.__name__]獲取到對應(yīng)po頁面的本身類的名字

 locator = get_yaml_data(
            config_path + r'\locator.yaml')[self.__class__.__name__]  # 字典格式

例如登錄的定位元素打印出來是:
ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
所以對字典處理:setattr方法將鍵值和self綁定

for k, v in locator.items():  # k自定義鍵名,v(定位方法,定位表達(dá)式)
            setattr(self, k, v)

則,self.k = v,則最終可以獲取[‘id’, ‘username’],也就是我們需要的,定位方法和定位方式
基類封裝中可以直接使用self.自定義鍵名

find_element(定位方式,定位表達(dá)式) ==find_element(self.自定義鍵名)

則優(yōu)化后登錄頁面可以寫成:

from pageObjcets.homePage import HomePage
from common.basePage import BasePage
from configs.config import url
from time import sleep


# 登錄類,繼承基類
class LoginPage(BasePage):
    def to_loginPage(self):
        self._driver.get(url)  # 打開登錄頁面
        return self

    # 1、登錄
    def login(self, username, pwd):
        # 輸入賬號self.username_input:優(yōu)化后的方法
        self.input_text(self.username_input, username, action='輸入賬號')
        # 輸入密碼
        self.input_text(self.pwd_input, pwd, action="輸入密碼")
        # 點(diǎn)擊登錄按鈕"self.login_btn"就是優(yōu)化后的使用方法
        self.click(self.login_btn, action="點(diǎn)擊登錄按鈕")
        sleep(2)


if __name__ == '__main__':
    # # 登錄頁面
    homepage = LoginPage().to_loginPage().login('xxx', 'xxx')
    # 首頁展示
    # # print('這個類的名字是', LoginPage().__class__.__name__)

這樣的話,整個測試框架中看不到定位:只需要配置locator.yaml即可。后續(xù)保持鍵與各個page的類名一樣即可。
-------------------------------.----------------------------------

6、測試用例yaml

data文件夾下新建一個文件loginData.yaml
登錄的的測試用例編寫格式:

# 登錄成功用例
- ['usernamexxx','pswxxx'] # 賬號密碼正確
---   #分隔符
# 登錄失敗用例
- [['xpath',"http://*[contains(text(),'該用戶不存在!')]"],'該用戶不存在!','usernamexx','pswxxx']
- [['xpath',"http://*[contains(text(),'輸入的密碼錯誤!')]"],'輸入的密碼錯誤!','usernamexx','pswxxx']
- [['xpath',"http://*[contains(text(),'該用戶不存在!')]"],'該用戶不存在!','','111111']
- [['css selector','.el-form-item__error'],'The password can not be less than 5 digits','xxxx','']
- [['css selector','.el-form-item__error'],'The password can not be less than 5 digits','','']

用例編寫完,需要進(jìn)一步處理數(shù)據(jù)成為自己想要的:[(‘username’,‘pwd’),(‘us’,‘pwd’),(‘usme’,‘wd’)]這種格式的,就可以使用pytest.mark.parametrize()參數(shù)化了。
在utile包新建一個handle_yaml.py文件,因?yàn)橹疤幚矶ㄎ粂aml有了,就在當(dāng)前文件下封裝個讀取用例的get_case_yaml函數(shù):因?yàn)槲覀儼颜蛴美头聪蛴美龑懺谝粋€yaml文件里,分隔成兩個yaml文件數(shù)據(jù)了,需要單獨(dú)處理

def get_case_yaml(filedir):
    caselist = []
    # 1、打開文件
    fo = open(filedir, 'r', encoding='utf-8')
    # 2、讀取文件
    testcases = yaml.load(fo, Loader=yaml.FullLoader)
    for one in testcases:
        caselist.append(one)
    return caselist
    # print(testcases)

test_login.py提取數(shù)據(jù)時需要使用角標(biāo)提取就行了:
get_case_yaml(filedir[0]),提取的就是正確的密碼和賬號
get_case_yaml(filedir[1]),提取反向用例的數(shù)據(jù)

7、pytest測試模塊+allure測試報告輸出

testCase包下新建一個文件test_login.py
1、參數(shù)化測試用例:@pytest.mark.parametrize('username, pwd', get_yamlData(testcase_path+r'\loginData.yaml'))
2、優(yōu)化測試報告:
標(biāo)題level: ---------------------測試步驟:
@allure.epic() -----------------with allure.step(’ ‘):
@allure.feature()--------------
@allure.story()
@allure.title()
測試報告輸出:標(biāo)紅的部分
pytest.main([‘test_login.py’, '--alluredir', reports_path, '--clean-alluredir'])
os.system(f'allure serve {reports_path}')
3、測試報告版本展示:
在reports/tmp下新建一個文件:environment.properties文件,也就是在你生成報告的路徑下新建這個文件
里面填寫你測試軟件平臺的版本信息,豐富allure測試報告的展示

Browser=Chromium
Browser.Version=21.1.18
Stand=test
python.Version=3.9.2
allure.version=2.13.3

pytest測試代碼如下:

import os, pytest, allure
from utils.handle_yaml import get_yamlData
from pageObjcets.loginPage import LoginPage
from utils.handle_path import testcase_path, reports_path
loginData = f"{testcase_path}/login_cases.yaml"

@allure.epic('登錄模塊test')
@allure.story('登錄模塊test')
class TestLogin:  # 測試類
    @pytest.mark.parametrize('username, pwd',
                             get_case_yaml(loginData)[0])
    @allure.title('登錄成功case')
    def test_login(self, username, pwd):
    	#第一步:輸入賬戶密碼登錄
        with allure.step('輸入賬戶密碼執(zhí)行登錄'):
            # 1/登錄
            homepage = LoginPage().to_loginPage().login(username, pwd)
            # 2/登錄是否成功,斷言四否具有首頁元素。assert斷言失敗后就無法繼續(xù)執(zhí)行。
            # assert homepage.element_is_presence(homepage.home_button)
            # 2/解決方案:assume斷言失敗后可以繼續(xù)執(zhí)行下一步,有時間也需要反向的用例測試失敗可以繼續(xù)下一步執(zhí)行
        # 第2步:驗(yàn)證登錄成功
        with allure.step('驗(yàn)證登錄是否成功'):
            pytest.assume(
                homepage.element_is_presence(
                    homepage.home_button,
                    action='登錄后驗(yàn)證首頁'))
        # 第3步:退出返回到登錄頁面,方便后續(xù)的反向用例執(zhí)行
        with allure.step('退出返回到登錄頁面'):
            # 3/做完登錄退回到登錄頁面
            homepage.to_login_page(action='退出登錄')


if __name__ == '__main__':
    pytest.main(['-sq', 'test_login.py', '--alluredir', reports_path, '--clean-alluredir'])
    os.system(f'allure serve  {reports_path}')

驗(yàn)證首頁元素,需要先在projectPage頁新建一個homePage.py文件,因?yàn)槭醉摬粚儆诘卿涰?,需要寫在首頁中?/p>

 # 點(diǎn)擊回到首頁
def homepage(self):
    self.click(self.home_button, '點(diǎn)擊首頁')    

homepage.element_is_presence(homepage.home_button,action='登錄后驗(yàn)證首頁'))中的home_button即是首頁元素。

反向用例處理:
測試反向用例若使用assert,斷言失敗就無法繼續(xù)執(zhí)行:
引入新的插件:assume
需要安裝pytest-assume庫,在pycharm終端使用命令安裝:

pip3 install pytest-assume

ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
引自:https://blog.csdn.net/weixin_50829653/article/details/113179401
反向用例準(zhǔn)備好了,在test_login.py再封裝一個函數(shù)處理反向測試場景:
1、在locator.yaml準(zhǔn)備好相應(yīng)的登錄失敗的提示文本的元素定位:
ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
2、編寫處理反向用例代碼

    # 執(zhí)行反向用例,登錄失敗的場景
    @pytest.mark.parametrize('locator, expected, username, password',
                             get_case_yaml(loginData)[1])
    # @pytest.mark.skip(reason='先不跑')
    @allure.title('登錄失敗用例')
    def test_loginerr(self, locator, expected, username, password):
        with allure.step('執(zhí)行登錄'):
            homepage = LoginPage().login_page()
            homepage.login(username, password)

        with allure.step('斷言登錄失敗提示'):
            pytest.assume(homepage.get_text(locator) == expected)
            # homepage.get_screenshot('報錯截圖')

四個參數(shù)分別對應(yīng)用例中的定位元素(locator),期望結(jié)果(expected),賬號和密碼
通過BasePage的get_text方法獲取登錄失敗提示文本信息,與期望對比,這里使用assert也行,建議使用assume,不然失敗了就停止測試了。
通過裝飾器mark.skip()選擇是否跑反向用例

最后合起來的pytest執(zhí)行腳本:

import os, pytest, allure
from utils.handle_yaml import get_yamlData
from pageObjcets.loginPage import LoginPage
from utils.handle_path import testcase_path, reports_path
loginData = f"{testcase_path}/login_cases.yaml"

@allure.epic('登錄模塊test')
@allure.story('登錄模塊test')
class TestLogin:  # 測試類
    @pytest.mark.parametrize('username, pwd',
                             get_case_yaml(loginData)[0])
    @allure.title('登錄成功case')
    def test_login(self, username, pwd):
    	#第一步:輸入賬戶密碼登錄
        with allure.step(' 1、輸入賬戶密碼執(zhí)行登錄'):
            # 1/登錄
            homepage = LoginPage().to_loginPage().login(username, pwd)
            # 2/登錄是否成功,斷言四否具有首頁元素。assert斷言失敗后就無法繼續(xù)執(zhí)行。
            # assert homepage.element_is_presence(homepage.home_button)
            # 2/解決方案:assume斷言失敗后可以繼續(xù)執(zhí)行下一步,有時間也需要反向的用例測試失敗可以繼續(xù)下一步執(zhí)行
        # 第2步:驗(yàn)證登錄成功
        with allure.step('2 、驗(yàn)證登錄是否成功'):
            pytest.assume(
                homepage.element_is_presence(
                    homepage.home_button,
                    action='登錄后驗(yàn)證首頁'))
        # 第3步:退出返回到登錄頁面,方便后續(xù)的反向用例執(zhí)行
        with allure.step(' 3、退出返回到登錄頁面'):
            # 3/做完登錄退回到登錄頁面
            homepage.to_login_page(action='退出登錄')

    # 執(zhí)行反向用例,登錄失敗的場景
    @pytest.mark.parametrize('locator, expected, username, password',
                             get_case_yaml(loginData)[1])
    # @pytest.mark.skip(reason='先不跑')
    @allure.title('登錄失敗用例')
    def test_loginerr(self, locator, expected, username, password):
        with allure.step('1、執(zhí)行登錄'):
            homepage = LoginPage().login_page()
            homepage.login(username, password)
        with allure.step('2、斷言登錄失敗提示'):
            pytest.assume(homepage.get_text(locator) == expected)
            # homepage.get_screenshot('報錯截圖')


if __name__ == '__main__':
    pytest.main(['-sq', 'test_login.py', '--alluredir', reports_path, '--clean-alluredir'])
    os.system(f'allure serve  {reports_path}')

8、PO模式結(jié)合fixture的數(shù)據(jù)清除與格式化

testCase包下新建一個conftest.py注:命名必須為conftest.py, pytest的規(guī)則命名。只有conftest才能識別


"""
scope指的是fixture的作用域:
      4種:
          function(函數(shù))<class(類)<module(模塊級別)<session(包)
auto
    1、手動調(diào)用執(zhí)行
    2、自動執(zhí)行
"""
import pytest
from time import sleep
from common.myDriver import Driver

@pytest.fixture(scope='session', autouse=True)
def start_running():
    print("------開始運(yùn)行UI自動化測試-----")
    yield
    # 自動化完成之后,關(guān)閉瀏覽器進(jìn)程
    sleep(3)    #避免瀏覽器關(guān)閉太快,最后一部操作了但響應(yīng)時間時瀏覽器關(guān)閉太快導(dǎo)致問題。
    Driver().get_driver().quit()
    print("-----結(jié)束-UI自動化測試-----")

--------------------**注**--------------------------
1、sleep(3)是為了保證關(guān)閉退出瀏覽器過快而報錯。有時候最后一步執(zhí)行操作未完成就關(guān)閉了瀏覽器。
2、關(guān)于數(shù)據(jù)清除:例如在增加設(shè)置或者新增數(shù)據(jù)時,保證不改變別人的數(shù)據(jù),我們只刪除自己的數(shù)據(jù),一般處理代碼放在執(zhí)行完成測試后:以下非登錄模塊的數(shù)據(jù)清除代碼。刪除代碼編寫在page模塊中調(diào)用。

 # 1、測試完畢刪除測試數(shù)據(jù)
    homepage.to_product_list().delete_first_product()
    # 2、回到首頁方便后續(xù)執(zhí)行測試
    homepage.to_home_page()

放置位置如下:
ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
本地一鍵執(zhí)行所有測試模塊
run.bat的創(chuàng)建:
本地項目的路徑下創(chuàng)建一個run.bat文件
ui自動化框架封裝,seleniumUI自動化,web UI自動化測試,selenium,自動化,測試工具
在文件內(nèi)使用如下:
cd到測試路徑->pytest執(zhí)行所有文件,->輸出allure報告

cd ./testCase_polly
pytest -sv --alluredir ./outFiles/reports/tmp --clean-alluredir
allure serve ./outFiles/reports/tmp

操作匯總

1:需要主要的是操作導(dǎo)致刷新頁面需要重新獲取定位元素,否則會失效
2:若操作會導(dǎo)致切換頁面,需要加一定強(qiáng)制等待sleep(3),不然很容易導(dǎo)致定位報錯或者定位不到
3:conftest 的fixture配置退出瀏覽器或者結(jié)束關(guān)閉瀏覽器需要強(qiáng)制等待sleep(5),不然最后一步的執(zhí)行可能會報錯文章來源地址http://www.zghlxwxcb.cn/news/detail-757975.html

到了這里,關(guān)于selenium UI自動化PO模式測試框架搭建的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • UI 自動化測試框架:PO 模式+數(shù)據(jù)驅(qū)動 【詳解版】

    UI 自動化測試框架:PO 模式+數(shù)據(jù)驅(qū)動 【詳解版】

    什么是 PO 模式? PO(PageObject)設(shè)計模式將某個頁面的所有元素對象定位和對元素對象的操作封裝成一個 Page 類,并以頁面為單位來寫測試用例,實(shí)現(xiàn)頁面對象和測試用例的分離。 PO 模式的設(shè)計思想與面向?qū)ο笙嗨?,能讓測試代碼變得可讀性更好,可維護(hù)性高,復(fù)用性高。

    2024年02月04日
    瀏覽(92)
  • Selenium Web自動化測試——基于unittest框架的PO設(shè)計模式

    Selenium Web自動化測試——基于unittest框架的PO設(shè)計模式

    ??? 交流討論: 歡迎加入我們一起學(xué)習(xí)! ?? 資源分享 : 耗時200+小時精選的「軟件測試」資料包 ??? 教程推薦: 火遍全網(wǎng)的《軟件測試》教程?? ?? 歡迎點(diǎn)贊 ?? 收藏 ?留言 ?? 如有錯誤敬請指正! 前面一直在講接口自動化測試框架與案例分享,很少講Selenium這個We

    2024年03月21日
    瀏覽(92)
  • Selenium自動化測試設(shè)計模式-PO模式

    Selenium自動化測試設(shè)計模式-PO模式

    在python自動化過程中,Selenium自動化測試中有一個名字常常被提及PageObject(思想與面向?qū)ο蟮奶匦韵嗤?,通過PO模式可以大大提高測試用例的維護(hù)效率。 不了解po設(shè)計模式的可自行百度 面向?qū)ο蟮奶匦?:封裝、繼承、多態(tài) 傳統(tǒng)測試腳本的弊端: 測試腳本分離,維護(hù)成本高

    2023年04月08日
    瀏覽(88)
  • Selenium基于Python web自動化測試框架 -- PO

    Selenium基于Python web自動化測試框架 -- PO

    ??? 交流討論: 歡迎加入我們一起學(xué)習(xí)! ?? 資源分享 : 耗時200+小時精選的「軟件測試」資料包 ??? 教程推薦: 火遍全網(wǎng)的《軟件測試》教程?? ?? 歡迎點(diǎn)贊 ?? 收藏 ?留言 ?? 如有錯誤敬請指正! 關(guān)于selenium測試框架首先想到的就是PO模型,簡單說下PO模型 PO模型的

    2024年02月22日
    瀏覽(26)
  • 如何搭建自動化測試框架?資深測試整理的PO模式,一套打通自動化...

    如何搭建自動化測試框架?資深測試整理的PO模式,一套打通自動化...

    Po模型介紹 1、簡介 在自動化中,Selenium自動化測試中有一個名字經(jīng)常被提及PageObject(思想與面向?qū)ο蟮奶卣飨嗤?,通常PO模型可以大大提高測試用例的維護(hù)效率 2、為什么要用PO 基于selenium2開始ui自動化測試腳本的編寫不是多么艱巨的任務(wù)。只需要定位到元素,執(zhí)行對應(yīng)元素的

    2024年02月13日
    瀏覽(98)
  • PO設(shè)計模式是selenium自動化測試中最佳的設(shè)計模式之一

    PO設(shè)計模式是selenium自動化測試中最佳的設(shè)計模式之一

    Page Object Model:PO設(shè)計模式是selenium自動化測試中最佳的設(shè)計模式之一,主要體現(xiàn)在對界面交互細(xì)節(jié)的封裝,也就是在實(shí)際測試中只關(guān)注業(yè)務(wù)流程就OK了傳統(tǒng)的設(shè)計中,在新增測試用例之后,代碼會有以下幾個問題:1.易讀性差:一連串的find element會使代碼顯得雜亂無章2.可擴(kuò)展

    2024年02月11日
    瀏覽(88)
  • 微信小程序自動化測試框架 Minium——PO模式測試用例

    微信小程序自動化測試框架 Minium——PO模式測試用例

    本文主要介紹PO模式的測試用例,PO模式優(yōu)點(diǎn)及層級間的關(guān)系,相關(guān)配置及運(yùn)行 minitest的測試小程序和測試case:minitest-demo miniprogram-demo :測試小程序 testcase :測試case,同時也包含文檔的測試case testcase-PO :Page Object(PO) 模式的測試case PO模式是自動化測試項目開發(fā)實(shí)踐的最佳設(shè)

    2024年02月07日
    瀏覽(110)
  • 讓自動化測試秒殺繁瑣操作?試試PO模式設(shè)計框架

    讓自動化測試秒殺繁瑣操作?試試PO模式設(shè)計框架

    目錄:導(dǎo)讀 引言 po模式 優(yōu)勢: ?目錄解釋: 頁面對象設(shè)計模式: base基礎(chǔ)層: page對象層: ?test:測試層 data數(shù)據(jù)層: ?common層: ?untils: ?config層: run層: report: 結(jié)語 你是否曾經(jīng)因?yàn)槊看胃鹿δ芏家匦聦懸欢炎詣踊瘻y試代碼而感到疲憊不堪? 或者因?yàn)轫撁嬖氐念l繁變

    2024年02月02日
    瀏覽(100)
  • 多測師肖sir___ui自動化測試po框架(升級)

    多測師肖sir___ui自動化測試po框架(升級)

    ui自動化測試po框架(升級) po框架 一、ui自動化po框架介紹 (1)PO是Page Object的縮寫(pom模型) (2)業(yè)務(wù)流程與頁面元素操作分離的模式,可以簡單理解為每個頁面下面都有一個配置class, 配置class就用來維護(hù)頁面元素或操作方法 (3)提高測試用例的可維護(hù)性、可讀取性

    2024年01月19日
    瀏覽(98)
  • 多測師肖sir___ui自動化測試po框架講解版

    多測師肖sir___ui自動化測試po框架講解版

    po框架 一、ui自動化po框架介紹 (1)PO是Page Object的縮寫(pom模型) (2)業(yè)務(wù)流程與頁面元素操作分離的模式,可以簡單理解為每個頁面下面都有一個配置class, 配置class就用來維護(hù)頁面元素或操作方法 (3)提高測試用例的可維護(hù)性、可讀取性 對比:傳統(tǒng)的設(shè)計測試用例存

    2024年02月02日
    瀏覽(92)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包