|
|
|
|
|
|
|
|
|
from PyQt5 import QtCore
|
|
|
|
|
from PyQt5.QtWidgets import QHeaderView, QStyle, QStyleOptionButton, QTableView, QAbstractItemView, QDesktopWidget
|
|
|
|
|
from PyQt5.QtCore import (pyqtSignal, Qt, QRect)
|
|
|
|
|
from PyQt5.QtCore import Qt, QTimer, QAbstractTableModel, QModelIndex, QPoint, QSize
|
|
|
|
|
from PyQt5.QtGui import QFont, QBrush, QColor
|
|
|
|
|
|
|
|
|
|
from PyQt5.QtWidgets import QTableView, QStyledItemDelegate
|
|
|
|
|
from utils import Globals
|
|
|
|
|
|
|
|
|
|
class BackgroundDelegate(QStyledItemDelegate):
|
|
|
|
|
def __init__(self, *args):
|
|
|
|
|
super(BackgroundDelegate, self).__init__(*args)
|
|
|
|
|
self.setObjectName('item')
|
|
|
|
|
|
|
|
|
|
def sizeHint(self, option, index):
|
|
|
|
|
"""设置项目的尺寸提示,确保足够的高度"""
|
|
|
|
|
size = super().sizeHint(option, index)
|
|
|
|
|
size.setHeight(max(46, size.height())) # 最小高度60px
|
|
|
|
|
return size
|
|
|
|
|
|
|
|
|
|
def paint(self, painter, option, index):
|
|
|
|
|
# 确保绘制区域有足够的高度
|
|
|
|
|
if index.data(QtCore.Qt.BackgroundRole):
|
|
|
|
|
height = option.rect.height()
|
|
|
|
|
top = option.rect.top()
|
|
|
|
|
# 减少高度调整,保持更多的绘制区域
|
|
|
|
|
option.rect.setHeight(max(46, height - 4)) # 最小保持56px高度
|
|
|
|
|
option.rect.moveTop(top + 2)
|
|
|
|
|
painter.fillRect(option.rect, index.data(QtCore.Qt.BackgroundRole))
|
|
|
|
|
super().paint(painter, option, index)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ProcedureTabel(QTableView):
|
|
|
|
|
def __init__(self, testSteps, parent=None):
|
|
|
|
|
super(ProcedureTabel, self).__init__(parent)
|
|
|
|
|
self.parent = parent
|
|
|
|
|
self.createTableSection(testSteps)
|
|
|
|
|
self.setupTableHeaders()
|
|
|
|
|
self.delegate = BackgroundDelegate(self)
|
|
|
|
|
self.setItemDelegate(self.delegate)
|
|
|
|
|
self.loadStylesheet()
|
|
|
|
|
|
|
|
|
|
def loadStylesheet(self):
|
|
|
|
|
"""加载表格样式表"""
|
|
|
|
|
try:
|
|
|
|
|
from PyQt5.QtCore import QFile, QTextStream
|
|
|
|
|
qssPath = "Static/ProcedureTable.qss"
|
|
|
|
|
qssFile = QFile(qssPath)
|
|
|
|
|
if qssFile.exists():
|
|
|
|
|
qssFile.open(QFile.ReadOnly | QFile.Text)
|
|
|
|
|
stream = QTextStream(qssFile)
|
|
|
|
|
stream.setCodec("UTF-8")
|
|
|
|
|
self.setStyleSheet(stream.readAll())
|
|
|
|
|
qssFile.close()
|
|
|
|
|
print(f"✅ ProcedureTable成功加载样式表: {qssPath}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"⚠️ ProcedureTable样式表文件不存在: {qssPath}")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"❌ ProcedureTable加载样式表失败: {str(e)}")
|
|
|
|
|
|
|
|
|
|
def createTableSection(self, testSteps):
|
|
|
|
|
"""创建表格区域"""
|
|
|
|
|
self.tableModel = StepTableModel(testSteps)
|
|
|
|
|
self.setModel(self.tableModel)
|
|
|
|
|
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
|
|
|
|
self.customContextMenuRequested.connect(self.parent.showContextMenu)
|
|
|
|
|
|
|
|
|
|
# 设置表格编辑行为
|
|
|
|
|
self.setEditTriggers(QTableView.DoubleClicked)
|
|
|
|
|
|
|
|
|
|
# 设置选择行为为整行选中
|
|
|
|
|
self.setSelectionBehavior(QTableView.SelectRows)
|
|
|
|
|
self.setSelectionMode(QAbstractItemView.SingleSelection) # 单行选择
|
|
|
|
|
|
|
|
|
|
# 设置表格显示优化
|
|
|
|
|
self.setAlternatingRowColors(False) # 交替行颜色
|
|
|
|
|
self.setShowGrid(True) # 显示网格线
|
|
|
|
|
self.setGridStyle(Qt.SolidLine) # 实线网格
|
|
|
|
|
self.setSortingEnabled(False) # 禁用排序避免干扰执行顺序
|
|
|
|
|
|
|
|
|
|
# 启用鼠标跟踪以支持hover效果
|
|
|
|
|
self.setMouseTracking(True)
|
|
|
|
|
|
|
|
|
|
# 设置最小行高
|
|
|
|
|
self.verticalHeader().setMinimumSectionSize(30)
|
|
|
|
|
|
|
|
|
|
self.setupTableHeaders()
|
|
|
|
|
|
|
|
|
|
# 初始调整所有行高
|
|
|
|
|
self.adjustAllRowHeights()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def setupTableHeaders(self):
|
|
|
|
|
"""设置表格头部"""
|
|
|
|
|
try:
|
|
|
|
|
header = self.horizontalHeader()
|
|
|
|
|
if header:
|
|
|
|
|
# 设置表格自动调整行高
|
|
|
|
|
self.verticalHeader().setDefaultSectionSize(35)
|
|
|
|
|
self.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
|
|
|
|
|
self.verticalHeader().hide()
|
|
|
|
|
|
|
|
|
|
# 设置列宽模式 - 让表格填充满整个宽度
|
|
|
|
|
header.setStretchLastSection(True) # 让最后一列自动拉伸填充剩余空间
|
|
|
|
|
|
|
|
|
|
# 设置各列的调整模式
|
|
|
|
|
header.setSectionResizeMode(0, QHeaderView.Fixed) # 步骤ID - 固定宽度
|
|
|
|
|
header.setSectionResizeMode(1, QHeaderView.Stretch) # 步骤描述 - 拉伸
|
|
|
|
|
header.setSectionResizeMode(2, QHeaderView.Fixed) # 操作类型 - 固定宽度
|
|
|
|
|
header.setSectionResizeMode(3, QHeaderView.Fixed) # 执行时间 - 固定宽度
|
|
|
|
|
header.setSectionResizeMode(4, QHeaderView.Fixed) # 执行结果 - 固定宽度
|
|
|
|
|
header.setSectionResizeMode(5, QHeaderView.Stretch) # 详细结果 - 拉伸
|
|
|
|
|
header.setSectionResizeMode(6, QHeaderView.Stretch) # 备注 - 拉伸
|
|
|
|
|
|
|
|
|
|
# 设置固定列的宽度
|
|
|
|
|
self.setColumnWidth(0, 80) # 步骤ID
|
|
|
|
|
self.setColumnWidth(2, 120) # 操作类型
|
|
|
|
|
self.setColumnWidth(3, 160) # 执行时间
|
|
|
|
|
self.setColumnWidth(4, 80) # 执行结果
|
|
|
|
|
|
|
|
|
|
# 设置拉伸列的最小宽度
|
|
|
|
|
header.setMinimumSectionSize(100) # 设置所有列的最小宽度
|
|
|
|
|
|
|
|
|
|
# 启用文本换行
|
|
|
|
|
self.setWordWrap(True)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"设置表格头部时出错: {e}")
|
|
|
|
|
|
|
|
|
|
def adjustRowHeight(self, row):
|
|
|
|
|
"""调整指定行的高度以适应内容"""
|
|
|
|
|
try:
|
|
|
|
|
# 获取该行的内容
|
|
|
|
|
stepInfo = self.tableModel.getStepInfo(row)
|
|
|
|
|
if not stepInfo:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 计算需要的行高,确保所有值都不为None
|
|
|
|
|
description = stepInfo.get('description') or ''
|
|
|
|
|
result = stepInfo.get('result') or ''
|
|
|
|
|
note = stepInfo.get('note') or ''
|
|
|
|
|
|
|
|
|
|
# 确保所有值都是字符串类型
|
|
|
|
|
if not isinstance(description, str):
|
|
|
|
|
description = str(description) if description is not None else ''
|
|
|
|
|
if not isinstance(result, str):
|
|
|
|
|
result = str(result) if result is not None else ''
|
|
|
|
|
if not isinstance(note, str):
|
|
|
|
|
note = str(note) if note is not None else ''
|
|
|
|
|
|
|
|
|
|
# 基于最长文本计算行高
|
|
|
|
|
max_text_length = max(len(description), len(result), len(note))
|
|
|
|
|
|
|
|
|
|
# 基础行高
|
|
|
|
|
base_height = 35
|
|
|
|
|
|
|
|
|
|
# 根据文本长度动态调整
|
|
|
|
|
if max_text_length > 100:
|
|
|
|
|
height = base_height + (max_text_length // 50) * 15
|
|
|
|
|
elif max_text_length > 50:
|
|
|
|
|
height = base_height + 15
|
|
|
|
|
else:
|
|
|
|
|
height = base_height
|
|
|
|
|
|
|
|
|
|
# 设置行高,最大不超过150像素
|
|
|
|
|
height = min(height, 150)
|
|
|
|
|
self.setRowHeight(row, height)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"调整行高时出错: {e}")
|
|
|
|
|
|
|
|
|
|
def adjustAllRowHeights(self):
|
|
|
|
|
"""调整所有行的高度"""
|
|
|
|
|
try:
|
|
|
|
|
if not hasattr(self, 'tableModel') or self.tableModel is None:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
row_count = self.tableModel.rowCount()
|
|
|
|
|
if row_count <= 0:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
for row in range(row_count):
|
|
|
|
|
self.adjustRowHeight(row)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"调整所有行高时出错: {e}")
|
|
|
|
|
|
|
|
|
|
def mouseMoveEvent(self, event):
|
|
|
|
|
"""鼠标移动事件,实现hover效果"""
|
|
|
|
|
super().mouseMoveEvent(event)
|
|
|
|
|
|
|
|
|
|
# 获取鼠标位置对应的行
|
|
|
|
|
index = self.indexAt(event.pos())
|
|
|
|
|
if index.isValid():
|
|
|
|
|
row = index.row()
|
|
|
|
|
if row != self.tableModel.hoverRow:
|
|
|
|
|
# 清除之前的hover行
|
|
|
|
|
oldHoverRow = self.tableModel.hoverRow
|
|
|
|
|
self.tableModel.hoverRow = row
|
|
|
|
|
|
|
|
|
|
# 更新显示
|
|
|
|
|
if oldHoverRow >= 0:
|
|
|
|
|
self.update(self.tableModel.index(oldHoverRow, 0))
|
|
|
|
|
for col in range(self.tableModel.columnCount()):
|
|
|
|
|
self.update(self.tableModel.index(oldHoverRow, col))
|
|
|
|
|
|
|
|
|
|
# 更新新的hover行
|
|
|
|
|
self.update(self.tableModel.index(row, 0))
|
|
|
|
|
for col in range(self.tableModel.columnCount()):
|
|
|
|
|
self.update(self.tableModel.index(row, col))
|
|
|
|
|
else:
|
|
|
|
|
# 鼠标不在任何行上,清除hover效果
|
|
|
|
|
if self.tableModel.hoverRow >= 0:
|
|
|
|
|
oldHoverRow = self.tableModel.hoverRow
|
|
|
|
|
self.tableModel.hoverRow = -1
|
|
|
|
|
self.update(self.tableModel.index(oldHoverRow, 0))
|
|
|
|
|
for col in range(self.tableModel.columnCount()):
|
|
|
|
|
self.update(self.tableModel.index(oldHoverRow, col))
|
|
|
|
|
|
|
|
|
|
def leaveEvent(self, event):
|
|
|
|
|
"""鼠标离开事件,清除hover效果"""
|
|
|
|
|
super().leaveEvent(event)
|
|
|
|
|
if self.tableModel.hoverRow >= 0:
|
|
|
|
|
oldHoverRow = self.tableModel.hoverRow
|
|
|
|
|
self.tableModel.hoverRow = -1
|
|
|
|
|
self.update(self.tableModel.index(oldHoverRow, 0))
|
|
|
|
|
for col in range(self.tableModel.columnCount()):
|
|
|
|
|
self.update(self.tableModel.index(oldHoverRow, col))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class StepTableModel(QAbstractTableModel):
|
|
|
|
|
columns = ['序号', '实验步骤','操作类型', '执行时间', '是否与预期一致', '实际结果', '备注']
|
|
|
|
|
|
|
|
|
|
def __init__(self, testSteps):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.stepData = []
|
|
|
|
|
self.stepIndex = 0
|
|
|
|
|
self.hoverRow = -1 # 添加hover行跟踪
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
# 优先级:执行结果 > hover效果 > 主步骤背景
|
|
|
|
|
if step['executed']:
|
|
|
|
|
if '失败' in step['result']:
|
|
|
|
|
# 失败状态:红色背景
|
|
|
|
|
if row == self.hoverRow:
|
|
|
|
|
return QBrush(QColor(255, 160, 170)) # hover时稍微深一点的红色
|
|
|
|
|
else:
|
|
|
|
|
return QBrush(QColor(255, 182, 193)) # 浅红色
|
|
|
|
|
else:
|
|
|
|
|
# 成功状态:绿色背景
|
|
|
|
|
if row == self.hoverRow:
|
|
|
|
|
return QBrush(QColor(120, 220, 120)) # hover时稍微深一点的绿色
|
|
|
|
|
else:
|
|
|
|
|
return QBrush(QColor(144, 238, 144)) # 浅绿色
|
|
|
|
|
elif row == self.hoverRow:
|
|
|
|
|
# hover效果:浅蓝色背景
|
|
|
|
|
if step['isMain']:
|
|
|
|
|
return QBrush(QColor(200, 200, 230)) # 主步骤hover时的颜色
|
|
|
|
|
else:
|
|
|
|
|
return QBrush(QColor(230, 240, 255)) # 子步骤hover时的颜色
|
|
|
|
|
elif step['isMain']:
|
|
|
|
|
# 主步骤默认背景:浅灰色
|
|
|
|
|
return QBrush(QColor(220, 220, 220))
|
|
|
|
|
|
|
|
|
|
elif role == Qt.TextAlignmentRole:
|
|
|
|
|
if col in [0, 2, 3, 4]: # 步骤ID、操作类型、执行时间、执行结果居中对齐
|
|
|
|
|
return Qt.AlignCenter
|
|
|
|
|
else: # 其他列左对齐并顶部对齐
|
|
|
|
|
return Qt.AlignLeft | Qt.AlignTop
|
|
|
|
|
|
|
|
|
|
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
|