测试工具:
1. 基本界面实现:
# coding:utf-8 import sys import os import os.path import re import time from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4 import Qt msg_file_not_exists = 'Can not find config file' msg_file_is_null = 'There is no attribute now' project_file = 'D:workspacepy_demoproject.py' case_file = 'D:workspacepy_democase.py' case_seprator = '|' def get_time(): return time.strftime("%Y-%m-%d %X", time.localtime(time.time())) def _save_project(project_index, project_info, create_time, edit_time, project_detail): all_lines = [] line_str = str(project_index) + case_seprator + project_info + case_seprator + create_time + case_seprator + edit_time + case_seprator + project_detail + ' ' if os.path.exists(project_file): if os.path.getsize(project_file): with open(project_file, 'r') as f: all_lines = f.readlines() if all_lines[project_index:project_index + 1]: all_lines[project_index] = line_str else: all_lines.append(line_str) else: all_lines.append(line_str) else: all_lines.append(line_str) with open(project_file, 'w') as f: f.writelines(all_lines) def _save_case(project_index, case_index, case_info, create_time, edit_time, start_run_time, finish_run_time, run_type, run_script, run_result): all_lines = [] line_str = str(project_index) + case_seprator + str( case_index) + case_seprator + case_info + case_seprator + create_time + case_seprator + edit_time + case_seprator + start_run_time + case_seprator + finish_run_time + case_seprator + run_type + case_seprator + run_script + case_seprator + run_result + ' ' if os.path.exists(case_file): if os.path.getsize(case_file): with open(case_file, 'r') as f: all_lines = f.readlines() if all_lines[case_index:case_index + 1]: all_lines[case_index] = line_str else: all_lines.append(line_str) else: all_lines.append(line_str) else: all_lines.append(line_str) with open(case_file, 'w') as f: f.writelines(all_lines) class MainWindow(QtGui.QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.setWindowTitle('AutoTest') self.resize(600, 300) self.setTool = self.addToolBar('Set') self.setToolAction = Qt.QAction( QtGui.QIcon('images/open.png'), u'Set', self) self.setToolAction.setShortcut('Ctrl+S') self.setToolAction.setStatusTip(u'Config') self.setToolAction.triggered.connect(self.set_config_file) self.setTool.addAction(self.setToolAction) self.newProjectTool = self.addToolBar('NewProject') self.newProjectToolAction = Qt.QAction( QtGui.QIcon('images/selectall.png'), u'CreateProject', self) self.newProjectToolAction.triggered.connect(self.newproject) self.newProjectTool.addAction(self.newProjectToolAction) self.newCaseTool = self.addToolBar('NewCase') self.newCaseToolAction = Qt.QAction( QtGui.QIcon('images/copy.png'), u'CreateCase', self) self.newCaseToolAction.triggered.connect(self.newcase) self.newCaseTool.addAction(self.newCaseToolAction) wedgit = QtGui.QWidget() layout = QtGui.QVBoxLayout() self.tree = QtGui.QTreeWidget() self.tree.setColumnCount(4) self.tree.setHeaderLabels(['Step', 'Start Time','Finish Time','Result']) # self.tree.headerItem().setStretchLastSection(True) self.load_case() self.tree.itemChanged.connect(self.save_project) self.tree.itemDoubleClicked.connect(self.edit_project) # self.tree.setExpanded(0,True) self.log_text = QtGui.QTextBrowser() layout.addWidget(self.tree) layout.addWidget(self.log_text) wedgit.setLayout(layout) self.setCentralWidget(wedgit) def set_config_file(self): self.dialog = config_file() self.dialog.show() def load_case(self): if os.path.exists(project_file): if os.path.getsize(project_file): with open(project_file, 'r') as f: all_lines = f.readlines() for i, line in enumerate(all_lines): project_text = line.split(case_seprator)[1] self.project = QtGui.QTreeWidgetItem(self.tree) self.tree.setItemExpanded(self.project, True) # 设置自动扩展 self.tree.addTopLevelItem(self.project) self.project.setText(0, project_text) project_no = line.split(case_seprator)[0] if os.path.exists(case_file): if os.path.getsize(case_file): with open(case_file, 'r') as f: case_all_line = f.readlines() for i, line in enumerate(case_all_line): case_project_no = line.split( case_seprator)[0] if case_project_no == project_no: case_name = line.split( case_seprator)[1] case_result = line.split( case_seprator)[2] self.case = QtGui.QTreeWidgetItem( self.project) self.case.setText(0, case_name) self.case.setText(0, case_result) def newproject(self): self.tree.blockSignals(True) # 禁止itemchanged信号 self.project = QtGui.QTreeWidgetItem(self.tree) self.tree.addTopLevelItem(self.project) self.project.setFlags(self.project.flags() | QtCore.Qt.ItemIsEditable) self.project.setText(0, 'Here is project information') self.tree.blockSignals(False) self.save_project(self.project, 0) def newcase(self): self.tree.blockSignals(True) check_index = self.tree.indexOfTopLevelItem(self.tree.currentItem()) if check_index > -1: self.project = self.tree.currentItem() else: self.project = self.tree.currentItem().parent() self.case = QtGui.QTreeWidgetItem(self.project) self.case.setFlags(self.project.flags() | QtCore.Qt.ItemIsEditable) self.case.setText(0, 'Here is case name') self.case.setCheckState(0, QtCore.Qt.Unchecked) self.project.addChild(self.case) self.tree.blockSignals(False) self.save_project(self.case, 0) def save_case(self, item, column): print 'item text', item.text(column) print 'index', self.tree.indexFromItem(item).row() print 'parent text', item.parent().text(0) def save_project(self, item, column): check_index = self.tree.indexOfTopLevelItem(item) if check_index > -1: project_index = check_index project_info = str(item.text(column)) create_time = get_time() edit_time = get_time() _save_project(project_index, project_info, create_time, edit_time, '') else: project_index = self.tree.indexOfTopLevelItem(item.parent()) case_index = self.tree.indexFromItem(item).row() case_info = str(item.text(column)) # case_index.data() create_time=get_time() edit_time=get_time() _save_case(project_index, case_index, case_info,create_time,edit_time,'','','','','') print 'index', project_index print 'text', item.text(0) print 'column', column def edit_project(self,item,column): current_index = self.tree.indexOfTopLevelItem(item) print current_index if current_index > -1: project_dialog = project(None,current_index) project_dialog.exec_() if project_dialog.reply == QtGui.QMessageBox.Yes: #窗口之间传值 project_title = project_dialog.get_project_title() item.setText(0,project_title) else: project_index = self.tree.indexOfTopLevelItem(item.parent()) case_index = self.tree.indexFromItem(item).row() case_dialog = case(None,project_index,case_index) case_dialog.exec_() if case_dialog.reply == QtGui.QMessageBox.Yes: case_title = case_dialog.get_case_title() item.setText(0,case_title) class case(QtGui.QDialog): def __init__(self, parent, project_index, case_index): super(case, self).__init__(parent) self.project_index = project_index self.case_index = case_index self.setWindowTitle('Case') self.resize(500, 300) self.setup_ui() self.update_flag = False def closeEvent(self, event): if self.update_flag: self.reply = QtGui.QMessageBox.question( self, 'Warning', 'Some content was changed,save?', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if self.reply == QtGui.QMessageBox.No: # event.ignore() # 选择No直接关闭窗口,event.ignore表示保留原窗口 pass else: case_edit_time = get_time() case_title = self.case_title_edit_line.text() _save_case(self.project_index, int(self.caseNo), self.case_title_edit_line.text( ), self.case_create_time, case_edit_time,'','',self.case_run_type_edit_line.currentText (),'','pending run') def set_update_flag(self): self.update_flag = True def get_case_title(self): return self.case_title_edit_line.text() def setup_ui(self): all_lines=[] with open(case_file, 'r') as f: for line in f.readlines(): if int(line.split(case_seprator)[0]) == int(self.project_index): all_lines.append(line) case_info = all_lines[self.case_index] self.caseNo = case_info.split(case_seprator)[1] case_title = case_info.split(case_seprator)[2] self.case_create_time = case_info.split(case_seprator)[3] case_edit_time = case_info.split(case_seprator)[4] case_start_time = case_info.split(case_seprator)[5] case_finish_time = case_info.split(case_seprator)[6] case_run_type = case_info.split(case_seprator)[7] case_run_script = case_info.split(case_seprator)[8] case_run_result = case_info.split(case_seprator)[9] mainlayout = QtGui.QVBoxLayout() layout1 = QtGui.QHBoxLayout() self.case_number_label = QtGui.QLabel('No:') self.case_number_read_line = QtGui.QLabel(self.caseNo) self.case_number_label.setBuddy(self.case_number_read_line) layout1.addWidget(self.case_number_label) layout1.addWidget(self.case_number_read_line) layout1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layout2 = QtGui.QHBoxLayout() self.case_title_label = QtGui.QLabel('Title:') self.case_title_edit_line = QtGui.QLineEdit(case_title) self.case_title_label.setBuddy(self.case_title_edit_line) layout2.addWidget(self.case_title_label) layout2.addWidget(self.case_title_edit_line) layout2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) self.case_title_edit_line.textChanged.connect(self.set_update_flag) layout3 = QtGui.QHBoxLayout() self.case_create_time_label = QtGui.QLabel('CreateTime:') self.case_create_time_read_line = QtGui.QLabel( self.case_create_time) self.case_create_time_label.setBuddy( self.case_create_time_read_line) layout3.addWidget(self.case_create_time_label) layout3.addWidget(self.case_create_time_read_line) layout3.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layout4 = QtGui.QHBoxLayout() self.case_edit_time_label = QtGui.QLabel('EditTime:') self.case_edit_time_read_line = QtGui.QLabel(case_edit_time) self.case_edit_time_label.setBuddy(self.case_edit_time_read_line) layout4.addWidget(self.case_edit_time_label) layout4.addWidget(self.case_edit_time_read_line) layout4.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layout5 = QtGui.QHBoxLayout() self.case_start_time_label = QtGui.QLabel('Start Run Time:') self.case_start_time_read_line = QtGui.QLineEdit(case_start_time) self.case_start_time_label.setBuddy(self.case_start_time_read_line) layout5.addWidget(self.case_start_time_label) layout5.addWidget(self.case_start_time_read_line) layout5.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layout6 = QtGui.QHBoxLayout() self.case_finish_time_label = QtGui.QLabel('Finish Run Time:') self.case_finish_time_read_line = QtGui.QLineEdit(case_finish_time) self.case_finish_time_label.setBuddy(self.case_finish_time_read_line) layout6.addWidget(self.case_finish_time_label) layout6.addWidget(self.case_finish_time_read_line) layout6.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layout7 = QtGui.QHBoxLayout() self.case_run_type_label = QtGui.QLabel('Run Type:') self.case_run_type_edit_line = QtGui.QComboBox(self) self.case_run_type_edit_line.addItems(['Shell','Python']) self.case_run_type_label.setBuddy(self.case_run_type_edit_line) layout7.addWidget(self.case_run_type_label) layout7.addWidget(self.case_run_type_edit_line) layout7.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layout8 = QtGui.QHBoxLayout() self.case_run_script_label = QtGui.QLabel('Run Script:') self.case_run_script_edit_line = QtGui.QTextEdit(case_run_script) self.case_run_script_label.setBuddy(self.case_run_script_edit_line) layout8.addWidget(self.case_run_script_label) layout8.addWidget(self.case_run_script_edit_line) layout8.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layout9 = QtGui.QHBoxLayout() self.case_run_result_label = QtGui.QLabel('Run Result:') self.case_run_result_read_line = QtGui.QLineEdit(case_run_result) self.case_run_result_label.setBuddy(self.case_run_result_read_line) layout9.addWidget(self.case_run_result_label) layout9.addWidget(self.case_run_result_read_line) layout9.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) mainlayout.addLayout(layout1) mainlayout.addLayout(layout2) mainlayout.addLayout(layout3) mainlayout.addLayout(layout4) mainlayout.addLayout(layout5) mainlayout.addLayout(layout6) mainlayout.addLayout(layout7) mainlayout.addLayout(layout8) mainlayout.addLayout(layout9) self.setLayout(mainlayout) class project(QtGui.QDialog): def __init__(self, parent,project_index): super(project, self).__init__(parent) self.project_index = project_index self.setWindowTitle('Project') self.resize(500, 300) self.setup_ui() self.update_flag = False def closeEvent(self, event): if self.update_flag: self.reply = QtGui.QMessageBox.question( self, 'Warning', 'Some content was changed,save?', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if self.reply == QtGui.QMessageBox.No: event.accept() # 选择No直接关闭窗口,event.ignore表示保留原窗口 else: edit_time = get_time() project_title = self.project_title_edit_line.text() _save_project(int(self.projectNo), self.project_title_edit_line.text( ), self.project_create_time, edit_time, self.project_detail_edit_line.toPlainText()) def set_update_flag(self): self.update_flag = True def get_project_title(self): return self.project_title_edit_line.text() def setup_ui(self): with open(project_file, 'r') as f: all_lines = f.readlines() project_info = all_lines[self.project_index] self.projectNo = project_info.split(case_seprator)[0] project_title = project_info.split(case_seprator)[1] self.project_create_time = project_info.split(case_seprator)[2] project_edit_time = project_info.split(case_seprator)[3] project_detail = project_info.split(case_seprator)[4] mainlayout = QtGui.QVBoxLayout() layout1 = QtGui.QHBoxLayout() self.project_number_label = QtGui.QLabel('No:') self.project_number_read_line = QtGui.QLabel(self.projectNo) self.project_number_label.setBuddy(self.project_number_read_line) layout1.addWidget(self.project_number_label) layout1.addWidget(self.project_number_read_line) layout1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layout2 = QtGui.QHBoxLayout() self.project_title_label = QtGui.QLabel('Title:') self.project_title_edit_line = QtGui.QLineEdit(project_title) self.project_title_label.setBuddy(self.project_title_edit_line) layout2.addWidget(self.project_title_label) layout2.addWidget(self.project_title_edit_line) layout2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) self.project_title_edit_line.textChanged.connect(self.set_update_flag) layout3 = QtGui.QHBoxLayout() self.project_create_time_label = QtGui.QLabel('CreateTime:') self.project_create_time_read_line = QtGui.QLabel( self.project_create_time) self.project_create_time_label.setBuddy( self.project_create_time_read_line) layout3.addWidget(self.project_create_time_label) layout3.addWidget(self.project_create_time_read_line) layout3.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layout4 = QtGui.QHBoxLayout() self.project_edit_time_label = QtGui.QLabel('EditTime:') self.project_edit_time_read_line = QtGui.QLabel(project_edit_time) self.project_edit_time_label.setBuddy(self.project_edit_time_read_line) layout4.addWidget(self.project_edit_time_label) layout4.addWidget(self.project_edit_time_read_line) layout4.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layout5 = QtGui.QHBoxLayout() self.project_detail_label = QtGui.QLabel('Detail:') self.project_detail_edit_line = QtGui.QTextEdit(project_detail) self.project_detail_label.setBuddy(self.project_detail_edit_line) layout5.addWidget(self.project_detail_label) layout5.addWidget(self.project_detail_edit_line) layout5.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) self.project_detail_edit_line.textChanged.connect(self.set_update_flag) mainlayout.addLayout(layout1) mainlayout.addLayout(layout2) mainlayout.addLayout(layout3) mainlayout.addLayout(layout4) mainlayout.addLayout(layout5) self.setLayout(mainlayout) class config_file(QtGui.QDialog): def __init__(self, parent=None): super(config_file, self).__init__(parent) self.file_name = 'D:workspacepy_demoNotePadconfig.py' self.separator_char = '=' self.config_table = QtGui.QTableWidget(0, 2) self.config_table.setSelectionMode( QtGui.QAbstractItemView.SingleSelection) # 设置为只能选中单个目标 self.config_table.setSelectionBehavior( QtGui.QAbstractItemView.SelectRows) # 设置选中单个单元格 self.config_table.setEditTriggers( QtGui.QAbstractItemView.NoEditTriggers) # 默认双击可以编辑,这里设置禁止编辑 self.config_table.setAlternatingRowColors(True) # 隔行改变颜色 self.config_table.setShowGrid(True) # 设置显示网格线 self.config_table.setSortingEnabled(False) # 设置禁止排序 self.config_table.setHorizontalHeaderLabels(['Attribute', 'Value']) self.load_config() layout = QtGui.QVBoxLayout() btnlayout = QtGui.QHBoxLayout() self.add_item_btn = QtGui.QPushButton() self.add_item_btn.setText('Add') self.add_item_btn.clicked.connect(self.add_config) self.edit_item_btn = QtGui.QPushButton() self.edit_item_btn.setText('Edit') self.edit_item_btn.clicked.connect(self.edit_config) self.delete_item_btn = QtGui.QPushButton() self.delete_item_btn.setText('Delete') self.delete_item_btn.clicked.connect(self.delete_config) btnlayout.addStretch() btnlayout.addWidget(self.add_item_btn) btnlayout.addWidget(self.edit_item_btn) btnlayout.addWidget(self.delete_item_btn) layout.addWidget(self.config_table) layout.addLayout(btnlayout) self.setLayout(layout) def load_config(self): if os.path.exists(self.file_name): if os.path.getsize(self.file_name): with open(self.file_name, 'r') as f: for line_count, line in enumerate(f.readlines()): if self.separator_char in line: attribute = line.split(self.separator_char)[ 0].strip() value = line.split(self.separator_char)[1].strip() self.config_table.insertRow(line_count) self.newAttr = QtGui.QTableWidgetItem(attribute) self.config_table.setItem( line_count, 0, self.newAttr) self.newValue = QtGui.QTableWidgetItem(value) self.config_table.setItem( line_count, 1, self.newValue) else: self.config_table.insertRow(0) self.newAttr = QtGui.QTableWidgetItem( 'There is no attribute now') self.config_table.setSpan(0, 0, 1, 2) self.newAttr.setTextAlignment( QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) self.config_table.setItem(0, 0, self.newAttr) else: self.config_table.insertRow(0) self.newAttr = QtGui.QTableWidgetItem(msg_file_not_exists) self.config_table.setSpan(0, 0, 1, 2) self.newAttr.setTextAlignment( QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) self.config_table.setItem(0, 0, self.newAttr) def add_config(self): if str(self.config_table.item(0, 0).text()) in (msg_file_is_null, msg_file_not_exists): current_row_index = self.config_table.currentRow() self.config_table.removeRow(current_row_index) total_count_index = self.config_table.rowCount() self.config_table.setEditTriggers( QtGui.QAbstractItemView.DoubleClicked) self.config_table.insertRow(total_count_index) def edit_config(self): self.config_table.setEditTriggers( QtGui.QAbstractItemView.DoubleClicked) def delete_config(self): current_row_index = self.config_table.currentRow() if current_row_index != -1: reply = QtGui.QMessageBox.warning( self, 'Warning', 'Could you confirm to delete the config', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: self.config_table.removeRow(current_row_index) def closeEvent(self, event): row_count = self.config_table.rowCount() all_lines = [] for row in range(row_count): if self.config_table.item(row, 0) and self.config_table.item(row, 1): line = str(self.config_table.item(row, 0).text()) + self.separator_char + str(self.config_table.item(row, 1).text()) all_lines.append(line + ' ') else: QtGui.QMessageBox.information( self, 'Error', 'Config shoud not be null') event.ignore() return with open(self.file_name, 'w') as f: f.writelines(all_lines) app = QtGui.QApplication(sys.argv) mainwindow = MainWindow() mainwindow.show() app.exec_()