21. 自動化測試框架開發之Excel配置文件的測試用例改造
一、測試框架核心架構
1.1 組件依賴關系
# 核心庫依賴
import unittest # 單元測試框架
import paramunittest # 參數化測試擴展
from chap3.po import * # 頁面對象模型
from file_reader import ExcelReader # Excel數據讀取器# 必須使用的庫版本
# xlrd==1.2.0(支持xlsx格式)
二、Excel數據驅動實現
2.1 數據加載配置
# Excel數據結構示例
# | name | password | assertion | message |
# |--------|----------|------------------------|-----------------------|
# | Tester | test | Invalid Login or Password | test_login_admin passed |data = ExcelReader(r'E:\Py3Sel3Ifram\chap5\Demo.xlsx',sheet=0, # 第一個工作表excel_title=True # 首行為標題
).data
參數說明:
- sheet=0:讀取第一個工作表
- excel_title=True:將首行作為字典鍵
- 文件路徑需使用原始字符串(r前綴)
三、測試用例參數化方案
3.1 使用paramunittest實現(注釋方案)
@paramunittest.parametrized(data[1],data[2],data[3])
class TestOder(unittest.TestCase, Oder):def setParameters(self, name, pwd, ass, txt):"""參數映射方法"""self.name = nameself.pwd = pwdself.ass = assself.txt = txtdef test_login(self):"""測試執行方法"""self.get()self.login(self.name, self.pwd)sleep(2)assert self.element('op.invalid_login').text == self.assprint(self.txt)
方案特點:
- 每個測試用例獨立執行
- 需要明確指定數據索引
- 自動生成多個測試方法
3.2 使用subTest實現(當前方案)
class TestLogin(unittest.TestCase, Oder):def test_login(self):for d in data:with self.subTest(d): # 子測試上下文self.get()self.login(d['name'], d['password'])sleep(2)try:self.assertEqual(self.element('op.invalid_login').text,d['assertion'])except AssertionError:self.driver.save_screenshot(f'./{d["assertion"]}.png')raiseprint(d['message'])
方案優勢:
- 單測試方法管理多組數據
- 失敗時繼續執行后續用例
- 自動生成詳細測試報告
四、關鍵技術點解析
4.1 數據驅動流程
開始
├─ 讀取Excel測試數據
├─ 遍歷數據集合
│ ├─ 初始化瀏覽器
│ ├─ 執行登錄操作
│ ├─ 驗證斷言結果
│ ├─ 成功:輸出日志
│ └─ 失敗:截圖保存
└─ 生成測試報告
4.2 異常處理機制
try:self.assertEqual(actual, expected)
except AssertionError:self.driver.save_screenshot(f'./{d["assertion"]}.png') # 失敗截圖raise # 重新拋出異常
功能特點:
- 精確捕獲斷言失敗
- 自動保存錯誤現場
- 保留原始異常堆棧
五、Excel數據規范要求
5.1 數據結構標準
列名 | 類型 | 說明 |
---|---|---|
name | str | 用戶名輸入 |
password | str | 密碼輸入 |
assertion | str | 預期斷言文本 |
message | str | 測試結果描述 |
5.2 格式注意事項
- 第一行必須為標題行
- 各列順序需與代碼參數對應
- 文本型斷言值需完全匹配
- 避免使用特殊字符作為文件名
六、工程實踐建議
6.1 數據管理策略
# 建議文件結構
testdata/
├─ login/
│ ├─ valid_login.xlsx
│ └─ invalid_login.xlsx
├─ order/
│ └─ create_order.xlsx
6.2 執行效率優化
優化策略 | 實現方式 | 效果預估 |
---|---|---|
瀏覽器復用 | 使用setUpClass/tearDownClass | 減少80%啟動時間 |
智能等待 | 顯式等待替代固定sleep | 提升30%執行速度 |
并行執行 | 使用pytest-xdist插件 | 線性提升效率 |
七、版本兼容性說明
7.1 必須環境配置
# 安裝指定版本庫
pip install xlrd==1.2.0 paramunittest==1.0.2# 版本沖突說明:
# xlrd>=2.0.0 不支持xlsx格式
# paramunittest需要兼容Python3.13
7.2 常見錯誤處理
錯誤現象 | 原因分析 | 解決方案 |
---|---|---|
無法打開xlsx文件 | xlrd版本不正確 | 降級到1.2.0版本 |
參數映射失敗 | Excel列名不匹配 | 檢查標題行命名 |
元素定位超時 | 頁面加載緩慢 | 添加顯式等待機制 |
截圖保存失敗 | 路徑權限問題 | 使用絕對路徑或檢查權限 |
八、完整代碼
"""
Python :3.13.3
Selenium: 4.31.0
"""import unittest
import paramunittest
from time import sleep
from chap3.po import *
from .file_reader import ExcelReader# 處理 collections.Mapping 的兼容性問題
import collectionstry:collections.Mapping
except AttributeError:import collections.abccollections.Mapping = collections.abc.Mapping# 獲取并解析Excel數據
# data = ExcelReader(r'E:\Py3Sel3Ifram\chap5\Demo.xlsx',
# sheet=0,
# excel_title=False).data# @paramunittest.parametrized(data[1],data[2],data[3])
# class TestOder(unittest.TestCase, Oder):
# def setParameters(self, name, pwd, ass, txt):
# self.name = name
# self.pwd = pwd
# self.ass = ass
# self.txt = txt
#
# def test_login(self):
# self.get()
# self.login(self.name, self.pwd)
# sleep(2)
# assert self.element('op.invalid_login').text == self.ass
# print(self.txt)# 獲取并解析Excel數據
data = ExcelReader(r'E:\Py3Sel3Ifram\chap5\Demo.xlsx',sheet=0).data# data = (
# {'name': 'Testerr', 'pwd': 'test', 'ass': 'Invalid Login or Password.', 'txt': 'test_login_admin is passed'},
# {'name': 'Sam', 'pwd': 'test', 'ass': 'Invalid Login or Password.', 'txt': 'test_login_Sam is passed'},
# {'name': 'Tom', 'pwd': 'test', 'ass': 'Invalid Login or Password..', 'txt': 'test_login_Tom is passed'}
# )class TestLogin(unittest.TestCase, Oder):def test_login(self):for d in data:with self.subTest(d):self.get()self.login(d['name'], d['password'])sleep(2)# assert self.element(self.invalid_login).text == d['ass'], \# self.driver.save_screenshot(f'./{d["ass"]}.png')try:self.assertEqual(self.element('op.invalid_login').text, d['assertion'])except AttributeError:self.driver.save_screenshot(f'./{d["assertion"]}.png')raise AssertionErrorprint(d['message'])if __name__ == '__main__':unittest.main()
Excel的數據:
最佳實踐建議:建議將測試數據與測試代碼分離管理,使用獨立的testdata目錄存儲各類測試數據文件。實際項目數據統計顯示,采用數據驅動模式可降低60%的測試維護成本。
「小貼士」:點擊頭像→【關注】按鈕,獲取更多軟件測試的晉升認知不迷路! 🚀