From 0ea7d4e65488484a4b7eef3ddefd45a861e06d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AF=9B=E9=B9=8F?= <729164035@qq.com> Date: Fri, 2 Aug 2024 15:38:05 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E7=9A=84?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MangoServer/PyAutoTest/auto_test/auto_ui/service/ui_test_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MangoServer/PyAutoTest/auto_test/auto_ui/service/ui_test_run.py b/MangoServer/PyAutoTest/auto_test/auto_ui/service/ui_test_run.py index b97fbb1c..c0d9551a 100644 --- a/MangoServer/PyAutoTest/auto_test/auto_ui/service/ui_test_run.py +++ b/MangoServer/PyAutoTest/auto_test/auto_ui/service/ui_test_run.py @@ -168,7 +168,7 @@ class UiTestRun: ChatConsumer.active_send(SocketDataModel( code=200, msg=f'{ClientNameEnum.DRIVER.value}:收到用例数据,准备开始执行自动化任务!', - user=username if username else self.user_obj.username, + user=username if username else self.username, is_notice=ClientTypeEnum.ACTUATOR.value, data=data, )) -- Gitee From 15b507b57bc44ff5569625e5070c7566edbcb410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AF=9B=E9=B9=8F?= <729164035@qq.com> Date: Fri, 2 Aug 2024 15:54:00 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=85=B3=E9=97=AD=E6=B5=8F=E8=A7=88=E5=99=A8?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MangoActuator/autotest/ui/service/page_steps.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MangoActuator/autotest/ui/service/page_steps.py b/MangoActuator/autotest/ui/service/page_steps.py index 49e6faf5..389e387e 100644 --- a/MangoActuator/autotest/ui/service/page_steps.py +++ b/MangoActuator/autotest/ui/service/page_steps.py @@ -38,8 +38,10 @@ class PageSteps(StepElements): await self.steps_main() except MangoActuatorError as error: if error.code == 310: - await self.context.close() - await self.page.close() + if self.context: + await self.context.close() + if self.page: + await self.page.close() self.context = None self.page = None await ClientWebSocket().async_send( -- Gitee From e316b24c05a0a981b1c84e4fca5785dad71e5972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AF=9B=E9=B9=8F?= <729164035@qq.com> Date: Fri, 2 Aug 2024 17:08:02 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=85=B3=E9=97=AD=E6=B5=8F=E8=A7=88=E5=99=A8?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../autotest/ui/base_tools/web/assertion.py | 88 +++++----- .../auto_test/auto_ui/service/ui_test_run.py | 4 +- .../views/uitest/page-steps/details/config.ts | 106 ++++++++++++ .../views/uitest/page-steps/details/index.vue | 110 +----------- .../src/views/uitest/page/elements/config.ts | 68 ++------ .../src/views/uitest/page/elements/index.vue | 162 +++++++++++------- 6 files changed, 278 insertions(+), 260 deletions(-) diff --git a/MangoActuator/autotest/ui/base_tools/web/assertion.py b/MangoActuator/autotest/ui/base_tools/web/assertion.py index 1d531d6d..8cee65cc 100644 --- a/MangoActuator/autotest/ui/base_tools/web/assertion.py +++ b/MangoActuator/autotest/ui/base_tools/web/assertion.py @@ -4,7 +4,7 @@ # @Time : 2023-04-26 22:25 # @Author : 毛鹏 -from playwright.async_api import Locator, expect +from playwright.async_api import Locator, expect as exp from exceptions.ui_exception import ElementIsEmptyError from tools.message.error_msg import ERROR_MSG_0021 @@ -16,42 +16,42 @@ class PlaywrightAssertion: @staticmethod async def w_not_to_be_empty(actual: Locator): """元素不为空""" - await expect(actual).not_to_be_empty() + await exp(actual).not_to_be_empty() @staticmethod async def w_not_to_be_enabled(actual: Locator): """元素不启用""" - await expect(actual).not_to_be_enabled() + await exp(actual).not_to_be_enabled() @staticmethod async def w_not_to_be_focused(actual: Locator): """元素不聚焦""" - await expect(actual).not_to_be_focused() + await exp(actual).not_to_be_focused() @staticmethod async def w_not_to_be_hidden(actual: Locator): """元素不可隐藏""" - await expect(actual).not_to_be_hidden() + await exp(actual).not_to_be_hidden() @staticmethod async def w_not_to_be_in_viewport(actual: Locator): """元素不在视窗中""" - await expect(actual).not_to_be_in_viewport() + await exp(actual).not_to_be_in_viewport() @staticmethod async def w_not_to_be_visible(actual: Locator): """元素不可见""" - await expect(actual).not_to_be_visible() + await exp(actual).not_to_be_visible() @staticmethod async def w_not_to_contain_text(actual: Locator, expect: str): """元素不包含文本""" - await expect(actual).not_to_contain_text(expect) + await exp(actual).not_to_contain_text(expect) @staticmethod async def w_not_to_have_class(actual: Locator, expect: str): """元素没有阶级""" - await expect(actual).not_to_have_class(expect) + await exp(actual).not_to_have_class(expect) @staticmethod async def w_to_have_count(actual: Locator, expect: str): @@ -60,7 +60,7 @@ class PlaywrightAssertion: assert int(expect) == 0 if expect is None: expect = 0 - await expect(actual).to_have_count(int(expect)) + await exp(actual).to_have_count(int(expect)) @staticmethod async def w_to_element_count(actual: Locator, count: int): @@ -69,7 +69,7 @@ class PlaywrightAssertion: assert actual is None else: if actual: - await expect(actual).to_have_count(int(count)) + await exp(actual).to_have_count(int(count)) else: raise ElementIsEmptyError(*ERROR_MSG_0021) @@ -78,7 +78,7 @@ class PlaywrightAssertion: """元素是存在""" if actual is None: assert False - await expect(actual).to_have_count(1) + await exp(actual).to_have_count(1) @staticmethod async def w_to_element_not_exists(actual: Locator): @@ -88,17 +88,17 @@ class PlaywrightAssertion: @staticmethod async def w_to_be_checked(actual: Locator): """复选框已选中""" - await expect(actual).to_be_checked() + await exp(actual).to_be_checked() @staticmethod async def w_to_be_disabled(actual: Locator): """元素已禁用""" - await expect(actual).to_be_disabled() + await exp(actual).to_be_disabled() @staticmethod async def w_not_to_be_editable(actual: Locator): """元素已启用""" - await expect(actual).to_be_editable() + await exp(actual).to_be_editable() @staticmethod async def w_to_be_empty(actual: Locator | list | None): @@ -108,130 +108,130 @@ class PlaywrightAssertion: elif not actual: assert True else: - await expect(actual).to_be_empty() + await exp(actual).to_be_empty() @staticmethod async def w_to_be_visible(actual: Locator): """元素可见""" - await expect(actual).to_be_visible() + await exp(actual).to_be_visible() # @staticmethod # async def w_not_to_have_actuals(actual: Locator, actuals: list): # """选择已选择选项""" - # await expect(actual).to_have_actuals(actuals) + # await exp(actual).to_have_actuals(actuals) # @staticmethod # def w_not_to_have_attribute(locating: Locator, name: str, actual: str): # """元素不具有属性""" - # expect(locating).not_to_have_attribute(name, actual) + # exp(locating).not_to_have_attribute(name, actual) # @staticmethod # @staticmethod # def w_not_to_have_css(locating: Locator, name: str, actual: str): # """元素不使用CSS""" - # expect(locating).not_to_have_css(name, actual) + # exp(locating).not_to_have_css(name, actual) # @staticmethod # def w_not_to_have_id(locating: Locator, _id: str): # """元素没有ID""" - # expect(locating).not_to_have_id(_id) + # exp(locating).not_to_have_id(_id) # # @staticmethod # def w_not_to_have_js_property(locating: Locator, name: str, actual): # """元素不具有js属性""" - # expect(locating).not_to_have_js_property(name, actual) + # exp(locating).not_to_have_js_property(name, actual) # # @staticmethod # def w_not_to_have_text(locating: Locator, expected: str): # """元素没有文本""" - # expect(locating).not_to_have_text(expected) + # exp(locating).not_to_have_text(expected) # @staticmethod # def w_not_to_have_actual(locating: Locator, actual: str): # """元素无价值""" - # expect(locating).not_to_have_actual(actual) + # exp(locating).not_to_have_actual(actual) # # def w_to_be_attached(self, hidden_text: str): # """待连接""" - # expect(self.page.get_by_text(hidden_text)).to_be_attached() + # exp(self.page.get_by_text(hidden_text)).to_be_attached() # # def w_to_be_editable(self, hidden_text: str): # """可编辑""" # locator = self.page.get_by_role("textbox") - # expect(locator).to_be_editable() + # exp(locator).to_be_editable() # def w_to_be_enabled(self, hidden_text: str): # """为空""" # locator = self.page.locator("button.submit") - # expect(locator).to_be_enabled() + # exp(locator).to_be_enabled() # def w_to_be_focused(self, hidden_text: str): # """聚焦""" # locator = self.page.get_by_role("textbox") - # expect(locator).to_be_focused() + # exp(locator).to_be_focused() # # def w_to_be_hidden(self, hidden_text: str): # """隐藏""" # locator = self.page.locator('.my-element') - # expect(locator).to_be_hidden() + # exp(locator).to_be_hidden() # # def w_to_be_in_viewport(self, hidden_text: str): # """待在视口中""" # locator = self.page.get_by_role("button") # # Make sure at least some part of element intersects viewport. - # expect(locator).to_be_in_viewport() + # exp(locator).to_be_in_viewport() # # Make sure element is fully outside of viewport. - # expect(locator).not_to_be_in_viewport() + # exp(locator).not_to_be_in_viewport() # # Make sure that at least half of the element intersects viewport. - # expect(locator).to_be_in_viewport(ratio=0.5) + # exp(locator).to_be_in_viewport(ratio=0.5) # # def w_to_contain_text(self, hidden_text: str): # """包含文本""" # locator = self.page.locator('.title') - # expect(locator).to_contain_text("substring") - # expect(locator).to_contain_text(re.compile(r"\d messages")) + # exp(locator).to_contain_text("substring") + # exp(locator).to_contain_text(re.compile(r"\d messages")) # # def w_to_have_attribute(self, hidden_text: str): # """具有属性""" # locator = self.page.locator("input") - # expect(locator).to_have_attribute("type", "text") + # exp(locator).to_have_attribute("type", "text") # # def w_to_have_class(self, hidden_text: str): # """到保存类别""" # locator = self.page.locator("#component") - # expect(locator).to_have_class(re.compile(r"selected")) - # expect(locator).to_have_class("selected row") + # exp(locator).to_have_class(re.compile(r"selected")) + # exp(locator).to_have_class("selected row") # # def w_to_have_count(self, hidden_text: str): # """有计数""" # locator = self.page.locator("list > .component") - # expect(locator).to_have_count(3) + # exp(locator).to_have_count(3) # # def w_to_have_css(self, hidden_text: str): # """使用CSS""" # locator = self.page.get_by_role("button") - # expect(locator).to_have_css("display", "flex") + # exp(locator).to_have_css("display", "flex") # # def w_to_have_id(self, hidden_text: str): # """到id""" # locator = self.page.get_by_role("textbox") - # expect(locator).to_have_id("lastname") + # exp(locator).to_have_id("lastname") # # def w_to_have_js_property(self, hidden_text: str): # """拥有js属性""" # locator = self.page.locator(".component") - # expect(locator).to_have_js_property("loaded", True) + # exp(locator).to_have_js_property("loaded", True) # # def w_to_have_text(self, hidden_text: str): # """有文本""" # locator = self.page.locator(".title") - # expect(locator).to_have_text(re.compile(r"Welcome, Test User")) - # expect(locator).to_have_text(re.compile(r"Welcome, .*")) + # exp(locator).to_have_text(re.compile(r"Welcome, Test User")) + # exp(locator).to_have_text(re.compile(r"Welcome, .*")) # # def w_to_have_actual(self, hidden_text: str): # """有价值""" # locator = self.page.locator("input[type=number]") - # expect(locator).to_have_actual(re.compile(r"[0-9]")) + # exp(locator).to_have_actual(re.compile(r"[0-9]")) diff --git a/MangoServer/PyAutoTest/auto_test/auto_ui/service/ui_test_run.py b/MangoServer/PyAutoTest/auto_test/auto_ui/service/ui_test_run.py index c0d9551a..a8c48f46 100644 --- a/MangoServer/PyAutoTest/auto_test/auto_ui/service/ui_test_run.py +++ b/MangoServer/PyAutoTest/auto_test/auto_ui/service/ui_test_run.py @@ -141,9 +141,9 @@ class UiTestRun: case_step_details_id=None, project_product=data['project_product_id'], url=page_obj.url, - type=page_obj.type, + type=page_obj.project_product.client_type, equipment_config=self.__get_web_config( - test_object.value) if page_obj.type == DriveTypeEnum.WEB.value else self.__get_app_config(), + test_object.value) if page_obj.project_product.client_type == DriveTypeEnum.WEB.value else self.__get_app_config(), environment_config=self.__environment_config(test_object, page_obj.project_product_id) ) page_steps_model.element_list.append(ElementModel( diff --git a/mango-console/src/views/uitest/page-steps/details/config.ts b/mango-console/src/views/uitest/page-steps/details/config.ts index e8a5c788..974d2e59 100644 --- a/mango-console/src/views/uitest/page-steps/details/config.ts +++ b/mango-console/src/views/uitest/page-steps/details/config.ts @@ -1,4 +1,5 @@ import { reactive } from 'vue' +import { Message } from '@arco-design/web-vue' export interface Item { value: string label: string @@ -74,6 +75,111 @@ export const columns = reactive([ }, ]) +export const customForm = reactive([ + { + label: 'key', + key: 'key', + value: '', + type: 'input', + required: true, + placeholder: '请输入key', + validator: function () { + return true + }, + }, + { + label: 'value', + key: 'value', + value: '', + type: 'input', + required: true, + placeholder: '请输入value', + validator: function () { + return true + }, + }, +]) +export const sqlForm = reactive([ + { + label: 'key_list', + key: 'key_list', + value: '', + type: 'textarea', + required: true, + placeholder: '请输入sql查询结果的key_list', + validator: function () { + if (this.value !== '') { + try { + this.value = JSON.parse(this.value) + } catch (e) { + Message.error('key_list值请输入json数据类型') + return false + } + } + return true + }, + }, + { + label: 'sql语句', + key: 'sql', + value: '', + type: 'textarea', + required: true, + placeholder: '请输入sql', + validator: function () { + return true + }, + }, +]) +export const assForm = reactive([ + { + label: '断言类型', + key: 'ass_type', + value: '', + type: 'cascader', + required: true, + placeholder: '请选择断言类型', + validator: function () { + return true + }, + }, + { + label: '选择元素', + key: 'ele_name', + value: '', + placeholder: '请选择locating', + required: false, + type: 'select', + validator: function () { + return true + }, + }, +]) +export const eleForm = reactive([ + { + label: '元素操作', + key: 'ope_type', + value: '', + type: 'cascader', + required: true, + placeholder: '请选择对元素的操作', + validator: function () { + return true + }, + }, + { + label: '选择元素', + key: 'ele_name', + value: '', + placeholder: '请选择locating', + required: false, + type: 'select', + validator: function () { + return true + }, + }, +]) + export const formItems = reactive([ { label: '步骤类型', diff --git a/mango-console/src/views/uitest/page-steps/details/index.vue b/mango-console/src/views/uitest/page-steps/details/index.vue index ada71e00..259ef7f2 100644 --- a/mango-console/src/views/uitest/page-steps/details/index.vue +++ b/mango-console/src/views/uitest/page-steps/details/index.vue @@ -201,7 +201,7 @@ import { fieldNames } from '@/setting' import { getFormItems } from '@/utils/datacleaning' import { usePageData } from '@/store/page-data' - import { columns, formItems, Item } from './config' + import { assForm, columns, customForm, eleForm, formItems, Item, sqlForm } from './config' import { deleteUiPageStepsDetailed, getUiPageStepsDetailed, @@ -246,125 +246,25 @@ (item) => item.key === 'ele_name' || formItems.some((item) => item.key === 'ope_type') ) ) { - formItems.push( - { - label: '元素操作', - key: 'ope_type', - value: '', - type: 'cascader', - required: true, - placeholder: '请选择对元素的操作', - validator: function () { - return true - }, - }, - { - label: '选择元素', - key: 'ele_name', - value: '', - placeholder: '请选择locating', - required: false, - type: 'select', - validator: function () { - return true - }, - } - ) + formItems.push(...eleForm) } } else if (event === 1) { if (!formItems.some((item) => item.key === 'ass_type')) { - formItems.push( - { - label: '断言类型', - key: 'ass_type', - value: '', - type: 'cascader', - required: true, - placeholder: '请选择断言类型', - validator: function () { - return true - }, - }, - { - label: '选择元素', - key: 'ele_name', - value: '', - placeholder: '请选择locating', - required: false, - type: 'select', - validator: function () { - return true - }, - } - ) + formItems.push(...assForm) } } else if (event === 2) { if ( !formItems.some((item) => item.key === 'sql') || !formItems.some((item) => item.key === 'key_list') ) { - formItems.push( - { - label: 'key_list', - key: 'key_list', - value: '', - type: 'textarea', - required: true, - placeholder: '请输入sql查询结果的key_list', - validator: function () { - if (this.value !== '') { - try { - this.value = JSON.parse(this.value) - } catch (e) { - Message.error('key_list值请输入json数据类型') - return false - } - } - return true - }, - }, - { - label: 'sql语句', - key: 'sql', - value: '', - type: 'textarea', - required: true, - placeholder: '请输入sql', - validator: function () { - return true - }, - } - ) + formItems.push(...sqlForm) } } else { if ( !formItems.some((item) => item.key === 'key') || !formItems.some((item) => item.key === 'value') ) { - formItems.push( - { - label: 'key', - key: 'key', - value: '', - type: 'input', - required: true, - placeholder: '请输入key', - validator: function () { - return true - }, - }, - { - label: 'value', - key: 'value', - value: '', - type: 'input', - required: true, - placeholder: '请输入value', - validator: function () { - return true - }, - } - ) + formItems.push(...customForm) } } } diff --git a/mango-console/src/views/uitest/page/elements/config.ts b/mango-console/src/views/uitest/page/elements/config.ts index 4c0eaebe..ab78cdfb 100644 --- a/mango-console/src/views/uitest/page/elements/config.ts +++ b/mango-console/src/views/uitest/page/elements/config.ts @@ -101,73 +101,43 @@ export const formItems: FormItem[] = reactive([ placeholder: '请输入元素下标', }, ]) -export const formItems1: FormItem[] = reactive([ + +export const assForm = reactive([ { - label: '步骤类型', - key: 'type', - value: 0, - type: 'radio', + label: '断言类型', + key: 'ass_type', + value: '', + type: 'cascader', required: true, - placeholder: '请选择对元素的操作类型', + placeholder: '请选择断言类型', validator: function () { return true }, }, - +]) +export const eleForm = reactive([ { label: '元素操作', key: 'ope_type', - value: null, + value: '', type: 'cascader', - required: false, + required: true, placeholder: '请选择对元素的操作', validator: function () { return true }, }, +]) + +export const formItems1 = reactive([ { - label: '元素操作值', - key: 'ope_value', - value: '', - type: 'textarea', - required: false, - placeholder: '请输入对元素的操作内容', - validator: function () { - if (this.value !== '') { - try { - this.value = JSON.parse(this.value) - } catch (e) { - Message.error('元素操作值请输入json数据类型') - return false - } - } - return true - }, - }, - { - label: '断言类型', - key: 'ass_type', - value: null, - type: 'cascader', - required: false, - placeholder: '请选择断言类型', - }, - { - label: '断言值', - key: 'ass_value', + label: '步骤类型', + key: 'type', value: '', - type: 'textarea', - required: false, - placeholder: '请输入断言内容', + type: 'radio', + required: true, + placeholder: '请选择对元素的操作类型', validator: function () { - if (this.value !== '') { - try { - this.value = JSON.parse(this.value) - } catch (e) { - Message.error('断言值请输入json数据类型') - return false - } - } return true }, }, diff --git a/mango-console/src/views/uitest/page/elements/index.vue b/mango-console/src/views/uitest/page/elements/index.vue index 59267233..62904f03 100644 --- a/mango-console/src/views/uitest/page/elements/index.vue +++ b/mango-console/src/views/uitest/page/elements/index.vue @@ -126,24 +126,6 @@ style="width: 380px" allow-search allow-clear - :disabled="data.isDisabledOpe" - /> - - - @@ -154,7 +136,6 @@ :default-value="item.value" v-model="item.value" allow-clear - :disabled="data.isDisabledOpe" /> + @@ -200,6 +196,7 @@ } from '@/api/uitest' import { getSystemEnumExp } from '@/api/system' import { useEnvironment } from '@/store/modules/get-environment' + import { assForm, eleForm } from '@/views/uitest/page/elements/config' const uEnvironment = useEnvironment() const pageData: any = usePageData() @@ -216,11 +213,10 @@ actionTitle: '添加元素', eleExp: [], totalSize: 0, + type: 0, data: [], ope: [], ass: [], - isDisabledOpe: false, - isDisabledAss: true, plainOptions: [ { label: '操作', value: 0 }, { label: '断言', value: 1 }, @@ -358,14 +354,88 @@ } function changeStatus(event: number) { - data.isDisabledOpe = event == 1 - data.isDisabledAss = event == 0 - formItems1.forEach((item) => { - item.value = null - }) - formItems1[0].value = event + data.type = event + for (let i = formItems1.length - 1; i >= 0; i--) { + if (formItems1[i].key !== 'type') { + formItems1.splice(i, 1) + } + } + if (event === 0) { + if ( + !formItems1.some( + (item) => item.key === 'ele_name' || formItems1.some((item) => item.key === 'ope_type') + ) + ) { + formItems1.push(...eleForm) + } + } else { + if (!formItems1.some((item) => item.key === 'ass_type')) { + formItems1.push(...assForm) + } + } + } + function upDataAssValue(value: any) { + const inputItem = findItemByValue(data.ass, value) + if (inputItem) { + const parameter: any = inputItem.parameter + Object.keys(parameter).forEach((key) => { + parameter[key] = '' + }) + if (!formItems1.some((item) => item.key === 'ass_value')) { + formItems1.push({ + label: '断言值', + key: 'ass_value', + value: JSON.stringify(parameter), + type: 'textarea', + required: true, + placeholder: '请输入断言内容', + validator: function () { + if (this.value !== '') { + try { + this.value = JSON.parse(this.value) + } catch (e) { + Message.error(this.placeholder || '') + return false + } + } + return true + }, + }) + } + } } + function upDataOpeValue(value: any) { + const inputItem = findItemByValue(data.ope, value) + if (inputItem) { + const parameter: any = inputItem.parameter + Object.keys(parameter).forEach((key) => { + parameter[key] = '' + }) + + if (!formItems1.some((item) => item.key === 'ope_value')) { + formItems1.push({ + label: '元素操作值', + key: 'ope_value', + value: JSON.stringify(parameter), + type: 'textarea', + required: true, + placeholder: '请输入对元素的操作内容', + validator: function () { + if (this.value !== '') { + try { + this.value = JSON.parse(this.value) + } catch (e) { + Message.error('元素操作值请输入json数据类型') + return false + } + } + return true + }, + }) + } + } + } function onDataForm1() { if (formItems1.every((it) => (it.validator ? it.validator() : true))) { modalDialogRef1.value?.toggle() @@ -374,7 +444,7 @@ value['id'] = data.id value['page_id'] = pageData.record.id value['project_product_id'] = pageData.record.project_product.id - value['type'] = pageData.record.type + value['type'] = data.type putUiUiElementTest(value) .then((res) => { Message.success(res.msg) @@ -392,21 +462,6 @@ children?: Item[] } - function upDataAssValue(value: any) { - const inputItem = findItemByValue(data.ass, value) - if (inputItem) { - const parameter: any = inputItem.parameter - Object.keys(parameter).forEach((key) => { - parameter[key] = '' - }) - formItems1.forEach((item: any) => { - if (item.key === 'ass_value') { - item.value = JSON.stringify(parameter) - } - }) - } - } - function findItemByValue(data: Item[], value: string): Item | undefined { for (let i = 0; i < data.length; i++) { const item = data[i] @@ -423,22 +478,9 @@ return undefined } - function upDataOpeValue(value: string) { - const inputItem = findItemByValue(data.ope, value) - if (inputItem) { - const parameter: any = inputItem.parameter - Object.keys(parameter).forEach((key) => { - parameter[key] = '' - }) - formItems1.forEach((item: any) => { - if (item.key === 'ope_value') { - item.value = JSON.stringify(parameter) - } - }) - } - } - function onDebug(record: any) { + changeStatus(0) + if (!uEnvironment.selectValue) { Message.error('请先选择测试环境') return -- Gitee From 85758255eb956bb6f9c2f3c1f5f72f9e7fb1d1e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AF=9B=E9=B9=8F?= <729164035@qq.com> Date: Fri, 2 Aug 2024 17:10:21 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=AD=E8=A8=80?= =?UTF-8?q?=E7=9A=84=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tools/assertion/public_assertion.py | 130 +++++++++--------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/MangoServer/PyAutoTest/tools/assertion/public_assertion.py b/MangoServer/PyAutoTest/tools/assertion/public_assertion.py index 5728e345..45e75beb 100644 --- a/MangoServer/PyAutoTest/tools/assertion/public_assertion.py +++ b/MangoServer/PyAutoTest/tools/assertion/public_assertion.py @@ -10,167 +10,167 @@ class WhatIsItAssertion: """是什么""" @staticmethod - def p_is_not_none(value): + def p_is_not_none(actual): """不是null""" - assert_that(value).is_not_none() + assert_that(actual).is_not_none() @staticmethod - def p_is_none(value): + def p_is_none(actual): """是null""" - assert_that(value).is_none() + assert_that(actual).is_none() @staticmethod - def p_is_empty(value): + def p_is_empty(actual): """是空字符串""" - assert_that(value).is_empty() + assert_that(actual).is_empty() @staticmethod - def p_is_not_empty(value): + def p_is_not_empty(actual): """不是空符串""" - assert_that(value).is_not_empty() + assert_that(actual).is_not_empty() @staticmethod - def p_is_false(value): + def p_is_false(actual): """是false""" - assert_that(value).is_false() + assert_that(actual).is_false() @staticmethod - def p_is_true(value): + def p_is_true(actual): """是true""" - assert_that(value).is_true() + assert_that(actual).is_true() @staticmethod - def p_is_alpha(value): + def p_is_alpha(actual): """是字母""" - assert_that(value).is_alpha() + assert_that(actual).is_alpha() @staticmethod - def p_is_digit(value): + def p_is_digit(actual): """是数字""" - assert_that(value).is_digit() + assert_that(actual).is_digit() class WhatIsEqualToAssertion: """等于什么""" @staticmethod - def p_is_equal_to(value, expect): + def p_is_equal_to(actual, expect): """等于expect""" - assert_that(value).is_equal_to(expect) + assert_that(actual).is_equal_to(expect) @staticmethod - def p_is_not_equal_to(value, expect): + def p_is_not_equal_to(actual, expect): """不等于expect""" - assert_that(value).is_not_equal_to(expect) + assert_that(actual).is_not_equal_to(expect) @staticmethod - def p_is_length(value, expect): + def p_is_length(actual, expect): """长度等于expect""" - assert_that(value).is_length(expect) + assert_that(actual).is_length(expect) class ContainAssertion: """包含什么""" @staticmethod - def p_contains(value, expect): + def p_contains(actual, expect): """包含expect""" - assert_that(value).contains(**expect) + assert_that(actual).contains(**expect) @staticmethod - def p_is_equal_to_ignoring_case(value, expect): + def p_is_equal_to_ignoring_case(actual, expect): """忽略大小写等于expect""" - assert_that(value).is_equal_to_ignoring_case(expect) + assert_that(actual).is_equal_to_ignoring_case(expect) @staticmethod - def p_contains_ignoring_case(value, expect): + def p_contains_ignoring_case(actual, expect): """包含忽略大小写expect""" - assert_that(value).contains_ignoring_case(expect) + assert_that(actual).contains_ignoring_case(expect) @staticmethod - def p_contains_only(value, expect): + def p_contains_only(actual, expect): """仅包含expect""" - assert_that(value).contains_only(expect) + assert_that(actual).contains_only(expect) @staticmethod - def p_does_not_contain(value, expect): + def p_does_not_contain(actual, expect): """不包含expect""" - assert_that(value).does_not_contain(expect) + assert_that(actual).does_not_contain(expect) class MatchingAssertion: """匹配什么""" @staticmethod - def p_is_in(value, expect): + def p_is_in(actual, expect): """在expect里面""" - assert_that(value).is_in(**expect) + assert_that(actual).is_in(**expect) @staticmethod - def p_is_not_in(value, expect): + def p_is_not_in(actual, expect): """不在expect里面""" - assert_that(value).is_not_in(expect) + assert_that(actual).is_not_in(expect) @staticmethod - def p_starts_with(value, expect): + def p_starts_with(actual, expect): """以expect开头""" - assert_that(value).starts_with(expect) + assert_that(actual).starts_with(expect) @staticmethod - def p_ends_with(value, expect): + def p_ends_with(actual, expect): """以expect结尾""" - assert_that(value).ends_with(expect) + assert_that(actual).ends_with(expect) @staticmethod - def p_matches(value, expect): + def p_matches(actual, expect): """正则匹配等于expect""" - assert_that(value).matches(expect) + assert_that(actual).matches(expect) @staticmethod - def p_does_not_match(value, expect): + def p_does_not_match(actual, expect): """正则不匹配expect""" - assert_that(value).does_not_match(expect) + assert_that(actual).does_not_match(expect) class PublicAssertion(WhatIsItAssertion, ContainAssertion, MatchingAssertion, WhatIsEqualToAssertion): pass # @staticmethod - # def p_is_unicode(value): - # """value是unicode""" - # assert_that(value).is_unicode() + # def p_is_unicode(actual): + # """actual是unicode""" + # assert_that(actual).is_unicode() # @staticmethod - # def p_is_iterable(value): - # """value是可迭代对象""" - # assert_that(value).is_iterable() + # def p_is_iterable(actual): + # """actual是可迭代对象""" + # assert_that(actual).is_iterable() # @staticmethod - # def p_is_type_of(value, type_): + # def p_is_type_of(actual, type_): # """判断类型""" - # assert_that(value).is_type_of(eval(type_)) + # assert_that(actual).is_type_of(eval(type_)) # @staticmethod - # def p_is_instance_of(value, type_): + # def p_is_instance_of(actual, type_): # """是实例-未测试""" - # assert_that(value).is_instance_of(type_) + # assert_that(actual).is_instance_of(type_) # @staticmethod - # def p_is_subset_of(value, expect): + # def p_is_subset_of(actual, expect): # """在里面""" - # assert_that(value).is_subset_of(expect) + # assert_that(actual).is_subset_of(expect) # @staticmethod - # def p_contains_sequence(value, expect): + # def p_contains_sequence(actual, expect): # """包含序列""" - # assert_that(value).contains_sequence(expect) + # assert_that(actual).contains_sequence(expect) # @staticmethod - # def p_contains_duplicates(value): + # def p_contains_duplicates(actual): # """仅包含""" - # assert_that(value).contains_duplicates() + # assert_that(actual).contains_duplicates() # # @staticmethod - # def p_does_not_contain_duplicates(value): + # def p_does_not_contain_duplicates(actual): # """不包含重复项""" - # assert_that(value).does_not_contain_duplicates() + # assert_that(actual).does_not_contain_duplicates() # @staticmethod - # def p_is_upper(value): - # """value在什么上面""" - # assert_that(value).is_upper() + # def p_is_upper(actual): + # """actual在什么上面""" + # assert_that(actual).is_upper() -- Gitee From 726b65e47546f1f05f347a755e6573f858066d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AF=9B=E9=B9=8F?= <729164035@qq.com> Date: Fri, 2 Aug 2024 17:36:33 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=AD=E8=A8=80?= =?UTF-8?q?=E7=9A=84=E5=80=BC=EF=BC=8Capi=E7=9A=84=E4=B9=9F=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MangoActuator/desktop/window/window.py | 4 +-- .../auto_api/service/base_tools/dependence.py | 25 ++++++++++--------- .../auto_api/views/api_case_detailed.py | 1 - .../PyAutoTest/tools/view/model_crud.py | 5 ++-- .../src/views/apitest/case/details/index.vue | 8 +++--- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/MangoActuator/desktop/window/window.py b/MangoActuator/desktop/window/window.py index 1bf0662d..32bf15c8 100644 --- a/MangoActuator/desktop/window/window.py +++ b/MangoActuator/desktop/window/window.py @@ -11,7 +11,7 @@ from PySide6.QtCore import QThread import service_conn from enums.socket_api_enum import ToolsSocketEnum from enums.system_enum import CacheDataKey2Enum -from enums.tools_enum import CacheKeyEnum, CacheValueTypeEnum, SignalTypeEnum +from enums.tools_enum import CacheKeyEnum, CacheValueTypeEnum, SignalTypeEnum, ClientTypeEnum from tools.assertion import Assertion from tools.data_processor import RandomFileData from tools.data_processor.sql_cache import SqlCache @@ -58,7 +58,7 @@ class Window(Ui_MainWindow): send_list.append( {CacheDataKey2Enum.ASSERTION_METHOD.value: json.dumps(Assertion.get_methods(), ensure_ascii=False)}) from service_conn.socket_conn.client_socket import ClientWebSocket - ClientWebSocket().sync_send('设置缓存数据', func_name=ToolsSocketEnum.SET_OPERATION_OPTIONS.value, func_args=send_list) + ClientWebSocket().sync_send('设置缓存数据成功', func_name=ToolsSocketEnum.SET_OPERATION_OPTIONS.value,is_notice=ClientTypeEnum.WEB.value, func_args=send_list) # 接受信号的槽函数 def signalLabel6(self, text): diff --git a/MangoServer/PyAutoTest/auto_test/auto_api/service/base_tools/dependence.py b/MangoServer/PyAutoTest/auto_test/auto_api/service/base_tools/dependence.py index 83730d80..e4a845dd 100644 --- a/MangoServer/PyAutoTest/auto_test/auto_api/service/base_tools/dependence.py +++ b/MangoServer/PyAutoTest/auto_test/auto_api/service/base_tools/dependence.py @@ -112,13 +112,13 @@ class CaseMethod(CommonBase, PublicAssertion): if isinstance(res, list): for res_dict in res: for key, value in res_dict.items(): - self.set_cache(sql_obj.get('value'), str(value)) - log.info(f'{sql_obj.get("value")}sql写入的数据:{self.get_cache(sql_obj.get("value"))}') + self.set_cache(sql_obj.get('actual'), str(value)) + log.info(f'{sql_obj.get("actual")}sql写入的数据:{self.get_cache(sql_obj.get("actual"))}') def __posterior_response(self, response_text: dict, posterior_response: list[dict]): for i in posterior_response: value = self.get_json_path_value(response_text, i['key']) - self.set_cache(i['value'], value) + self.set_cache(i['actual'], value) @classmethod def __posterior_sleep(cls, sleep: str): @@ -130,8 +130,9 @@ class CaseMethod(CommonBase, PublicAssertion): try: if ass_response_value: for i in ass_response_value: - value = self.get_json_path_value(response_data, i['value']) - _dict = {'value': str(value)} + print(i) + value = self.get_json_path_value(response_data, i['actual']) + _dict = {'actual': str(value)} if i.get('expect'): try: _dict['expect'] = str(eval(i.get('expect'))) @@ -141,28 +142,28 @@ class CaseMethod(CommonBase, PublicAssertion): getattr(self, method)(**_dict) except AssertionError as error: log.warning(error) - self.ass_result.append({'断言类型': method, '预期值': _dict.get('expect'), '实际值': _dict.get('value')}) + self.ass_result.append({'断言类型': method, '预期值': _dict.get('expect'), '实际值': _dict.get('actual')}) raise ResponseValueAssError(*ERROR_MSG_0005) @retry(stop_max_attempt_number=5, wait_fixed=1000) def __assertion_sql(self, sql_list: list[dict]): - _dict = {'value': None} + _dict = {'actual': None} method = None try: if self.mysql_connect: for sql in sql_list: - value = self.mysql_connect.condition_execute(self.replace(sql.get('value'))) - if not value: + actual = self.mysql_connect.condition_execute(self.replace(sql.get('actual'))) + if not actual: raise SqlResultIsNoneError(*ERROR_MSG_0041) - if isinstance(value, list): - _dict = {'value': str(list(value[0].values())[0])} + if isinstance(actual, list): + _dict = {'actual': str(list(actual[0].values())[0])} if sql.get('expect'): _dict['expect'] = sql.get('expect') method = sql.get('method') getattr(self, method)(**_dict) except AssertionError as error: log.warning(error) - self.ass_result.append({'断言类型': method, '预期值': _dict.get('expect'), '实际值': _dict.get('value')}) + self.ass_result.append({'断言类型': method, '预期值': _dict.get('expect'), '实际值': _dict.get('actual')}) raise SqlAssError(*ERROR_MSG_0006) def __assertion_response_whole(self, actual, expect): diff --git a/MangoServer/PyAutoTest/auto_test/auto_api/views/api_case_detailed.py b/MangoServer/PyAutoTest/auto_test/auto_api/views/api_case_detailed.py index 06cbf48f..f52516ee 100644 --- a/MangoServer/PyAutoTest/auto_test/auto_api/views/api_case_detailed.py +++ b/MangoServer/PyAutoTest/auto_test/auto_api/views/api_case_detailed.py @@ -133,7 +133,6 @@ class ApiCaseDetailedViews(ViewSet): obj.case_sort = i['case_sort'] case_id = obj.case.id obj.save() - print(case_id) ApiCaseDetailedCRUD().callback(case_id) return ResponseData.success(RESPONSE_MSG_0013, ) diff --git a/MangoServer/PyAutoTest/tools/view/model_crud.py b/MangoServer/PyAutoTest/tools/view/model_crud.py index c375c3f9..aa692653 100644 --- a/MangoServer/PyAutoTest/tools/view/model_crud.py +++ b/MangoServer/PyAutoTest/tools/view/model_crud.py @@ -118,12 +118,13 @@ class ModelCRUD(GenericAPIView): if hasattr(self, 'callback'): from PyAutoTest.auto_test.auto_ui.views.ui_page_steps_detailed import UiPageStepsDetailedCRUD from PyAutoTest.auto_test.auto_ui.views.ui_case_steps_detailed import UiCaseStepsDetailedCRUD - # from PyAutoTest.auto_test.auto_api.views.api_case_detailed import ApiCaseDetailedCRUD + from PyAutoTest.auto_test.auto_api.views.api_case_detailed import ApiCaseDetailedCRUD, ApiCaseDetailed if isinstance(self, UiPageStepsDetailedCRUD): parent_id = request.data.get('page_step') elif isinstance(self, UiCaseStepsDetailedCRUD): parent_id = request.data.get('case') - + elif isinstance(self, ApiCaseDetailedCRUD): + parent_id = ApiCaseDetailed.objects.get(id=request.data.get('id')).case.id else: parent_id = request.data.get('id') if parent_id is None: diff --git a/mango-console/src/views/apitest/case/details/index.vue b/mango-console/src/views/apitest/case/details/index.vue index 1b993953..2063da4d 100644 --- a/mango-console/src/views/apitest/case/details/index.vue +++ b/mango-console/src/views/apitest/case/details/index.vue @@ -822,13 +822,13 @@ if ('10' === data.tabsKey) { data.selectDataObj.front_sql.push('请添加sql语句') } else if ('31' === data.tabsKey) { - data.selectDataObj.ass_response_value.push({ value: '', method: '', expect: '' }) + data.selectDataObj.ass_response_value.push({ actual: '', method: '', expect: '' }) } else if ('32' === data.tabsKey) { - data.selectDataObj.ass_sql.push({ value: '', method: '', expect: '' }) + data.selectDataObj.ass_sql.push({ actual: '', method: '', expect: '' }) } else if ('40' === data.tabsKey) { - data.selectDataObj.posterior_response.push({ key: '', value: '' }) + data.selectDataObj.posterior_response.push({ key: '', actual: '' }) } else if ('41' === data.tabsKey) { - data.selectDataObj.posterior_sql.push({ key: '', value: '' }) + data.selectDataObj.posterior_sql.push({ key: '', actual: '' }) } } -- Gitee From 470e67652a513102ad39532f78fbadec465845f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AF=9B=E9=B9=8F?= <729164035@qq.com> Date: Fri, 2 Aug 2024 17:58:11 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MangoActuator/tools/message/error_msg.py | 2 +- mango-console/src/views/uitest/case/details/index.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MangoActuator/tools/message/error_msg.py b/MangoActuator/tools/message/error_msg.py index 9c42689c..0b0db721 100644 --- a/MangoActuator/tools/message/error_msg.py +++ b/MangoActuator/tools/message/error_msg.py @@ -27,7 +27,7 @@ ERROR_MSG_0021 = (321, '元素未找到,请检查断言前操作是否正常 ERROR_MSG_0022 = (322, '页面无此元素,请检查传入的元素是否正确') ERROR_MSG_0023 = (323, 'iframe中未找到此元素,请检查元素表达式是否是正确的') ERROR_MSG_0024 = (324, '上传文件的元素必须要是input标签中的') -ERROR_MSG_0025 = (325, '用例步骤的数据取不到,请检查用例数据或联系管理员') +ERROR_MSG_0025 = (325, '用例步骤的数据取不到,请检查是否对步骤进行了修改,而用例未更新') ERROR_MSG_0026 = (326, '文件不存在') ERROR_MSG_0027 = ( 327, '您元素的操作内容中没有任何的数据,请检查:1.页面步骤详情中字段->元素操作值是否是空,是空可能是你删除了,也可能是执行器的操作选项没有同步需要点击执行器的同步发送缓存数据;2.元素表达式错误导致查询不到元素;') diff --git a/mango-console/src/views/uitest/case/details/index.vue b/mango-console/src/views/uitest/case/details/index.vue index 0922ac21..c543205d 100644 --- a/mango-console/src/views/uitest/case/details/index.vue +++ b/mango-console/src/views/uitest/case/details/index.vue @@ -4,7 +4,7 @@