You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
10 KiB
Python

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import json
import re
from datetime import datetime
from PyQt5.QtCore import Qt, QTimer, QAbstractTableModel, QModelIndex, QPoint, QSize
from PyQt5.QtGui import QFont, QBrush, QColor
from openpyxl import load_workbook
class ExcelParser:
@staticmethod
def parseProcedure(filePath):
wb = load_workbook(filename=filePath)
if '测试脚本' in wb.sheetnames:
sheet = wb['测试脚本']
else:
sheet = wb.active
specInfo = {
"规程名称": sheet['B1'].value or "",
"规程编号": sheet['D1'].value or "",
"规程类型": sheet['F1'].value or ""
}
testCaseInfo = {
"测试用例": sheet['B2'].value or "",
"用例编号": sheet['D2'].value or "",
"工况描述": sheet['H2'].value or ""
}
testSteps = []
currentStep = None
stepCounter = 0
for rowIdx in range(5, sheet.max_row + 1):
cellA = sheet[f'A{rowIdx}'].value
cellB = sheet[f'B{rowIdx}'].value
cellC = sheet[f'C{rowIdx}'].value
if cellB is None and cellA is None:
continue
if cellA and re.match(r'STEP\d+[:]', str(cellA)):
if currentStep:
testSteps.append(currentStep)
stepCounter += 1
stepName = str(cellA).replace('', ':').strip()
stepDesc = str(cellB) if cellB else ""
currentStep = {
"步骤ID": stepName,
"步骤描述": stepDesc,
"操作类型": cellC if cellC else "",
"预期结果": sheet[f'D{rowIdx}'].value,
"子步骤": []
}
elif currentStep and cellA and str(cellA).isdigit():
subStep = {
"序号": int(cellA),
"操作": str(cellB) if cellB else "",
"操作类型": cellC if cellC else "",
"预期结果": sheet[f'D{rowIdx}'].value,
"实际结果": sheet[f'E{rowIdx}'].value,
"一致性": sheet[f'F{rowIdx}'].value if sheet[f'F{rowIdx}'].value == "" else "",
"测试时间": sheet[f'H{rowIdx}'].value,
"备注": sheet[f'I{rowIdx}'].value
}
currentStep["子步骤"].append(subStep)
if currentStep:
testSteps.append(currentStep)
return {
"文件路径": filePath,
"规程信息": {
"规程名称": specInfo["规程名称"],
"规程编号": specInfo["规程编号"],
"规程类型": specInfo["规程类型"]
},
"测试用例信息": {
"测试用例": testCaseInfo["测试用例"],
"用例编号": testCaseInfo["用例编号"],
"工况描述": testCaseInfo["工况描述"]
},
"测试步骤": testSteps
}
class StepTableModel(QAbstractTableModel):
columns = ['序号', '实验步骤','操作类型', '执行时间', '是否与预期一致', '实际结果', '备注']
def __init__(self, testSteps):
super().__init__()
self.stepData = []
self.stepIndex = 0
for mainStep in testSteps:
self.stepData.append({
'id': self.stepIndex,
'isMain': True,
'stepId': mainStep['步骤ID'],
'description': mainStep['步骤描述'],
'executed': False,
'stepType': mainStep['操作类型'],
'time': None,
'result': None,
'note': mainStep.get('备注', '') # 修复:从主步骤的备注字段读取
})
self.stepIndex += 1
for subStep in mainStep['子步骤']:
self.stepData.append({
'id': self.stepIndex,
'isMain': False,
'stepId': f"{mainStep['步骤ID']}{subStep['序号']}",
'description': subStep['操作'],
'stepType': subStep['操作类型'],
'executed': False,
'time': None,
'result': None,
'note': subStep['备注'] # 新增从Excel解析的备注字段
})
self.stepIndex += 1
def rowCount(self, parent=QModelIndex()):
return len(self.stepData)
def columnCount(self, parent=QModelIndex()):
return len(self.columns)
def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return None
row = index.row()
col = index.column()
step = self.stepData[row]
if role == Qt.DisplayRole:
if col == 0:
return step['stepId'] or ''
elif col == 1:
return step['description'] or ''
elif col == 2:
return step['stepType'] or ''
elif col == 3:
return step['time'].strftime("%Y-%m-%d %H:%M:%S") if step['time'] else ''
elif col == 4:
# print(step['result'])
if step['executed']:
if '失败' in step['result']:
return ''
else:
return ''
elif col == 5:
# print(step['result'])
return step['result'] or ''
elif col == 6:
return step['note'] if step['note'] else ''
elif role == Qt.BackgroundRole:
if step['executed']:
if '失败' in step['result']:
return QBrush(QColor(255, 182, 193))
else:
return QBrush(QColor(144, 238, 144))
elif step['isMain']:
return QBrush(QColor(220, 220, 220))
elif role == Qt.FontRole and step['isMain']:
font = QFont()
font.setBold(True)
return font
# 新增:支持自动换行
elif role == Qt.TextAlignmentRole:
if col in [1, 5]: # 描述和备注列
return Qt.AlignLeft | Qt.AlignVCenter
elif role == Qt.TextWordWrap:
if col in [1, 5]:
return True
return None
def flags(self, index):
"""返回单元格标志"""
flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
return flags
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self.columns[section]
return None
def getStepInfo(self, row):
if 0 <= row < len(self.stepData):
return self.stepData[row]
return None
def getFullStepInfo(self, row):
"""获取完整的步骤信息"""
if 0 <= row < len(self.stepData):
return self.stepData[row]
return None
def updateStepResult(self, row, result, time):
if 0 <= row < len(self.stepData):
# print(result)
self.stepData[row]['executed'] = True
self.stepData[row]['time'] = time
self.stepData[row]['result'] = result
self.dataChanged.emit(self.index(row, 0),
self.index(row, self.columnCount()-1),
[Qt.DisplayRole, Qt.BackgroundRole])
return True
return False
def resetExecutionState(self):
"""只重置执行状态(颜色),不清除时间和结果"""
for step in self.stepData:
step['executed'] = False
step['result'] = None
self.dataChanged.emit(self.index(0, 0),
self.index(self.rowCount()-1, self.columnCount()-1),
[Qt.BackgroundRole])
def resetAll(self):
"""完全重置所有状态(包括时间和结果)"""
for step in self.stepData:
step.update({
'executed': False,
'time': None,
'result': None
})
self.dataChanged.emit(self.index(0, 0),
self.index(self.rowCount()-1, self.columnCount()-1),
[Qt.DisplayRole, Qt.BackgroundRole])
def getTestSteps(self):
"""获取测试步骤数据,用于保存"""
testSteps = []
currentMainStep = None
for step in self.stepData:
if step['isMain']:
# 如果有前一个主步骤,先添加到结果中
if currentMainStep:
testSteps.append(currentMainStep)
# 创建新的主步骤
currentMainStep = {
'步骤ID': step['stepId'],
'步骤描述': step['description'],
'操作类型': step['stepType'],
'预期结果': '',
'子步骤': []
}
else:
# 子步骤
if currentMainStep:
# 从步骤ID中提取序号
stepId = step['stepId']
if currentMainStep['步骤ID'] in stepId:
subStepId = stepId.replace(currentMainStep['步骤ID'], '')
else:
subStepId = stepId
subStep = {
'序号': subStepId,
'操作': step['description'],
'操作类型': step['stepType'],
'预期结果': '',
'实际结果': step.get('result', ''),
'一致性': '' if step.get('result') and '失败' not in step.get('result', '') else '',
'测试时间': step.get('time', ''),
'备注': step.get('note', '')
}
currentMainStep['子步骤'].append(subStep)
# 添加最后一个主步骤
if currentMainStep:
testSteps.append(currentMainStep)
return testSteps