def __init__(self, config, *args, **kwargs): super().__init__(*args, **kwargs) ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'tag_manage_widget.ui') uic.loadUi(ui_file_path, self) self.db_helper = DBCommandLineHelper() self.message_box = QMessageBox() self.tag_names_line_edit = TagNamesLineEdit() self.tag_names_line_edit.setPlaceholderText("Tag Names") self.cmp = None self.set_completer() self.selected_tag_names_layout.insertWidget(0, self.tag_names_line_edit) add_icon = QIcon() add_icon.addPixmap(QPixmap(config.images + '/add.png'), QIcon.Normal, QIcon.Off) self.new_tag_btn.setIcon(add_icon) self.tag_editor = None self.tag_list = None self.set_tag_list_widget() # init data self.select_btn.clicked.connect(self.select_event) self.cancel_btn.clicked.connect(self.close) self.new_tag_btn.clicked.connect(self.new_tag_event) self.refresh_signal.connect(self.set_tag_list_widget, Qt.QueuedConnection)
class CaseDataManager: def __init__(self): self.db_helper = DBCommandLineHelper() def get_case_data_count(self, case_id): case_data_list = self.get_run_format_data(case_id) return len(case_data_list) def get_case_data(self, case_id): case_data_list = [] case = self.db_helper.query_case_by_id(case_id) header_relation_list = eval(case.header_relation) if case.header_relation else [] case_data_list.append(header_relation_list) if case.data_relation is not None and case.data_relation: data_relation_list = eval(case.data_relation) for data_relation in data_relation_list: temp_data_list = [] for data_id in data_relation: case_data = CaseData() if data_id: temp_case_data = self.db_helper.query_case_data(id=int(data_id)) case_data.id = temp_case_data.id case_data.data = temp_case_data.data case_data.init_data = temp_case_data.data temp_data_list.append(case_data) case_data_list.append(temp_data_list) return case_data_list
def update_task_record_stats(): ''' 更新event 统计数据 :return: ''' task_record_statses = DBCommandLineHelper.get_task_record_stats([0]) if task_record_statses: for task_record_stats in task_record_statses: total_count = 0 pass_count = 0 fail_count = 0 if task_record_stats.task_records: total_count = len(task_record_stats.task_records) for task_records in task_record_stats.task_records: if task_records.status == task_records.pass_flag: pass_count += 1 else: fail_count += 1 task_record_stats.total_count = total_count task_record_stats.pass_count = pass_count task_record_stats.fail_count = fail_count task_record_stats.end_time = task_record_stats.task_records[ len(task_record_stats.task_records) - 1].end_time if len(task_record_stats.task_records ) > 0 else task_record_stats.end_time DBCommandLineHelper.update_data()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.dBCommandLineHelper = DBCommandLineHelper() ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'add_case.ui') uic.loadUi(ui_file_path, self) screen = QDesktopWidget().screenGeometry() self.resize(screen.width() / 5 * 2, screen.height() / 5 * 2) self.search_button = SearchButton() self.tag_names_line_edit = TagLineEdit("tag_names_line_edit", self.search_button) self.tag_names_line_edit_adapter() self.tag_list = None self.result_widget = RunnerTableWidget( self.dBCommandLineHelper.query_case_all(), []) self.result_table_layout.insertWidget(0, self.result_widget) self.message_box = QMessageBox() self.search_button.clicked.connect(self.search_event) self.selectcasebtn.clicked.connect(self.select_event) self.casecancelbtn.clicked.connect(self.close)
def get_record_by_case_id(case_id): ''' 获取详细record :param case_id: :return: ''' task_record = DBCommandLineHelper.query_record_by_case_id(case_id) return task_record
def __init__(self, tester, *args, **kwargs): super().__init__(*args, **kwargs) ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'case_run.ui') uic.loadUi(ui_file_path, self) # set icon run_icon = QIcon() self.tester = tester self.config = self.tester.get_config() run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off) self.run_stop_btn.setIcon(run_icon) add_icon = QIcon() add_icon.addPixmap(QPixmap(self.config.images + '/add.png'), QIcon.Normal, QIcon.Off) self.addbtn.setIcon(add_icon) self.message_box = QMessageBox() self.dBCommandLineHelper = DBCommandLineHelper() self.addbtn.clicked.connect(self.click_add_case) self.run_stop_btn.clicked.connect(self.click_run_stop_btn) self.add_case_widget = None self.add_device_widget = None self.splitter = None self.case_widget = RunnerTableWidget([], [0]) self.log_area = Console() self.splitter_setting() self.status_listener = CaseRunStatusListener() self.status_listener.listener_msg_signal.connect( self.update_case_name_color, Qt.QueuedConnection) self.tester.add_run_status_listener(self.status_listener)
def __init__(self, show_case_editor_signal, tester, *args, **kwargs): super().__init__(*args, **kwargs) self.show_case_editor_signal = show_case_editor_signal self.db_helper = DBCommandLineHelper() self.case_data_manager = CaseManager() ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'case_manager.ui') uic.loadUi(ui_file_path, self) self.add_case_button.clicked.connect(self.add_case) # add case event self.tester = tester # 从上级窗体获得Tester() # case 搜索 self.search_button = SearchButton() self.search_button.clicked.connect(self.update_table_data_by_search_line) self.tag_names_line_edit = TagLineEdit('tag_names_line_edit', self.search_button) self.query_conditions_layout.insertWidget(5, self.tag_names_line_edit) self.table_widget = TableWidget(self.show_case_editor_signal, self.tester, []) # init ui table self.delete_case_button.clicked.connect(self.delete_case) self.export_button.clicked.connect(self.export_data) self.import_button.clicked.connect(self.import_data) self.add_tag_button.clicked.connect(self.add_tag) self.delete_tag_button.clicked.connect(self.delete_tag) self.modify_tag_button.clicked.connect(self.modify_tag) self.button_style(self.delete_case_button, '/delete.png', 'Delete') self.button_style(self.add_case_button, '/add.png', 'Add') self.button_style(self.import_button, '/import.png', 'Import') self.button_style(self.export_button, '/export.png', 'Export') self.button_style(self.add_tag_button, '/add.png', 'Add') self.button_style(self.delete_tag_button, '/delete.png', 'Delete') self.button_style(self.modify_tag_button, '/edit.png', 'Modify') self.set_tag_list_widget() # show all tags self.set_tag_search_line() # Set the tag input line automatic completion self.data_message_layout.insertWidget(1, self.table_widget) self.refresh_signal.connect(self.refresh, Qt.QueuedConnection)
def update_task_record_stats(): ''' 更新event 统计数据 :return: ''' task_record_statses = DBCommandLineHelper.get_task_record_stats([0]) if task_record_statses: for task_record_stats in task_record_statses: total_count = 0 pass_count = 0 fail_count = 0 if task_record_stats.task_records: total_count = len(task_record_stats.task_records) for task_records in task_record_stats.task_records: if task_records.status == task_records.pass_flag: pass_count += 1 else: fail_count += 1 task_record_stats.total_count = total_count task_record_stats.pass_count = pass_count task_record_stats.fail_count = fail_count task_record_stats.end_time = task_record_stats.task_records[len(task_record_stats.task_records) - 1].end_time if len( task_record_stats.task_records) > 0 else task_record_stats.end_time DBCommandLineHelper.update_data()
def __init__(self, refresh_signal, tag_name=None, *args, **kwargs): super().__init__(*args, **kwargs) self.refresh_signal = refresh_signal self.db_helper = DBCommandLineHelper() ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'tag_editor.ui') uic.loadUi(ui_file_path, self) # set icon save_icon = QIcon() config = Config() save_icon.addPixmap(QPixmap(config.images + '/save.png'), QIcon.Normal, QIcon.Off) self.tag_save_btn.setIcon(save_icon) self.tag_save_btn.clicked.connect(self.tag_save) self.tag_id_line_edit.hide() # 隐藏line_edit self.tag_name_line_edit.setPlaceholderText("Tag Name") # 设置提示文字 self.tag_description_text_edit.setPlaceholderText('Tag Description') if tag_name: self.tag = self.db_helper.query_tag_by_name(tag_name) self.tag_id_line_edit.setText(str(self.tag.id)) self.tag_name_line_edit.setText(self.tag.name) self.tag_description_text_edit.setPlainText(self.tag.description)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.dBCommandLineHelper = DBCommandLineHelper() ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'add_case.ui') uic.loadUi(ui_file_path, self) screen = QDesktopWidget().screenGeometry() self.resize(screen.width() / 5 * 2, screen.height() / 5 * 2) self.search_button = SearchButton() self.tag_names_line_edit = TagLineEdit("tag_names_line_edit", self.search_button) self.tag_names_line_edit_adapter() self.tag_list = None self.result_widget = RunnerTableWidget(self.dBCommandLineHelper.query_case_all(), []) self.result_table_layout.insertWidget(0, self.result_widget) self.message_box = QMessageBox() self.search_button.clicked.connect(self.search_event) self.selectcasebtn.clicked.connect(self.select_event) self.casecancelbtn.clicked.connect(self.close)
def __init__(self, tester, *args, **kwargs): super().__init__(*args, **kwargs) ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'case_run.ui') uic.loadUi(ui_file_path, self) # set icon run_icon = QIcon() self.tester = tester self.config = self.tester.get_config() run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off) self.run_stop_btn.setIcon(run_icon) add_icon = QIcon() add_icon.addPixmap(QPixmap(self.config.images + '/add.png'), QIcon.Normal, QIcon.Off) self.addbtn.setIcon(add_icon) self.message_box = QMessageBox() self.dBCommandLineHelper = DBCommandLineHelper() self.addbtn.clicked.connect(self.click_add_case) self.run_stop_btn.clicked.connect(self.click_run_stop_btn) self.add_case_widget = None self.add_device_widget = None self.splitter = None self.case_widget = RunnerTableWidget([], [0]) self.log_area = Console() self.splitter_setting() self.status_listener = CaseRunStatusListener() self.status_listener.listener_msg_signal.connect(self.update_case_name_color, Qt.QueuedConnection) self.tester.add_run_status_listener(self.status_listener)
class CaseManagerWidget(QWidget): refresh_signal = pyqtSignal(name='refresh_data') def __init__(self, show_case_editor_signal, tester, *args, **kwargs): super().__init__(*args, **kwargs) self.show_case_editor_signal = show_case_editor_signal self.db_helper = DBCommandLineHelper() self.case_data_manager = CaseManager() ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'case_manager.ui') uic.loadUi(ui_file_path, self) self.add_case_button.clicked.connect(self.add_case) # add case event self.tester = tester # 从上级窗体获得Tester() # case 搜索 self.search_button = SearchButton() self.search_button.clicked.connect(self.update_table_data_by_search_line) self.tag_names_line_edit = TagLineEdit('tag_names_line_edit', self.search_button) self.query_conditions_layout.insertWidget(5, self.tag_names_line_edit) self.table_widget = TableWidget(self.show_case_editor_signal, self.tester, []) # init ui table self.delete_case_button.clicked.connect(self.delete_case) self.export_button.clicked.connect(self.export_data) self.import_button.clicked.connect(self.import_data) self.add_tag_button.clicked.connect(self.add_tag) self.delete_tag_button.clicked.connect(self.delete_tag) self.modify_tag_button.clicked.connect(self.modify_tag) self.button_style(self.delete_case_button, '/delete.png', 'Delete') self.button_style(self.add_case_button, '/add.png', 'Add') self.button_style(self.import_button, '/import.png', 'Import') self.button_style(self.export_button, '/export.png', 'Export') self.button_style(self.add_tag_button, '/add.png', 'Add') self.button_style(self.delete_tag_button, '/delete.png', 'Delete') self.button_style(self.modify_tag_button, '/edit.png', 'Modify') self.set_tag_list_widget() # show all tags self.set_tag_search_line() # Set the tag input line automatic completion self.data_message_layout.insertWidget(1, self.table_widget) self.refresh_signal.connect(self.refresh, Qt.QueuedConnection) def refresh(self): self.set_tag_search_line() self.set_tag_list_widget() def add_tag(self): ''' add tag :return: ''' self.tag_editor_window = TagEditorWidget(self.refresh_signal) self.tag_editor_window.setWindowModality(Qt.ApplicationModal) self.tag_editor_window.show() def modify_tag(self): items = self.tag_list_widget.selectedItems() item = items[0] if item.text() == '全部' or item.text() == '无标识': QMessageBox.warning(self, 'tag select ', 'please select a tag') else: self.tag_editor_window = TagEditorWidget(self.refresh_signal, item.text()) self.tag_editor_window.setWindowModality(Qt.ApplicationModal) self.tag_editor_window.show() def delete_tag(self): ''' delete tag :return: ''' items = self.tag_list_widget.selectedItems() item = items[0] if item.text() == '全部' or item.text() == '无标识': QMessageBox.warning(self, 'Tag Select ', 'please select a tag') else: reply = QMessageBox.information(self, "Tag Delete", "Do you want to delete ["+item.text()+"]", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: # update case info self.db_helper.delete_tag_by_name(item.text()) self.refresh_signal.emit() def import_data(self): ''' import data :return: ''' file_name = QFileDialog.getOpenFileName(caption='Open File', directory='/', filter='dpk files(*.dpk)') if file_name[0] and '.dpk' in file_name[0]: conflict_tags_message_dict = self.case_data_manager.import_data(file_name[0]) if conflict_tags_message_dict: self.conflict_tags_widget = ConflictTagsWidget(self.refresh_signal, conflict_tags_message_dict, self.case_data_manager) self.conflict_tags_widget.setWindowModality(Qt.ApplicationModal) self.conflict_tags_widget.show() else: QMessageBox.information(self, ' import operation', 'import success') self.refresh_signal.emit() def export_data(self): ''' export data :return: ''' self.table_widget.get_checked_data() # todo 尝试能否直接获取到checkboxs 的状态 if len(self.table_widget.checked_cases_message) > 0: path = QFileDialog.getSaveFileName(caption='Save file', directory='/', filter='dpk file(*.dpk)', options=QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) if path[0]: case_id_list = [] for case_message in self.table_widget.checked_cases_message: case_id_list.append(case_message['case_id']) self.case_data_manager.export_data(path[0], case_id_list) QMessageBox.information(self, 'export operation', 'export success') else: QMessageBox.warning(self, 'export error', 'please select a case to be exported') def button_style(self, button, image_path, text): icon = QIcon() config = Config() icon.addPixmap(QPixmap(config.images + image_path), QIcon.Normal, QIcon.Off) button.setIcon(icon) button.setText('') button.setToolTip(text) button.resize(50, 50) button.setStyleSheet( # 'QPushButton{border-width:0px; background:transparent;} ' 'border:none; ' ) def delete_case(self): self.table_widget.get_checked_data() # todo 尝试能否直接获取到checkboxs 的状态 if len(self.table_widget.checked_cases_message) > 0: infor_message = 'Confirm delete article ' + str(len(self.table_widget.checked_cases_message)) + ' case' reply = QMessageBox.information(self, 'delete reminder', infor_message, QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: case_ids = [] for index,case_message in enumerate(self.table_widget.checked_cases_message): self.table_widget.dataTableWidget.removeRow(int(case_message['row_num']) - index) # 删除行后 行数会变 所以-i case_ids.append(int(case_message['case_id'])) self.db_helper.batch_delete_case(case_ids) del self.table_widget.checked_cases_message[:] # todo statusbar 应该提示 else: QMessageBox.warning(self, 'delte error', 'please select cases to delete') def add_case(self): """ show editor :return: """ self.show_case_editor_signal.emit(0, 0) def update_table_data_by_list_view(self, tag_name): self.table_widget.setParent(None) self.data_message_layout.removeWidget(self.table_widget) if '全部' == tag_name: case_list = self.db_helper.query_case_all() elif '无标识' == tag_name: case_list = self.db_helper.query_no_tag_case() else: case_list = self.db_helper.query_case_by_tag_names([tag_name]) self.table_widget = TableWidget(self.show_case_editor_signal, self.tester, case_list) self.data_message_layout.insertWidget(1, self.table_widget) def update_table_data_by_search_line(self): ''' update ui table data :return: ''' self.table_widget.setParent(None) self.data_message_layout.removeWidget(self.table_widget) tag_names = self.tag_names_line_edit.text() if (tag_names.endswith(';')): tag_names = tag_names[0: len(tag_names) - 1] case_list = [] if tag_names != '': tag_names = tag_names[:len(tag_names)].split(';') case_list = self.db_helper.query_case_by_tag_names(tag_names) else: case_list = self.db_helper.query_case_all() self.table_widget = TableWidget(self.show_case_editor_signal, self.tester, case_list) self.data_message_layout.insertWidget(1, self.table_widget) def set_tag_list_widget(self): ''' init ui table data and onclick event :return: ''' self.tag_list_widget.clear() self.tag_list_widget.addItem('全部') self.tag_list_widget.addItem('无标识') self.tag_list = self.db_helper.query_tag_all() for tag in self.tag_list: self.tag_list_widget.addItem(tag.name) self.tag_list_widget.itemClicked.connect( lambda: self.list_widget_item_clicked(self.tag_list_widget.currentItem())) item = self.tag_list_widget.item(0) item.setSelected(True) self.list_widget_item_clicked(item) def set_tag_search_line(self): ''' set tag search line :return: ''' string_list = [] tag_names_list = string_list + self.get_tag_names() tag_completer = TagCompleter(tag_names_list) self.tag_names_line_edit.setCompleter(tag_completer) def get_tag_names(self): tag_model_list = [] for tag in self.tag_list: tag_model_list.append(tag.name) return tag_model_list def list_widget_item_clicked(self, tag_list_widget_item): self.tag_names_line_edit.is_completer = False self.tag_names_line_edit.clear() text = tag_list_widget_item.text() if tag_list_widget_item.text() == '全部' or tag_list_widget_item.text() == '无标识': self.tag_names_line_edit.setText('') else: text = tag_list_widget_item.text() self.tag_names_line_edit.setText(text+';') self.update_table_data_by_list_view(text) self.tag_names_line_edit.is_completer = True
def get_task_record_stats(): update_task_record_stats() task_record_statses = DBCommandLineHelper.get_task_record_stats() return task_record_statses
def add_record(self, case_id, device_id, start_time, status, expect): DBCommandLineHelper.insert_record(self.task_id, case_id, device_id, start_time, status, expect)
def __init__(self): task_record_stats = DBCommandLineHelper.insert_task_record_stats() self.task_id = task_record_stats.id
def setUp(self): self.db_helper = DBCommandLineHelper()
class TestDataBase(unittest.TestCase): def setUp(self): self.db_helper = DBCommandLineHelper() def test_operate_tag_data(self): ms_str = str(time.time()) tag_name = "test_tag_name_" + ms_str tag_description = "test_tag_name_" + ms_str tag = self.db_helper.insert_tag(tag_name, tag_description) # 插入tag dst_tag = self.db_helper.query_tag_by_id(tag.id) # 根据tag.id 查询tag self.assertTrue(tag == dst_tag) tag_list = self.db_helper.fuzzy_query_tag_by_name(tag.name) self.assertTrue(tag in tag_list) dst_tag = self.db_helper.query_tag_by_name(tag.name) self.assertTrue(tag == dst_tag) tag_list = self.db_helper.query_tag_all() # 查询所有tag self.assertTrue(type(tag_list[0]) is Tag) self.db_helper.delete_tag(tag.id) # 删除tag dst_tag = self.db_helper.query_tag_by_id(tag.id) # 根据tag.id 查询tag、 self.assertTrue(dst_tag is None) def test_operate_case_data(self): ms_str = str(time.time()) tag_name = "test_tag_name_" + ms_str tag_description = "test_tag_name_" + ms_str tag = self.db_helper.insert_tag(tag_name, tag_description) # 插入tag tags = [tag] case_name = case_content = "test_case_name_" + ms_str case = self.db_helper.insert_case_with_tags(case_name, case_content, tags) # 插入case dst_case = self.db_helper.query_case_by_id(case.id) self.assertTrue(case == dst_case) dst_case = self.db_helper.query_case_by_name(True, case.name) self.assertTrue(case == dst_case) dst_case_list = self.db_helper.query_case_by_name(False, case.name) self.assertTrue(case in dst_case_list) case_list = self.db_helper.query_case_by_tag_names([tag.name]) self.assertTrue(type(case_list[0]) is Case) # tag_name = "test_tag_name_" + str(time.time()) # 更改case: case = self.db_helper.query_case_by_id(case.id) case_id = case.id case_name = 'test_case_name_' + str(time.time()) case.name = case_name case.content = 'test_case_name_' + str(time.time()) tags = self.db_helper.query_tag_all() case.tags = tags self.db_helper.update_case() case = self.db_helper.query_case_by_id(case.id) self.assertTrue(case.name == case_name) tag_name = "test_tag_name_" + str(time.time()) case = self.db_helper.insert_case_with_tagnames(case.name, case.content, [tag.name], [tag_name]) self.assertTrue(type(case) is Case and case.id) result = self.db_helper.get_table_data_by_cases_id(str(case.id)) self.assertTrue(result['case'] and result['tag'] and result['case_tag']) self.db_helper.delete_case(case.id) dst_case = self.db_helper.query_case_by_id(case.id) self.assertTrue(dst_case is None) def test_delete_tag_by_name(self): tag_name = 'test_123' tag = self.db_helper.insert_tag(tag_name, 'test tag') case = self.db_helper.insert_case_with_tags('test_123', 'test case', [tag]) self.db_helper.delete_tag_by_name(tag_name) self.assertTrue(self.db_helper.query_case_by_id(case.id) is not None) self.assertTrue(self.db_helper.query_tag_by_name(tag_name) is None)
class RunWidget(QWidget): running = False device_list_signal = pyqtSignal(list, name="device_list_signal") cases = [] def __init__(self, tester, *args, **kwargs): super().__init__(*args, **kwargs) ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'case_run.ui') uic.loadUi(ui_file_path, self) # set icon run_icon = QIcon() self.tester = tester self.config = self.tester.get_config() run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off) self.run_stop_btn.setIcon(run_icon) add_icon = QIcon() add_icon.addPixmap(QPixmap(self.config.images + '/add.png'), QIcon.Normal, QIcon.Off) self.addbtn.setIcon(add_icon) self.message_box = QMessageBox() self.dBCommandLineHelper = DBCommandLineHelper() self.addbtn.clicked.connect(self.click_add_case) self.run_stop_btn.clicked.connect(self.click_run_stop_btn) self.add_case_widget = None self.add_device_widget = None self.splitter = None self.case_widget = RunnerTableWidget([], [0]) self.log_area = Console() self.splitter_setting() self.status_listener = CaseRunStatusListener() self.status_listener.listener_msg_signal.connect(self.update_case_name_color, Qt.QueuedConnection) self.tester.add_run_status_listener(self.status_listener) def splitter_setting(self): """ set splitter :return: """ if self.splitter: self.splitter = None self.splitter = QSplitter(Qt.Vertical) self.splitter.setHandleWidth(1) # add "case_widget" and "log_area" to splitter self.splitter.addWidget(self.case_widget) self.splitter.addWidget(self.log_area) # set the initial scale: 4:1 self.splitter.setStretchFactor(0, 4) self.splitter.setStretchFactor(1, 1) self.case_table_layout.addWidget(self.splitter) def click_add_case(self): """ click the button to show add case widget :return: """ self.add_case_widget = AddCaseWidget() self.add_case_widget.select_case_signal.connect(self.show_cases, Qt.QueuedConnection) self.add_case_widget.setWindowModality(Qt.ApplicationModal) self.add_case_widget.show() def click_run_stop_btn(self): """ start or stop to run case :return: """ devices = [] if self.running: self.stop_case() return if not self.cases: # cases is null self.message_box.warning(self, "Message", "Please add cases first.", QMessageBox.Ok) return try: devices = self.tester.devices() except Exception as e: self.add_log("<font color='red'>" + str(e) + "</font>") if not devices: # There is no device connected self.message_box.warning(self, "Message", "Please connect the device to your computer.", QMessageBox.Ok) return self.add_device_widget = AddDeviceWidget() self.add_device_widget.setWindowModality(Qt.ApplicationModal) self.add_device_widget.add_log_signal.connect(self.add_log, Qt.QueuedConnection) self.add_device_widget.run_case_signal.connect(self.run_case, Qt.QueuedConnection) self.device_list_signal.connect(self.add_device_widget.add_radio_to_widget, Qt.QueuedConnection) self.add_device_widget.show() try: self.device_list_signal.emit(devices) except Exception as e: self.add_log("<font color='red'><pre>" + str(e) + "</pre></font>") def add_log(self, log_info): """ add log to log_area :return: """ if self.log_area is None: return self.log_area.append(log_info) def update_case_name_color(self, msg, is_passed): """ update case's font color according to the case's result pass: green; fail: red :param is_passed: :param msg: :return: """ if msg.status == 601: self.add_log("<font color='green'> Start to install agent.</font>") elif msg.status == 602: self.add_log("<font color='green'> Install agent success.</font>") elif msg.status == 603: self.add_log("<font color='red'> Install agent Fail." + "\r Error Info:\r<pre>" + msg.message + "</pre></font>") elif msg.status == 701: self.add_log("<font color='green'> Start agent.</font>") elif msg.status == 702: self.add_log("<font color='green'> Stop agent.</font>") elif msg.status == 703: self.add_log("<font color='red'> Agent error." + "\r Error Info:\r<pre>" + msg.message + "</pre></font>") for row_index in range(self.case_widget.dataTableWidget.rowCount()): case_id_item = self.case_widget.dataTableWidget.item(row_index, 1) # get case id from dataTableWidget if msg.status == 2: # test end if is_passed: self.add_log("<font color='green'> All cases are Passed.</font>") self.stop_case() break if case_id_item.text() != str(msg.case_id): continue self.case_widget.dataTableWidget.selectRow(row_index) if msg.status == 101: # default: case pass self.update_green(row_index) elif msg.status == 500: self.update_red(row_index) self.add_log("<font color='red'> Case Failed, case id: " + str(msg.case_id) + "</font>") self.add_log("<pre><font color='red'>" + str(msg.message) + "</font></pre>") def run_case(self, devices): kw_case_list = [] if not self.cases: return for case_id in self.cases: kw_case = KWCase() case = self.dBCommandLineHelper.query_case_by_id(case_id) kw_case.id = case.id kw_case.name = case.name kw_case.content = case.content kw_case.data = case.data kw_case_list.append(kw_case) # set icon stop_icon = QIcon() stop_icon.addPixmap(QPixmap(self.config.images + '/stop.png'), QIcon.Normal, QIcon.Off) self.run_stop_btn.setIcon(stop_icon) self.run_stop_btn.setText("Stop") self.running = True if not devices: return try: self.tester.select_devices(devices) self.tester.run(kw_case_list) except Exception as e: self.stop_case() self.add_log(str(e)) def stop_case(self): run_icon = QIcon() run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off) self.run_stop_btn.setIcon(run_icon) # change icon self.run_stop_btn.setText("Run") self.running = False try: self.tester.stop() self.tester.stop_server() except Exception as e: self.add_log(str(e)) def show_cases(self, id_list): """ show cases in RunnerTableWidget according to id list :param id_list: :return: """ self.case_table_layout.removeWidget(self.splitter) case_list = [] self.cases = id_list for case_id in id_list: case = self.dBCommandLineHelper.query_case_by_id(case_id) case_list.append(case) self.case_widget = RunnerTableWidget(case_list, [0]) self.splitter_setting() # reload splitter def update_green(self, row_index): """ update item text color to green by row number :param row_index: :return: """ brush_green_color = QBrush(QColor(55, 177, 88)) for column_index in range(self.case_widget.dataTableWidget.columnCount()): item = self.case_widget.dataTableWidget.item(row_index, column_index) item.setForeground(brush_green_color) def update_red(self, row_index): """ update item text color to red by row number :param row_index: :return: """ brush_red_color = QBrush(QColor(255, 0, 0)) for column_index in range(self.case_widget.dataTableWidget.columnCount()): item = self.case_widget.dataTableWidget.item(row_index, column_index) item.setForeground(brush_red_color)
class TestDataBase(unittest.TestCase): def setUp(self): self.db_helper = DBCommandLineHelper() def test_operate_tag_data(self): ms_str = str(time.time()) tag_name = "test_tag_name_" + ms_str tag_description = "test_tag_name_" + ms_str tag = self.db_helper.insert_tag(tag_name, tag_description) # 插入tag dst_tag = self.db_helper.query_tag_by_id(tag.id) # 根据tag.id 查询tag self.assertTrue(tag == dst_tag) tag_list = self.db_helper.fuzzy_query_tag_by_name(tag.name) self.assertTrue(tag in tag_list) dst_tag = self.db_helper.query_tag_by_name(tag.name) self.assertTrue(tag == dst_tag) tag_list = self.db_helper.query_tag_all() # 查询所有tag self.assertTrue(type(tag_list[0]) is Tag) self.db_helper.delete_tag(tag.id) # 删除tag dst_tag = self.db_helper.query_tag_by_id(tag.id) # 根据tag.id 查询tag、 self.assertTrue(dst_tag is None) def test_operate_case_data(self): ms_str = str(time.time()) tag_name = "test_tag_name_" + ms_str tag_description = "test_tag_name_" + ms_str tag = self.db_helper.insert_tag(tag_name, tag_description) # 插入tag tags = [tag] case_name = case_content = "test_case_name_" + ms_str case = self.db_helper.insert_case_with_tags(case_name, case_content, tags) # 插入case dst_case = self.db_helper.query_case_by_id(case.id) self.assertTrue(case == dst_case) dst_case = self.db_helper.query_case_by_name(True, case.name) self.assertTrue(case == dst_case) dst_case_list = self.db_helper.query_case_by_name(False, case.name) self.assertTrue(case in dst_case_list) case_list = self.db_helper.query_case_by_tag_names([tag.name]) self.assertTrue(type(case_list[0]) is Case) # tag_name = "test_tag_name_" + str(time.time()) # 更改case: case = self.db_helper.query_case_by_id(case.id) case_id = case.id case_name = 'test_case_name_' + str(time.time()) case.name = case_name case.content = 'test_case_name_' + str(time.time()) tags = self.db_helper.query_tag_all() case.tags = tags self.db_helper.update_case() case = self.db_helper.query_case_by_id(case.id) self.assertTrue(case.name == case_name) tag_name = "test_tag_name_" + str(time.time()) case = self.db_helper.insert_case_with_tagnames( case.name, case.content, [tag.name], [tag_name]) self.assertTrue(type(case) is Case and case.id) result = self.db_helper.get_table_data_by_cases_id(str(case.id)) self.assertTrue(result['case'] and result['tag'] and result['case_tag']) self.db_helper.delete_case(case.id) dst_case = self.db_helper.query_case_by_id(case.id) self.assertTrue(dst_case is None) def test_delete_tag_by_name(self): tag_name = 'test_123' tag = self.db_helper.insert_tag(tag_name, 'test tag') case = self.db_helper.insert_case_with_tags('test_123', 'test case', [tag]) self.db_helper.delete_tag_by_name(tag_name) self.assertTrue(self.db_helper.query_case_by_id(case.id) is not None) self.assertTrue(self.db_helper.query_tag_by_name(tag_name) is None)
def __init__(self): self.db_helper = DBCommandLineHelper()
class AddCaseWidget(QWidget): select_case_signal = pyqtSignal(list, name="select_case_signal") def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.dBCommandLineHelper = DBCommandLineHelper() ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'add_case.ui') uic.loadUi(ui_file_path, self) screen = QDesktopWidget().screenGeometry() self.resize(screen.width() / 5 * 2, screen.height() / 5 * 2) self.search_button = SearchButton() self.tag_names_line_edit = TagLineEdit("tag_names_line_edit", self.search_button) self.tag_names_line_edit_adapter() self.tag_list = None self.result_widget = RunnerTableWidget(self.dBCommandLineHelper.query_case_all(), []) self.result_table_layout.insertWidget(0, self.result_widget) self.message_box = QMessageBox() self.search_button.clicked.connect(self.search_event) self.selectcasebtn.clicked.connect(self.select_event) self.casecancelbtn.clicked.connect(self.close) def search_event(self): """ search tags by tag name, and show the result in the table widget :return: """ self.result_widget.setParent(None) self.result_table_layout.removeWidget(self.result_widget) tag_names = self.tag_names_line_edit.text().strip() # tag_names is None if not tag_names: case_list = self.dBCommandLineHelper.query_case_all() self.result_widget = RunnerTableWidget(case_list, []) self.result_table_layout.insertWidget(0, self.result_widget) return # tag_names is not None tag_names = tag_names.split(';') for tag_name in tag_names: if not tag_name.strip(): # remove null tag tag_names.remove(tag_name.strip()) continue case_list = self.dBCommandLineHelper.query_case_by_tag_names([tag_name.strip() for tag_name in tag_names]) self.result_widget = RunnerTableWidget(case_list, []) self.result_table_layout.insertWidget(0, self.result_widget) def select_event(self): """ handle the select event :return: """ self.result_widget.get_checked_data() if not self.result_widget.checked_cases_message: self.message_box.warning(self, "Message", "Please choose cases first.", QMessageBox.Ok) return id_list = [] for item in self.result_widget.checked_cases_message: id_list.append(int(item["case_id"])) self.select_case_signal.emit(id_list) self.close() # close AddCase def tag_names_line_edit_adapter(self): """ settings for tag_names_line_edit such as completer, placeholder text :return: """ self.tag_names_line_edit.setPlaceholderText("Tag names") self.search_layout.insertWidget(0, self.tag_names_line_edit) self.tag_list = self.dBCommandLineHelper.query_tag_all() # get all tags tag_name_list = [] for tag in self.tag_list: tag_name_list.append(tag.name) cmp = TagCompleter(tag_name_list) self.tag_names_line_edit.setCompleter(cmp)
class EditorWidget(QWidget): device_and_data_signal = pyqtSignal(list, int, name="device_list_signal") import_list_signal = pyqtSignal(set, name="import_list_signal") close_cancel_signal = pyqtSignal(name="close_cancel_signal") def __init__(self, refresh_signal, tester, case_id=None, *args, **kwargs): super().__init__(*args, **kwargs) ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'case_editor.ui') uic.loadUi(ui_file_path, self) self.dBCommandLineHelper = DBCommandLineHelper() self.tester = tester self.config = self.tester.get_config() self.debug_runner = self.tester.get_debug_runner() self.case_id = case_id self.refresh_signal = refresh_signal self.init_ui() self.is_log_show = True self.is_running = False self.tag_list = [] self.parsed_line_list = [] self.case = None self.high_lighter = None self.tag_manage_widget = None self.add_device_widget = None self.message_box = QMessageBox() self.add_tag_button = SearchButton() self.tag_names_line_edit = TagLineEdit("tag_names_line_edit", self.add_tag_button) self.set_tag_name_completer() self.splitter = QSplitter(Qt.Vertical) self.splitter.setHandleWidth(1) # set handle width self.editor_text_edit = TextEdit(self.debug_runner.core) # case content TextEdit self.console = Console() # Add the 'editor text edit' and 'console' to splitter self.splitter.addWidget(self.editor_text_edit) self.splitter.addWidget(self.console) # Set the initial scale: 4:1 self.splitter.setStretchFactor(0, 4) self.splitter.setStretchFactor(1, 1) self.editor_layout.addWidget(self.splitter) self.import_list_signal.connect(self.editor_text_edit.get_import_from_content, Qt.QueuedConnection) self.editor_text_edit.parse_error_info_signal.connect(self.add_info_console, Qt.QueuedConnection) self.editor_adapter() # set completer and highlighter self.set_case_edit_data() # update case # run status listener self.status_listener = EditorRunStatusListener() self.status_listener.editor_listener_msg_signal.connect(self.result_handle, Qt.QueuedConnection) self.debug_runner.listener = self.status_listener self.data_line = None # button event self.save_btn.clicked.connect(self.save_case) self.run_btn.clicked.connect(self.run_btn_event) self.console_btn.clicked.connect(self.log_show_hide_event) self.edit_data_btn.clicked.connect(self.add_case_data) self.add_tag_button.clicked.connect(self.choose_event) # case data self.case_manager = CaseManager() self.case_data_manage = CaseDataManager() self.case_data_count = 0 # init case data count self.is_case_data_modify = False def init_ui(self): """ init ui, include: resize window :return: """ screen = QDesktopWidget().screenGeometry() self.resize(screen.width() / 2, screen.height() / 2) self.init_btn_icon() self.id_line_edit.hide() # hide line_edit self.case_name_line_edit.setPlaceholderText("Case Name") def init_btn_icon(self): """ init button icon, including: save button、run button、show/hide console button :return: """ save_icon = QIcon() save_icon.addPixmap(QPixmap(self.config.images + '/save.png'), QIcon.Normal, QIcon.Off) # save icon self.save_btn.setIcon(save_icon) run_icon = QIcon() run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off) # run icon self.run_btn.setIcon(run_icon) console_icon = QIcon() console_icon.addPixmap(QPixmap(self.config.images + '/console.png'), QIcon.Normal, QIcon.Off) # console icon self.console_btn.setIcon(console_icon) edit_data_icon = QIcon() edit_data_icon.addPixmap(QPixmap(self.config.images + '/edit.png'), QIcon.Normal, QIcon.Off) # console icon self.edit_data_btn.setIcon(edit_data_icon) def add_case_data(self): """ show case data widget :return: """ if hasattr(self, 'case_data_widget'): self.case_data_widget.close() self.case_data_widget = CaseDataWidget(self.case_id) self.case_data_widget.show() def choose_event(self): """ choose tag event, show tags :return: """ self.tag_manage_widget = TagManageWidget(self.config) self.tag_manage_widget.selected_tag_names_signal.connect(self.set_selected_tag_names) self.tag_manage_widget.setWindowModality(Qt.ApplicationModal) self.tag_manage_widget.show() def set_selected_tag_names(self, tag_names): """ set tag names :param tag_names: :return: """ original_tag_names = self.tag_names_line_edit.text().strip() tag_name_set = set(original_tag_names.split(";")) # original tag name set if not tag_names: return # handle the repeat tag names tag_name_list = tag_names.split(";") for tag_name in tag_name_list: if (tag_name.strip() in original_tag_names) or (not tag_name.strip()): continue tag_name_set.add(tag_name.strip()) # add new selected tag name all_tag_names = "" for tag_name in tag_name_set: if not tag_name.strip(): continue all_tag_names += tag_name.strip() + ";" self.tag_names_line_edit.is_completer = False self.tag_names_line_edit.setText(all_tag_names) self.tag_names_line_edit.is_completer = True def log_show_hide_event(self): if self.is_log_show: self.console_btn.setText("Show Console") self.console.hide() self.is_log_show = False else: self.console_btn.setText("Hide Console") self.console.show() self.is_log_show = True def add_info_console(self, info): """ append error massage to console :param info: :return: """ self.console.append(info) def result_handle(self, msg, is_passed): """ show the debug result in console :param is_passed: :param msg: :return: """ if msg.status == 601: self.add_info_console("<font color='green'> Start to install agent.</font>") elif msg.status == 602: self.add_info_console("<font color='green'> Install agent success.</font>") elif msg.status == 603: self.add_info_console("<font color='red'> Install agent Fail." + "\r Error Info:\r<pre>" + msg.message + "</pre></font>") elif msg.status == 701: self.add_info_console("<font color='green'> Start agent.</font>") elif msg.status == 702: self.add_info_console("<font color='green'> Stop agent.</font>") elif msg.status == 703: self.add_info_console("<font color='red'> Agent error." + "\r Error Info:\r<pre>" + msg.message + "</pre></font>") if msg.status == 500: # fail self.add_info_console("<font color='red'> <pre>" + str(msg.message) + "</pre></font>") if msg.status == 102 and is_passed: self.add_info_console("<font color='green'> The case is Passed.</font>") elif msg.status == 102 and not is_passed: self.add_info_console("<font color='red'> The case is Failed.</font>") def set_case_edit_data(self): """ init data for update case :return: """ if not self.case_id: return self.case = self.dBCommandLineHelper.query_case_by_id(self.case_id) self.id_line_edit.setText(self.case_id) self.case_name_line_edit.setText(self.case.name) tags = '' for tag in self.case.tags: tags = tags + tag.name + ";" self.tag_names_line_edit.setText(tags) self.editor_text_edit.setPlainText(self.case.content) # 'import' block in the case content init_import_set = set() for cmd in self.case.content.split("\n"): if cmd.strip().find("import") == 0: init_import_set.add(cmd.strip()) # send the init import block to editor's text edit, for init the highlighter and completer self.import_list_signal.emit(init_import_set) def closeEvent(self, event): """ close window event :param event: :return: """ case_name = self.case_name_line_edit.text().strip() # Case Name content = self.editor_text_edit.toPlainText().strip() # Case Content tag_list = self.get_tag_list() # check case data widget isVisible if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible() and ( not self.case_data_widget.has_modify): self.case_data_widget.close() if not self.case_id: # new case if (not case_name) and (not content) and (not tag_list): self.close() return elif self.case_id: # update case if not self.check_modify(): self.close() return self.handle_message_box_apply(event) def handle_message_box_apply(self, event): """ message box :param event: :return: """ reply = self.message_box.question(self, "Save Changes?", "The case has been modified, save changes?", QMessageBox.Save | QMessageBox.Cancel | QMessageBox.Discard) if reply == QMessageBox.Save: # update case info self.save_case(event) # check case data widget isVisible if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible(): self.case_data_widget.close() elif reply == QMessageBox.Discard: # check case data widget isVisible if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible(): self.case_data_widget.close() self.close() return else: self.close_cancel_signal.emit() event.ignore() def check_modify(self): """ check the changes of the case :return: """ is_case_modified = False case_db = self.dBCommandLineHelper.query_case_by_id(self.case_id) is_name_modified = case_db.name.strip() != self.case_name_line_edit.text().strip() is_content_modified = case_db.content.strip() != self.editor_text_edit.toPlainText().strip() # tag names in the line edit tag_list = self.get_tag_list() # tag names in db db_tag_list = case_db.tags is_tags_names_modify = set(db_tag_list).difference(set(tag_list)) != set(tag_list).difference(set(db_tag_list)) # check the case data if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible(): self.is_case_data_modify = self.case_data_widget.has_modify if is_name_modified or is_content_modified or is_tags_names_modify or self.is_case_data_modify: logger.debug('case changed. case name: {}, tags: {}, content: {}, case data: {}' .format(is_name_modified, is_tags_names_modify, is_content_modified, self.is_case_data_modify)) is_case_modified = True return is_case_modified def get_tag_list(self): """ get tag list from tag_names_line_edit :return: """ # get tag names tag_name_list = self.tag_names_line_edit.text().strip().split(";") tag_set = set() for tag_name in tag_name_list: if not tag_name.strip(): continue tag = self.dBCommandLineHelper.query_tag_by_name(tag_name.strip()) tag_set.add(tag) return list(tag_set) def run_btn_event(self): """ click run button, show add_device_widget :return: """ self.add_device_widget = AddDeviceWidget() # add device self.add_device_widget.setWindowModality(Qt.ApplicationModal) self.device_and_data_signal.connect(self.add_device_widget.add_radio_to_widget, Qt.QueuedConnection) self.add_device_widget.run_editor_signal.connect(self.run_case, Qt.QueuedConnection) devices = [] if self.is_running: self.stop_case() try: devices = self.tester.devices() except Exception as e: self.add_info_console("<font color='red'>" + str(e) + "</font>") if not devices: # There is no device connected self.message_box.warning(self, "Message", "Please connect the device to your computer.", QMessageBox.Ok) return # get case data count if self.case_id is not None: self.case_data_count = self.case_data_manage.get_case_data_count(self.case_id) self.device_and_data_signal.emit(devices, self.case_data_count) self.add_device_widget.show() def run_case(self, devices, data_line_number): # change icon stop_icon = QIcon() stop_icon.addPixmap(QPixmap(self.config.images + '/stop.png'), QIcon.Normal, QIcon.Off) self.run_btn.setIcon(stop_icon) self.run_btn.setText("Stop") self.is_running = True if not devices: return self.tester.select_devices(devices) self.data_line = data_line_number self.run() # run def stop_case(self): # set icon run_icon = QIcon() run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off) self.run_btn.setIcon(run_icon) self.run_btn.setText("Run") self.is_running = False try: self.tester.stop() self.tester.stop_server() except Exception as e: self.add_info_console("<font color='red'>" + str(e) + "</font>") def run(self): """ run case content :return: """ case_content = self.editor_text_edit.toPlainText().strip() case_data = None try: if (self.case_id is not None) and (self.case_data_count > 0): # case data exist case_data = self.case_data_manage.get_run_format_data(self.case_id) # get all case data self.debug_runner.reset() self.debug_runner._data = case_data # set case data self.debug_runner.parse(case_content) logger.debug("Debug beginning") self.debug_runner.execute(case_content, self.data_line) except Exception as e: logger.exception(str(e)) self.add_info_console("<font color='red'>" + str(e) + "</font>") self.stop_case() def save_case(self, event=None): """ save case :return: """ case_name = self.case_name_line_edit.text().strip() # Case Name content = self.editor_text_edit.toPlainText() # Case Content if self.check_null(): if event: event.ignore() return tags = self.get_tag_list() if self.check_tag_name(): # check unrecognized tag names return if self.case_id: self.case.name = case_name self.case.content = content self.case.tags = tags try: # update case and case data if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible(): self.case.last_modify_time = datetime.datetime.now() # update time self.case_manager.update_case(self.case_id, self.case_data_widget.case_data_list, self.case_data_widget.delete_data_ids) del self.case_data_widget.delete_data_ids[:] self.case_data_widget.has_modify = False else: self.case.last_modify_time = datetime.datetime.now() # update time self.dBCommandLineHelper.update_case() except Exception as e: logger.exception(str(e)) self.message_box.information(self, "Update Case Error", "Update case Fail.\nError Info:\n" + str(e), QMessageBox.Ok) else: try: # insert case and save case data if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible(): case = self.case_manager.insert_case(case_name, content, tags, self.case_data_widget.case_data_list, self.case_data_widget.delete_data_ids) del self.case_data_widget.delete_data_ids[:] self.case_data_widget.has_modify = False else: case = self.dBCommandLineHelper.insert_case_with_tags(case_name, content, tags) self.id_line_edit.setText(str(case.id)) self.case_id = self.id_line_edit.text().strip() self.set_case_edit_data() except Exception as e: logger.exception(str(e)) self.message_box.information(self, "Add Case Error", "Add case Fail.\nError Info:\n" + str(e), QMessageBox.Ok) self.refresh_signal.emit() # refresh the main table def check_null(self): """ check the required options :return: """ is_none = False type_info = '' case_name = self.case_name_line_edit.text().strip() content = self.editor_text_edit.toPlainText().strip() if not case_name: is_none = True type_info += "Case Name" if not content: is_none = True if not type_info: type_info += "Content" else: type_info += ", Content" if is_none: self.message_box.warning(self, "Message", type_info + " is required.", QMessageBox.Ok) return is_none def editor_adapter(self): """ get keywords for the completer and the highlighter :return: """ if self.case_id: self.parse_import_as() func_dict = self.debug_runner.core.kw_func # get default functions cmp = Completer(self.debug_runner) self.editor_text_edit.set_completer(cmp) # highlighter kw_list = [] for func_name, func in func_dict.items(): kw_list.append(func_name) self.high_lighter = MyHighlighter(self.editor_text_edit, kw_list) self.editor_text_edit.set_highlighter(self.high_lighter) def parse_import_as(self): """ parse all the 'import' and 'as' block in the case content :return: """ self.debug_runner.core.kw_func.clear() self.debug_runner.core.kw_func = {**self.debug_runner.core.default_func} content_list = self.dBCommandLineHelper.query_case_by_id(self.case_id).content.split("\n") if not content_list: return for line in content_list: if line.strip().find("import") == 0: # parse 'import' try: self.debug_runner.core.parse_line(line) except Exception as e: self.add_info_console("<font color='red'>" + str(e) + "</font>") elif " as " in line.strip(): # parse 'as' try: self.debug_runner.core.parse_line(line) except Exception as e: self.add_info_console("<font color='red'>" + str(e) + "</font>") def set_tag_name_completer(self): """ set completer to tag_names_line_edit :return: """ # change button icon add_icon = QIcon() add_icon.addPixmap(QPixmap(self.config.images + '/add.png'), QIcon.Normal, QIcon.Off) self.add_tag_button.setIcon(add_icon) self.add_tag_button.setToolTip("add tag") self.tag_names_line_edit.setPlaceholderText("Tag Names") self.tag_layout.insertWidget(0, self.tag_names_line_edit) self.tag_list = self.dBCommandLineHelper.query_tag_all() # get all tags tag_name_list = [] for tag in self.tag_list: tag_name_list.append(tag.name) cmp = TagCompleter(tag_name_list) self.tag_names_line_edit.setCompleter(cmp) def check_tag_name(self): """ check tag name,return unrecognized tag names :return: """ tag_name_list = self.tag_names_line_edit.text().strip().split(";") unrecognized_tag_names = "" has_unrecognized = False for tag_name in tag_name_list: if not tag_name.strip(): continue tag = self.dBCommandLineHelper.query_tag_by_name(tag_name.strip()) if not tag: unrecognized_tag_names += "\"" + tag_name + "\"" + "、" if not unrecognized_tag_names: return has_unrecognized has_unrecognized = True unrecognized_tag_names = unrecognized_tag_names[:-1] self.message_box.about(self, "Warning", "Tag name: " + unrecognized_tag_names + " unrecognized, please add it first.") return has_unrecognized
class AddCaseWidget(QWidget): select_case_signal = pyqtSignal(list, name="select_case_signal") def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.dBCommandLineHelper = DBCommandLineHelper() ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'add_case.ui') uic.loadUi(ui_file_path, self) screen = QDesktopWidget().screenGeometry() self.resize(screen.width() / 5 * 2, screen.height() / 5 * 2) self.search_button = SearchButton() self.tag_names_line_edit = TagLineEdit("tag_names_line_edit", self.search_button) self.tag_names_line_edit_adapter() self.tag_list = None self.result_widget = RunnerTableWidget( self.dBCommandLineHelper.query_case_all(), []) self.result_table_layout.insertWidget(0, self.result_widget) self.message_box = QMessageBox() self.search_button.clicked.connect(self.search_event) self.selectcasebtn.clicked.connect(self.select_event) self.casecancelbtn.clicked.connect(self.close) def search_event(self): """ search tags by tag name, and show the result in the table widget :return: """ self.result_widget.setParent(None) self.result_table_layout.removeWidget(self.result_widget) tag_names = self.tag_names_line_edit.text().strip() # tag_names is None if not tag_names: case_list = self.dBCommandLineHelper.query_case_all() self.result_widget = RunnerTableWidget(case_list, []) self.result_table_layout.insertWidget(0, self.result_widget) return # tag_names is not None tag_names = tag_names.split(';') for tag_name in tag_names: if not tag_name.strip(): # remove null tag tag_names.remove(tag_name.strip()) continue case_list = self.dBCommandLineHelper.query_case_by_tag_names( [tag_name.strip() for tag_name in tag_names]) self.result_widget = RunnerTableWidget(case_list, []) self.result_table_layout.insertWidget(0, self.result_widget) def select_event(self): """ handle the select event :return: """ self.result_widget.get_checked_data() if not self.result_widget.checked_cases_message: self.message_box.warning(self, "Message", "Please choose cases first.", QMessageBox.Ok) return id_list = [] for item in self.result_widget.checked_cases_message: id_list.append(int(item["case_id"])) self.select_case_signal.emit(id_list) self.close() # close AddCase def tag_names_line_edit_adapter(self): """ settings for tag_names_line_edit such as completer, placeholder text :return: """ self.tag_names_line_edit.setPlaceholderText("Tag names") self.search_layout.insertWidget(0, self.tag_names_line_edit) self.tag_list = self.dBCommandLineHelper.query_tag_all( ) # get all tags tag_name_list = [] for tag in self.tag_list: tag_name_list.append(tag.name) cmp = TagCompleter(tag_name_list) self.tag_names_line_edit.setCompleter(cmp)
class RunWidget(QWidget): running = False device_list_signal = pyqtSignal(list, name="device_list_signal") cases = [] def __init__(self, tester, *args, **kwargs): super().__init__(*args, **kwargs) ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'case_run.ui') uic.loadUi(ui_file_path, self) # set icon run_icon = QIcon() self.tester = tester self.config = self.tester.get_config() run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off) self.run_stop_btn.setIcon(run_icon) add_icon = QIcon() add_icon.addPixmap(QPixmap(self.config.images + '/add.png'), QIcon.Normal, QIcon.Off) self.addbtn.setIcon(add_icon) self.message_box = QMessageBox() self.dBCommandLineHelper = DBCommandLineHelper() self.addbtn.clicked.connect(self.click_add_case) self.run_stop_btn.clicked.connect(self.click_run_stop_btn) self.add_case_widget = None self.add_device_widget = None self.splitter = None self.case_widget = RunnerTableWidget([], [0]) self.log_area = Console() self.splitter_setting() self.status_listener = CaseRunStatusListener() self.status_listener.listener_msg_signal.connect( self.update_case_name_color, Qt.QueuedConnection) self.tester.add_run_status_listener(self.status_listener) def splitter_setting(self): """ set splitter :return: """ if self.splitter: self.splitter = None self.splitter = QSplitter(Qt.Vertical) self.splitter.setHandleWidth(1) # add "case_widget" and "log_area" to splitter self.splitter.addWidget(self.case_widget) self.splitter.addWidget(self.log_area) # set the initial scale: 4:1 self.splitter.setStretchFactor(0, 4) self.splitter.setStretchFactor(1, 1) self.case_table_layout.addWidget(self.splitter) def click_add_case(self): """ click the button to show add case widget :return: """ self.add_case_widget = AddCaseWidget() self.add_case_widget.select_case_signal.connect( self.show_cases, Qt.QueuedConnection) self.add_case_widget.setWindowModality(Qt.ApplicationModal) self.add_case_widget.show() def click_run_stop_btn(self): """ start or stop to run case :return: """ devices = [] if self.running: self.stop_case() return if not self.cases: # cases is null self.message_box.warning(self, "Message", "Please add cases first.", QMessageBox.Ok) return try: devices = self.tester.devices() except Exception as e: self.add_log("<font color='red'>" + str(e) + "</font>") if not devices: # There is no device connected self.message_box.warning( self, "Message", "Please connect the device to your computer.", QMessageBox.Ok) return self.add_device_widget = AddDeviceWidget() self.add_device_widget.setWindowModality(Qt.ApplicationModal) self.add_device_widget.add_log_signal.connect(self.add_log, Qt.QueuedConnection) self.add_device_widget.run_case_signal.connect(self.run_case, Qt.QueuedConnection) self.device_list_signal.connect( self.add_device_widget.add_radio_to_widget, Qt.QueuedConnection) self.add_device_widget.show() try: self.device_list_signal.emit(devices) except Exception as e: self.add_log("<font color='red'><pre>" + str(e) + "</pre></font>") def add_log(self, log_info): """ add log to log_area :return: """ if self.log_area is None: return self.log_area.append(log_info) def update_case_name_color(self, msg, is_passed): """ update case's font color according to the case's result pass: green; fail: red :param is_passed: :param msg: :return: """ if msg.status == 601: self.add_log("<font color='green'> Start to install agent.</font>") elif msg.status == 602: self.add_log("<font color='green'> Install agent success.</font>") elif msg.status == 603: self.add_log("<font color='red'> Install agent Fail." + "\r Error Info:\r<pre>" + msg.message + "</pre></font>") elif msg.status == 701: self.add_log("<font color='green'> Start agent.</font>") elif msg.status == 702: self.add_log("<font color='green'> Stop agent.</font>") elif msg.status == 703: self.add_log("<font color='red'> Agent error." + "\r Error Info:\r<pre>" + msg.message + "</pre></font>") for row_index in range(self.case_widget.dataTableWidget.rowCount()): case_id_item = self.case_widget.dataTableWidget.item( row_index, 1) # get case id from dataTableWidget if msg.status == 2: # test end if is_passed: self.add_log( "<font color='green'> All cases are Passed.</font>") self.stop_case() break if case_id_item.text() != str(msg.case_id): continue self.case_widget.dataTableWidget.selectRow(row_index) if msg.status == 101: # default: case pass self.update_green(row_index) elif msg.status == 500: self.update_red(row_index) self.add_log("<font color='red'> Case Failed, case id: " + str(msg.case_id) + "</font>") self.add_log("<pre><font color='red'>" + str(msg.message) + "</font></pre>") def run_case(self, devices): kw_case_list = [] if not self.cases: return for case_id in self.cases: kw_case = KWCase() case = self.dBCommandLineHelper.query_case_by_id(case_id) kw_case.id = case.id kw_case.name = case.name kw_case.content = case.content kw_case.data = case.data kw_case_list.append(kw_case) # set icon stop_icon = QIcon() stop_icon.addPixmap(QPixmap(self.config.images + '/stop.png'), QIcon.Normal, QIcon.Off) self.run_stop_btn.setIcon(stop_icon) self.run_stop_btn.setText("Stop") self.running = True if not devices: return try: self.tester.select_devices(devices) self.tester.run(kw_case_list) except Exception as e: self.stop_case() self.add_log(str(e)) def stop_case(self): run_icon = QIcon() run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off) self.run_stop_btn.setIcon(run_icon) # change icon self.run_stop_btn.setText("Run") self.running = False try: self.tester.stop() self.tester.stop_server() except Exception as e: self.add_log(str(e)) def show_cases(self, id_list): """ show cases in RunnerTableWidget according to id list :param id_list: :return: """ self.case_table_layout.removeWidget(self.splitter) case_list = [] self.cases = id_list for case_id in id_list: case = self.dBCommandLineHelper.query_case_by_id(case_id) case_list.append(case) self.case_widget = RunnerTableWidget(case_list, [0]) self.splitter_setting() # reload splitter
class CaseDataManager: def __init__(self): self.db_helper = DBCommandLineHelper() def get_case_data_count(self, case_id): case_data_list = self.get_run_format_data(case_id) return len(case_data_list) def get_case_data(self, case_id): case_data_list = [] case = self.db_helper.query_case_by_id(case_id) header_relation_list = eval(case.header_relation) if case.header_relation else [] case_data_list.append(header_relation_list) if case.data_relation is not None and case.data_relation: data_relation_list = eval(case.data_relation) for data_relation in data_relation_list: temp_data_list = [] for data_id in data_relation: case_data = CaseData() if data_id: temp_case_data = self.db_helper.query_case_data(id=int(data_id)) case_data.id = temp_case_data.id case_data.data = temp_case_data.data case_data.init_data = temp_case_data.data temp_data_list.append(case_data) case_data_list.append(temp_data_list) return case_data_list def get_run_format_data(self, case_id): case_data_list = [] data_dict = self.filter_data(case_id) new_data_relation_list = data_dict['new_data_relation'] key_name = data_dict['key_name'] if new_data_relation_list: # 格式化过滤后的数据 case_data_list = self.get_format_data_row(new_data_relation_list, key_name) return case_data_list def filter_data(self, case_id): data_dict = {} new_data_relation_list = [] case = self.db_helper.query_case_by_id(case_id) key_name = [] key_index = [] if case.header_relation and case.data_relation: data_relation_list = eval(case.data_relation) header_relation_list = eval(case.header_relation) # 获取header for index, key in enumerate(header_relation_list): if key: key_index.append(index) key_name.append(key) if key_index and data_relation_list: for data_relation in data_relation_list: new_data_relation = [] for index in key_index: new_data_relation.append(data_relation[index]) if not self.is_empty_list(new_data_relation): # 去除空行 new_data_relation_list.append(new_data_relation) data_dict['key_name'] = key_name data_dict['new_data_relation'] = new_data_relation_list return data_dict def is_empty_list(self, data_list): data_str = ''.join(data_list) if data_str: return False else: return True def get_format_data_row(self, data_relation_list, key_name): ''' 获取运行 case data 格式化 :param data_relation_list: :param key_name: :return: ''' case_data_list = [] for new_data_relation in data_relation_list: case_data_dict = {} for index, data_id in enumerate(new_data_relation): if data_id: case_data = self.db_helper.query_case_data(id=int(data_id)) case_data_dict[key_name[index]] = case_data.data else: case_data_dict[key_name[index]] = '' data = DataRow() data.__dict__ = case_data_dict case_data_list.append(data) return case_data_list def get_format_case_data(self, row_count, column_count, case_id): ''' table 展示case data 格式化 :param row_count: :param column_count: :param case_id: :return: ''' case_data_list = [] db_case_data_list = [] if case_id: db_case_data_list = self.get_case_data(case_id) # header: db_case_data_len = len(db_case_data_list) for row_num in range(0, row_count): temp_list = [] for column_num in range(0, column_count): if db_case_data_list and row_num < db_case_data_len and column_num < len(db_case_data_list[row_num]): temp_list.append(db_case_data_list[row_num][column_num]) else: if row_num == 0: temp_list.append('') else: temp_list.append(CaseData()) case_data_list.append(temp_list) return case_data_list def save_case_data(self, case_id, case_data_list, delete_data_ids): case = self.db_helper.query_case_by_id(case_id) case_relation_list = [] header_relation_list = case_data_list[0] for case_data in case_data_list[1:]: for case_data_detail in case_data: # if type(case_data_detail) == CaseData: if case_data_detail.id and case_data_detail.data != case_data_detail.init_data and case_data_detail.data != '': # 修改 self.db_helper.update_case_data(case_data_detail.id, case_data_detail.data) elif case_data_detail.data == '' or case_data_detail.data is None and case_data_detail.id: # 删除 self.db_helper.delete_case_data(id=case_data_detail.id) case_data_detail.id = None case_data_detail.data = '' elif case_data_detail.id is None and case_data_detail.data: # 添加 检验id 值 add_case_data = self.db_helper.insert_case_data(data=case_data_detail.data) case_data_detail.id = add_case_data.id case_data_detail.init_data = case_data_detail.data # 获取 case relation for case_data in case_data_list[1:]: temp_list = [] for case_data_detail in case_data: if type(case_data_detail) == CaseData: id = '' if case_data_detail.id is None else str(case_data_detail.id) temp_list.append(id) else: temp_list.append(case_data_detail) case_relation_list.append(temp_list) case.data_relation = self.list_to_str(case_relation_list, 2) case.header_relation = self.list_to_str(header_relation_list, 1) self.db_helper.update_case() # 删除 case data if delete_data_ids: self.db_helper.batch_delete_case_data(delete_data_ids) def list_to_str(self, data_list, dimension): ''' two-dimensional array to string string [[],[],[]] :return: ''' if dimension == 1: # 一维数组 data_relation_str = '[' for column in data_list: data_relation_str = data_relation_str + '\'' + column + '\',' data_relation_str = data_relation_str[:len(data_relation_str) - 1] data_relation_str += ']' return data_relation_str elif dimension == 2: # 二维数组 data_relation_str = '[' for data in data_list: data_relation_str += '[' for column in data: data_relation_str = data_relation_str + '\'' + column + '\',' data_relation_str = data_relation_str[:len(data_relation_str) - 1] data_relation_str += '],' data_relation_str = data_relation_str[:len(data_relation_str) - 1] data_relation_str += ']' return data_relation_str else: pass
tag_names = tag_names + ',' + tag.name self.setItem(row, 4, QTableWidgetItem(tag_names[1:])) self.resizeColumnsToContents() # Adjust the width according to the content self.horizontalHeader().setStretchLastSection(True) def horsection_clicked(self, index): if index == 0: if self.check_all: check_status = Qt.Unchecked self.check_all = False else: check_status = Qt.Checked self.check_all = True for row in range(0, self.rowCount()): check_box_item = self.item(row, 0) check_box_item.setCheckState(check_status) if __name__ == '__main__': app = QApplication(sys.argv) db_helper = DBCommandLineHelper() case_list = db_helper.query_case_by_tag_names(['我的']) # table_widget = RunnerTableWidget(case_list,[0,1])#隐藏第0/1列 table_widget = RunnerTableWidget(case_list) # 全部展示 dict = table_widget.get_checked_data() # 获取选中的checkbox window = QMainWindow() window.resize(500, 500) window.setCentralWidget(table_widget) window.show() app.exec_()
class TagEditorWidget(QWidget): def __init__(self, refresh_signal, tag_name=None, *args, **kwargs): super().__init__(*args, **kwargs) self.refresh_signal = refresh_signal self.db_helper = DBCommandLineHelper() ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'tag_editor.ui') uic.loadUi(ui_file_path, self) # set icon save_icon = QIcon() config = Config() save_icon.addPixmap(QPixmap(config.images + '/save.png'), QIcon.Normal, QIcon.Off) self.tag_save_btn.setIcon(save_icon) self.tag_save_btn.clicked.connect(self.tag_save) self.tag_id_line_edit.hide() # 隐藏line_edit self.tag_name_line_edit.setPlaceholderText("Tag Name") # 设置提示文字 self.tag_description_text_edit.setPlaceholderText('Tag Description') if tag_name: self.tag = self.db_helper.query_tag_by_name(tag_name) self.tag_id_line_edit.setText(str(self.tag.id)) self.tag_name_line_edit.setText(self.tag.name) self.tag_description_text_edit.setPlainText(self.tag.description) # self.tag_description_text_edit.setDocument(QTextDocument("Tag description")) # 设置提示文字 def closeEvent(self, close_even): if self.tag_id_line_edit.text() != '': if self.tag.name != self.tag_name_line_edit.text() or self.tag.description != self.tag_description_text_edit.toPlainText(): reply = QMessageBox.information(self, 'close window', 'Changes not saved, confirm close?', QMessageBox.Yes, QMessageBox.No) if reply != QMessageBox.Yes: close_even.ignore() return else: if self.tag_id_line_edit.text() != '' or self.tag_description_text_edit.toPlainText() != '': reply = QMessageBox.information(self, 'close window', 'Changes not saved, confirm close?', QMessageBox.Yes, QMessageBox.No) if reply != QMessageBox.Yes: close_even.ignore() return self.refresh_signal.emit() def tag_save(self): tag_id = self.tag_id_line_edit.text() tag_name = self.tag_name_line_edit.text() tag_description = self.tag_description_text_edit.toPlainText() if tag_name == '' or tag_description == '': QMessageBox.warning(self, 'tag editor', 'tag name and description can\'t be empty') else: if len(tag_name) > 8: QMessageBox.warning(self, 'tag editor', 'tag name is not greater than 8 characters') else: if tag_id: self.tag.name = tag_name self.tag.description = tag_description self.db_helper.update_tag() QMessageBox.information(self, 'tag editor', 'tag update success')#todo 是否添加刷新 else: tag = self.db_helper.query_tag_by_name(tag_name) if tag is None: tag = self.db_helper.insert_tag(tag_name, tag_description) self.tag_id_line_edit.setText(str(tag.id)) self.tag = tag QMessageBox.information(self, 'tag editor', 'tag insert success')#todo 是否添加刷新 else: QMessageBox.warning(self, 'tag editor', 'tag has existed')
class CaseManager: CASE_TABLE_NAME = "case" TAG_TABLE_NAME = "tag" CASE_TAG_TABLE_NAME = "case_tag" CASE_DATA_TABLE_NAME = "case_data" CASE_TABLE_NAME_FILE = CASE_TABLE_NAME + ".csv" TAG_TABLE_NAME_FILE = TAG_TABLE_NAME + ".csv" CASE_TAG_TABLE_NAME_FILE = CASE_TAG_TABLE_NAME + ".csv" CASE_DATA_TABLE_NAME_FILE = CASE_DATA_TABLE_NAME + ".csv" db_helper = DBCommandLineHelper() tag_file_data = [] case_tag_file_data = [] case_file_data = [] case_data_file_data = [] conflict_tag_name = [] conflict_tag_message_dict = [] def __init__(self): self.case_data_manager = CaseDataManager() def update_case(self, case_id, case_data_list, delete_data_ids): ''' 更新case :return: ''' self.db_helper.update_case() self.case_data_manager.save_case_data(case_id, case_data_list, delete_data_ids) def insert_case(self, case_name, content, tags, case_data_list, delete_data_ids): ''' 插入case :return: ''' case = self.db_helper.insert_case_with_tags(case_name, content, tags) self.case_data_manager.save_case_data(case.id, case_data_list, delete_data_ids) return case # 解压zip文件 def unzip(self, path): zip = zipfile.ZipFile(path) filelist = zip.namelist() for file in filelist: f_handle = open(file, "wb") f_handle.write(zip.read(file)) f_handle.close() zip.close() # 添加文件到已有的zip包中 def addzip(self, path): f = zipfile.ZipFile(path, 'w', zipfile.ZIP_DEFLATED) f.write(self.CASE_TABLE_NAME_FILE) f.write(self.TAG_TABLE_NAME_FILE) f.write(self.CASE_TAG_TABLE_NAME_FILE) f.write(self.CASE_DATA_TABLE_NAME_FILE) f.close() self.remove_data_file() def remove_data_file(self): os.remove(os.path.join(os.getcwd(), self.CASE_TABLE_NAME_FILE)) os.remove(os.path.join(os.getcwd(), self.TAG_TABLE_NAME_FILE)) os.remove(os.path.join(os.getcwd(), self.CASE_TAG_TABLE_NAME_FILE)) os.remove(os.path.join(os.getcwd(), self.CASE_DATA_TABLE_NAME_FILE)) def export_data(self, path, case_id_list): cases_id = ','.join(case_id_list) result = self.db_helper.get_table_data_by_cases_id(cases_id) self.trans_to_csv(result) self.addzip(path) def trans_to_csv(self, result): case_data_frame = pd.DataFrame(data=list(result[self.CASE_TABLE_NAME]), columns=result[self.CASE_TABLE_NAME].keys()) case_data_frame.to_csv(os.path.join(os.getcwd(), self.CASE_TABLE_NAME_FILE), encoding="utf-8", index=False) tag_data_frame = pd.DataFrame(data=list(result[self.TAG_TABLE_NAME]), columns=result[self.TAG_TABLE_NAME].keys()) tag_data_frame.to_csv(os.path.join(os.getcwd(), self.TAG_TABLE_NAME_FILE), encoding="utf-8", index=False) case_tag_data_frame = pd.DataFrame(data=list(result[self.CASE_TAG_TABLE_NAME]), columns=result[self.CASE_TAG_TABLE_NAME].keys()) case_tag_data_frame.to_csv(os.path.join(os.getcwd(), self.CASE_TAG_TABLE_NAME_FILE), encoding="utf-8", index=False) case_data_data_frame = pd.DataFrame(data=list(result[self.CASE_DATA_TABLE_NAME]), columns=result[self.CASE_DATA_TABLE_NAME].keys()) case_data_data_frame.to_csv(os.path.join(os.getcwd(), self.CASE_DATA_TABLE_NAME_FILE), encoding="utf-8", index=False) # 导入数据 def import_data(self, path): self.unzip(path) self.tag_file_data = pd.read_csv(os.path.join(os.getcwd(), self.TAG_TABLE_NAME_FILE)) self.case_tag_file_data = pd.read_csv(os.path.join(os.getcwd(), self.CASE_TAG_TABLE_NAME_FILE)) self.case_tag_file_data['has_changed'] = False self.case_file_data = pd.read_csv(os.path.join(os.getcwd(), self.CASE_TABLE_NAME_FILE)) self.case_data_file_data = pd.read_csv(os.path.join(os.getcwd(), self.CASE_DATA_TABLE_NAME_FILE)) self.remove_data_file() self.check_data() if self.conflict_tag_message_dict: return self.conflict_tag_message_dict else: self.merge_data() return None def merge_conflict_data_callback(self, updata_tag_message_list, callback): result = self.merge_conflict_data(updata_tag_message_list) callback(result) # 返回冲突修改后的信息 进行数据合并 def merge_conflict_data(self, updata_tag_message_list): for tag_message in updata_tag_message_list: self.tag_file_data.loc[self.tag_file_data["id"] == tag_message['id'], 'name'] = tag_message['name'] self.tag_file_data.loc[self.tag_file_data["id"] == tag_message['id'], 'description'] = tag_message[ 'description'] self.merge_data() return True def check_data(self): tag_data = self.db_helper.get_table_data(self.TAG_TABLE_NAME) tag_db_data = pd.DataFrame(data=list(tag_data), columns=tag_data.keys()) del self.conflict_tag_name[:] for name in self.tag_file_data['name']: # 获取冲突tag名称 if name in tag_db_data['name'].values: self.conflict_tag_name.append(name) if len(self.conflict_tag_name) > 0: # 获取tag冲突详细信息 conflict_message_frame = tag_db_data[tag_db_data["name"].isin(self.conflict_tag_name)] src_tag_message_frame = self.tag_file_data[self.tag_file_data["name"].isin(self.conflict_tag_name)] conflict_message_frame.loc[:, 'src_id'] = src_tag_message_frame["id"].values conflict_message_frame.loc[:, 'src_name'] = src_tag_message_frame["name"].values conflict_message_frame.loc[:, 'src_description'] = src_tag_message_frame[ "description"].values self.conflict_tag_message_dict = conflict_message_frame.T.to_dict() return self.conflict_tag_message_dict # 合并数据 def merge_data(self): for i in range(len(self.tag_file_data)): old_tag_id = self.tag_file_data["id"][i] tag_name = self.tag_file_data["name"][i] tag = self.db_helper.query_tag_by_name(tag_name) # 检查tag是否存在 存在的不插入 获取ID ,不存在的插入 生成ID if tag is None: tag_description = self.tag_file_data["description"][i] tag = self.db_helper.insert_tag(tag_name, tag_description) new_tag_id = tag.id self.case_tag_file_data.loc[ (self.case_tag_file_data['tag_id'] == old_tag_id) & (self.case_tag_file_data['has_changed'] == False), [ 'tag_id', 'has_changed']] = [new_tag_id, True] # 插入case data: data_id_dict = {} for i in range(len(self.case_data_file_data)): old_data_id = self.case_data_file_data['id'][i] data = self.case_data_file_data['data'][i] case_data = self.db_helper.insert_case_data(data) new_data_id = case_data.id data_id_dict[old_data_id] = new_data_id # 插入case 插入case_tag case_list = [] for i in range(len(self.case_file_data)): old_case_id = self.case_file_data["id"][i] tag_ids = self.case_tag_file_data[self.case_tag_file_data["case_id"] == old_case_id]["tag_id"].values tags = [] for tag_id in tag_ids: tag = self.db_helper.query_tag_by_id(int(tag_id)) tags.append(tag) case = Case() case.name = self.case_file_data["name"][i] case.content = self.case_file_data["content"][i] case.tags = tags case.header_relation = self.case_file_data["header_relation"][i] # data_relation 更新 if self.case_file_data["data_relation"][i] and type(self.case_file_data["data_relation"][i]) is str: data_relation_list = eval(self.case_file_data["data_relation"][i]) # if len(data_relation_list) > 1: for data_relation in data_relation_list: for index,data_id in enumerate(data_relation): if data_id and data_id_dict[int(data_id)]: # index = data_relation.index(data_id) data_relation[index] = str(data_id_dict[int(data_id)]) case.data_relation = self.case_data_manager.list_to_str(data_relation_list,2) # self.case_file_data["data_relation"][i] = case.data_relation case_list.append(case) self.db_helper.batch_insert_case_with_tags(case_list) def add_tag(self, tag_name, tag_description): # TODO 前端确保标识不存在 result = {} tag = self.db_helper.query_tag_by_name(tag_name) if tag: result['status'] = -1 result['message'] = '标识已存在' else: self.db_helper.insert_tag(tag_name, tag_description) result['status'] = 0 result['message'] = '标识插入成功' return result def query_case_data(self, case=None, case_id=None):
def __init__(self, refresh_signal, tester, case_id=None, *args, **kwargs): super().__init__(*args, **kwargs) ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'case_editor.ui') uic.loadUi(ui_file_path, self) self.dBCommandLineHelper = DBCommandLineHelper() self.tester = tester self.config = self.tester.get_config() self.debug_runner = self.tester.get_debug_runner() self.case_id = case_id self.refresh_signal = refresh_signal self.init_ui() self.is_log_show = True self.is_running = False self.tag_list = [] self.parsed_line_list = [] self.case = None self.high_lighter = None self.tag_manage_widget = None self.add_device_widget = None self.message_box = QMessageBox() self.add_tag_button = SearchButton() self.tag_names_line_edit = TagLineEdit("tag_names_line_edit", self.add_tag_button) self.set_tag_name_completer() self.splitter = QSplitter(Qt.Vertical) self.splitter.setHandleWidth(1) # set handle width self.editor_text_edit = TextEdit(self.debug_runner.core) # case content TextEdit self.console = Console() # Add the 'editor text edit' and 'console' to splitter self.splitter.addWidget(self.editor_text_edit) self.splitter.addWidget(self.console) # Set the initial scale: 4:1 self.splitter.setStretchFactor(0, 4) self.splitter.setStretchFactor(1, 1) self.editor_layout.addWidget(self.splitter) self.import_list_signal.connect(self.editor_text_edit.get_import_from_content, Qt.QueuedConnection) self.editor_text_edit.parse_error_info_signal.connect(self.add_info_console, Qt.QueuedConnection) self.editor_adapter() # set completer and highlighter self.set_case_edit_data() # update case # run status listener self.status_listener = EditorRunStatusListener() self.status_listener.editor_listener_msg_signal.connect(self.result_handle, Qt.QueuedConnection) self.debug_runner.listener = self.status_listener self.data_line = None # button event self.save_btn.clicked.connect(self.save_case) self.run_btn.clicked.connect(self.run_btn_event) self.console_btn.clicked.connect(self.log_show_hide_event) self.edit_data_btn.clicked.connect(self.add_case_data) self.add_tag_button.clicked.connect(self.choose_event) # case data self.case_manager = CaseManager() self.case_data_manage = CaseDataManager() self.case_data_count = 0 # init case data count self.is_case_data_modify = False
class TagManageWidget(QWidget): selected_tag_names_signal = pyqtSignal(str, name="selected_tag_names_signal") refresh_signal = pyqtSignal(name="refresh_signal") def __init__(self, config, *args, **kwargs): super().__init__(*args, **kwargs) ui_dir_path = os.path.dirname(__file__) ui_file_path = os.path.join(ui_dir_path, 'tag_manage_widget.ui') uic.loadUi(ui_file_path, self) self.db_helper = DBCommandLineHelper() self.message_box = QMessageBox() self.tag_names_line_edit = TagNamesLineEdit() self.tag_names_line_edit.setPlaceholderText("Tag Names") self.cmp = None self.set_completer() self.selected_tag_names_layout.insertWidget(0, self.tag_names_line_edit) add_icon = QIcon() add_icon.addPixmap(QPixmap(config.images + '/add.png'), QIcon.Normal, QIcon.Off) self.new_tag_btn.setIcon(add_icon) self.tag_editor = None self.tag_list = None self.set_tag_list_widget() # init data self.select_btn.clicked.connect(self.select_event) self.cancel_btn.clicked.connect(self.close) self.new_tag_btn.clicked.connect(self.new_tag_event) self.refresh_signal.connect(self.set_tag_list_widget, Qt.QueuedConnection) def new_tag_event(self): """ show tag editor :return: """ self.tag_editor = TagEditorWidget(self.refresh_signal) self.tag_editor.setWindowModality(Qt.ApplicationModal) self.tag_editor.show() def select_event(self): """ handle select event :return: """ selected_tag_names = self.tag_names_line_edit.text().strip() if not selected_tag_names: self.close() return if self.check_tag_name(): return self.selected_tag_names_signal.emit(selected_tag_names) self.close() def set_tag_list_widget(self): """ init tag_list_widget data and onclick event :return: """ self.tag_list_widget.clear() self.tag_list = self.db_helper.query_tag_all() for tag in self.tag_list: self.tag_list_widget.addItem(tag.name) self.tag_list_widget.itemClicked.connect( lambda: self.list_widget_item_clicked(self.tag_list_widget.currentItem())) item = self.tag_list_widget.item(0) if not item: return item.setSelected(True) self.set_completer() # reset completer's tag name list def list_widget_item_clicked(self, tag_list_widget_item): """ handle list widget item click event :param tag_list_widget_item: :return: """ tag_name_set = set() selected_tag_names = "" selected_line_edit_text = self.tag_names_line_edit.text().strip() tag_names_list = selected_line_edit_text.split(";") # origin tag names for tag_name in tag_names_list: if tag_name.strip(): tag_name_set.add(tag_name.strip() + ";") tag_name_set.add(tag_list_widget_item.text() + ';') # add clicked tag name for tag_name in tag_name_set: selected_tag_names += tag_name self.tag_names_line_edit.is_completer = False self.tag_names_line_edit.clear() self.tag_names_line_edit.setText(selected_tag_names) self.tag_names_line_edit.is_completer = True def check_tag_name(self): """ check tag name,return unrecognized tag names :return: """ tag_name_list = self.tag_names_line_edit.text().strip().split(";") unrecognized_tag_names = "" has_unrecognized = False for tag_name in tag_name_list: if not tag_name.strip(): continue tag = self.db_helper.query_tag_by_name(tag_name.strip()) if not tag: unrecognized_tag_names += "\"" + tag_name + "\"" + "、" if not unrecognized_tag_names: return has_unrecognized has_unrecognized = True unrecognized_tag_names = unrecognized_tag_names[:-1] self.message_box.about(self, "Warning", "Tag name: " + unrecognized_tag_names + " unrecognized, please add it first.") return has_unrecognized def set_completer(self): """ set completer to tag_names_line_edit :return: """ self.tag_list = self.db_helper.query_tag_all() # get all tag tag_name_list = [] for tag in self.tag_list: tag_name_list.append(tag.name) cmp = TagCompleter(tag_name_list) self.tag_names_line_edit.setCompleter(cmp)