mangoautomation 1.0.60__tar.gz → 1.1.21__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mangoautomation might be problematic. Click here for more details.

Files changed (65) hide show
  1. {mangoautomation-1.0.60/mangoautomation.egg-info → mangoautomation-1.1.21}/PKG-INFO +2 -10
  2. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/enums/_ui_enum.py +3 -1
  3. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/exceptions/error_msg.py +2 -2
  4. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/models/_ui_model.py +19 -16
  5. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/_async_element.py +83 -54
  6. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/_sync_element.py +85 -56
  7. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/async_web/__init__.py +1 -1
  8. {mangoautomation-1.0.60 → mangoautomation-1.1.21/mangoautomation.egg-info}/PKG-INFO +2 -10
  9. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/setup.py +1 -1
  10. mangoautomation-1.1.21/tests/get_ope.py +8 -0
  11. mangoautomation-1.0.60/tests/get_ope.py +0 -12
  12. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/LICENSE +0 -0
  13. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/MANIFEST.in +0 -0
  14. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/README.md +0 -0
  15. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/__init__.py +0 -0
  16. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/enums/__init__.py +0 -0
  17. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/enums/_base_enum.py +0 -0
  18. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/exceptions/__init__.py +0 -0
  19. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/exceptions/_exceptions.py +0 -0
  20. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/models/__init__.py +0 -0
  21. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/tools/__init__.py +0 -0
  22. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/tools/_mate.py +0 -0
  23. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/tools/_uiautodev.py +0 -0
  24. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/__init__.py +0 -0
  25. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/_base_data.py +0 -0
  26. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/_driver_object.py +0 -0
  27. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/android/__init__.py +0 -0
  28. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/android/_application.py +0 -0
  29. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/android/_assertion.py +0 -0
  30. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/android/_customization.py +0 -0
  31. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/android/_element.py +0 -0
  32. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/android/_equipment.py +0 -0
  33. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/android/_new_android.py +0 -0
  34. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/android/_page.py +0 -0
  35. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/ios/__init__.py +0 -0
  36. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/pc/__init__.py +0 -0
  37. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/pc/assertion.py +0 -0
  38. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/pc/customization.py +0 -0
  39. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/pc/element.py +0 -0
  40. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/pc/input_device.py +0 -0
  41. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/pc/new_windows.py +0 -0
  42. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/__init__.py +0 -0
  43. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/async_web/_assertion.py +0 -0
  44. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/async_web/_browser.py +0 -0
  45. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/async_web/_customization.py +0 -0
  46. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/async_web/_element.py +0 -0
  47. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/async_web/_input_device.py +0 -0
  48. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/async_web/_new_browser.py +0 -0
  49. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/async_web/_page.py +0 -0
  50. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/sync_web/__init__.py +0 -0
  51. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/sync_web/_assertion.py +0 -0
  52. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/sync_web/_browser.py +0 -0
  53. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/sync_web/_customization.py +0 -0
  54. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/sync_web/_element.py +0 -0
  55. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/sync_web/_input_device.py +0 -0
  56. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/sync_web/_new_browser.py +0 -0
  57. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation/uidrive/web/sync_web/_page.py +0 -0
  58. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation.egg-info/SOURCES.txt +0 -0
  59. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation.egg-info/dependency_links.txt +0 -0
  60. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation.egg-info/requires.txt +0 -0
  61. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/mangoautomation.egg-info/top_level.txt +0 -0
  62. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/setup.cfg +0 -0
  63. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/tests/__init__.py +0 -0
  64. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/tests/test_ui_and.py +0 -0
  65. {mangoautomation-1.0.60 → mangoautomation-1.1.21}/tests/test_ui_web.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.1
2
2
  Name: mangoautomation
3
- Version: 1.0.60
3
+ Version: 1.1.21
4
4
  Summary: 测试工具
5
5
  Home-page: https://gitee.com/mao-peng/testkit
6
6
  Author: 毛鹏
@@ -18,14 +18,6 @@ Requires-Dist: uiautomator2>=3.2.5
18
18
  Requires-Dist: mangotools>=1.1.42
19
19
  Requires-Dist: adbutils~=2.8.9
20
20
  Requires-Dist: uiautodev>=0.9.0
21
- Dynamic: author
22
- Dynamic: author-email
23
- Dynamic: classifier
24
- Dynamic: description
25
- Dynamic: home-page
26
- Dynamic: license-file
27
- Dynamic: requires-dist
28
- Dynamic: summary
29
21
 
30
22
  # testkit
31
23
 
@@ -73,10 +73,12 @@ class ElementOperationEnum(BaseEnum):
73
73
  ASS = 1
74
74
  SQL = 2
75
75
  CUSTOM = 3
76
+ CONDITION = 4
77
+ PYTHON_CODE = 5
76
78
 
77
79
  @classmethod
78
80
  def obj(cls):
79
- return {0: "操作", 1: "断言", 2: "SQL", 3: "参数"}
81
+ return {0: "元素操作", 1: "断言操作", 2: "SQL变量", 3: "自定义变量", 4: "条件判断", 5: "python代码"}
80
82
 
81
83
 
82
84
  class DeviceEnum(BaseEnum):
@@ -38,8 +38,8 @@ ERROR_MSG_0029 = (4029, '页面无元素【{}】,表达式:{}')
38
38
  ERROR_MSG_0030 = (4030, '断言时没有找到元素')
39
39
  ERROR_MSG_0031 = (4031, '元素未找到准备进行断言获取元素文本类容异常')
40
40
  ERROR_MSG_0032 = (4032, '元素【{}】的元素表达式定位有多个,或其他元素异常,请检查元素是否可用')
41
- ERROR_MSG_0036 = (4036, '公共参数sql在数据库中查询不到结果,sql:{}')
42
- ERROR_MSG_0038 = (4038, '公共参数的sql_key不是列表')
41
+ ERROR_MSG_0036 = (4036, 'sql参数在数据库中查询不到结果,sql:{}')
42
+ ERROR_MSG_0038 = (4038, 'sql参数的sql_key不是列表')
43
43
  ERROR_MSG_0040 = (
44
44
  340, '设备启动超时!请检查设备是否开启了:文件传输模式、开发者模式、usb调试,开启后请重新连接电脑,设备号:{}')
45
45
  ERROR_MSG_0041 = (4041, '查找页面元素【{}】时直接失败,报错信息:{}')
@@ -6,6 +6,7 @@
6
6
 
7
7
  from pydantic import BaseModel
8
8
 
9
+ from mangoautomation.enums import ElementOperationEnum
9
10
  from mangotools.models import MysqlConingModel, MethodModel
10
11
 
11
12
 
@@ -18,24 +19,24 @@ class EnvironmentConfigModel(BaseModel):
18
19
 
19
20
 
20
21
  class ElementListModel(BaseModel):
21
- exp: int | None
22
- loc: str | None
22
+ exp: int
23
+ loc: str
24
+ sub: int | None = None
25
+ is_iframe: int | None
23
26
 
24
27
 
25
28
  class ElementModel(BaseModel):
26
29
  id: int
27
- type: int
30
+ type: ElementOperationEnum
28
31
  name: str | None
29
32
  elements: list[ElementListModel] = []
30
33
  sleep: int | None
31
- sub: int | None
32
- is_iframe: int | None
33
34
  ope_key: str | None
34
- ope_value: list[MethodModel] | None
35
- key_list: list | None = None
36
- sql: str | None = None
37
- key: str | None = None
38
- value: str | None = None
35
+ ope_value: list[MethodModel] | None = None
36
+ sql_execute: list[dict] | None = None
37
+ custom: list[dict] | None = None
38
+ condition_value: dict | None = None
39
+ func: str | None = None
39
40
 
40
41
 
41
42
  class ElementListResultModel(BaseModel):
@@ -43,25 +44,27 @@ class ElementListResultModel(BaseModel):
43
44
  exp: int | None = None
44
45
  ele_quantity: int = 0
45
46
  element_text: str | None = None
47
+ sub: int | None = None
48
+ is_iframe: int | None
46
49
 
47
50
 
48
51
  class ElementResultModel(BaseModel):
49
52
  id: int
50
53
  name: str | None = None
51
54
  sleep: int | None = None
52
- sub: int | None = None
53
55
 
54
56
  type: int
55
57
  ope_key: str | None = None
56
- ope_value: dict = {}
58
+ ope_value: list[MethodModel] | None = None
59
+ sql_execute: list[dict] | None = None
60
+ custom: list[dict] | None = None
61
+ condition_value: dict | None = None
57
62
  ass_msg: str | None = None
58
- sql: str | None = None
59
- key_list: str | None = None
60
- key: str | None = None
61
- value: str | None = None
62
63
 
63
64
  elements: list[ElementListResultModel] = []
64
65
  status: int = 0
65
66
  error_message: str | None = None
66
67
  picture_path: str | None = None
67
68
  picture_name: str | None = None
69
+
70
+ next_node_id: int | None = None
@@ -28,8 +28,9 @@ class AsyncElement(AsyncWebDevice, AndroidDriver):
28
28
  super().__init__(base_data)
29
29
  self.drive_type = drive_type
30
30
  self.element_model: Optional[ElementModel | None] = None
31
- self.element_data: dict | None = None
32
31
  self.element_result_model: Optional[ElementResultModel | None] = None
32
+ self.element_list_model: list[ElementModel] = []
33
+ self.test_data = self.base_data.test_data
33
34
 
34
35
  async def open_device(self, is_open: bool = False):
35
36
  if self.drive_type == DriveTypeEnum.WEB.value:
@@ -42,21 +43,20 @@ class AsyncElement(AsyncWebDevice, AndroidDriver):
42
43
  self.base_data.log.debug(f'不存在这个类型,如果是非管理员看到这种提示,请联系管理员')
43
44
  raise Exception('不存在的设备类型')
44
45
 
45
- async def element_main(self, element_model: ElementModel, element_data: dict | None = None) -> ElementResultModel:
46
+ async def element_main(self,
47
+ element_model: ElementModel,
48
+ element_list_model: list[ElementModel]) -> ElementResultModel:
46
49
  self.element_model = element_model
47
- self.element_data = element_data
50
+ self.element_list_model = element_list_model
48
51
  self.element_result_model = ElementResultModel(
49
52
  id=self.element_model.id,
50
53
  name=self.element_model.name,
51
- sub=self.element_model.sub,
52
54
  sleep=self.element_model.sleep,
53
55
 
54
- type=self.element_model.type,
56
+ type=self.element_model.type.value,
55
57
  ope_key=self.element_model.ope_key,
56
- sql=self.element_model.sql,
57
- key_list=self.element_model.key_list,
58
- key=self.element_model.key,
59
- value=self.element_model.value,
58
+ sql_execute=self.element_model.sql_execute,
59
+ custom=self.element_model.custom,
60
60
 
61
61
  status=StatusEnum.FAIL.value,
62
62
  )
@@ -91,14 +91,18 @@ class AsyncElement(AsyncWebDevice, AndroidDriver):
91
91
  @async_retry()
92
92
  async def __main(self):
93
93
  self.base_data.verify_equipment(self.drive_type)
94
- if self.element_model.type == ElementOperationEnum.OPE.value:
94
+ if self.element_model.type == ElementOperationEnum.OPE:
95
95
  await self.__ope()
96
- elif self.element_model.type == ElementOperationEnum.ASS.value:
96
+ elif self.element_model.type == ElementOperationEnum.ASS:
97
97
  await self.__ass()
98
- elif self.element_model.type == ElementOperationEnum.SQL.value:
98
+ elif self.element_model.type == ElementOperationEnum.SQL:
99
99
  await self.__sql()
100
- elif self.element_model.type == ElementOperationEnum.CUSTOM.value:
100
+ elif self.element_model.type == ElementOperationEnum.CUSTOM:
101
101
  await self.__custom()
102
+ elif self.element_model.type == ElementOperationEnum.CONDITION:
103
+ await self.__condition()
104
+ elif self.element_model.type == ElementOperationEnum.PYTHON_CODE:
105
+ await self.__python_code()
102
106
  else:
103
107
  raise MangoAutomationError(*ERROR_MSG_0015)
104
108
 
@@ -106,11 +110,9 @@ class AsyncElement(AsyncWebDevice, AndroidDriver):
106
110
  try:
107
111
  for i in self.element_model.elements:
108
112
  i.loc = self.base_data.test_data.replace(i.loc)
109
- self.element_result_model.elements.append(ElementListResultModel(exp=i.exp, loc=i.loc))
113
+ i.sub = self.base_data.test_data.replace(i.sub)
110
114
  self.element_model.sleep = self.base_data.test_data.replace(self.element_model.sleep)
111
115
  self.element_result_model.sleep = self.element_model.sleep
112
- self.element_model.sub = self.base_data.test_data.replace(self.element_model.sub)
113
- self.element_result_model.sub = self.element_model.sub
114
116
 
115
117
  except MangoAutomationError as error:
116
118
  self.base_data.log.error(f'操作元素解析数据失败,类型:{type(error)}, 详情:{error}')
@@ -144,62 +146,76 @@ class AsyncElement(AsyncWebDevice, AndroidDriver):
144
146
  )
145
147
  else:
146
148
  pass
147
- self.element_result_model.ope_value = {i.f: i.v for i in self.element_model.ope_value if i.d}
149
+ self.element_result_model.ope_value = self.element_model.ope_value
150
+ for i in self.element_result_model.ope_value:
151
+ if not isinstance(i.v, str):
152
+ i.v = str(i.v)
148
153
 
149
- async def __ass(self):
154
+ async def __ass(self, _ope_value: dict | None = None):
150
155
  if self.element_model.ope_value is None:
151
156
  raise MangoAutomationError(*ERROR_MSG_0054)
152
157
  await self.__ope_value(True)
158
+ ope_value = {i.f: i.v for i in self.element_model.ope_value}
159
+ if _ope_value is not None:
160
+ ope_value.update(_ope_value)
153
161
  try:
154
162
  if self.drive_type == DriveTypeEnum.WEB.value:
155
163
  self.element_result_model.ass_msg = await self.web_assertion_element(
156
164
  self.element_model.name,
157
165
  self.element_model.ope_key,
158
- {i.f: i.v for i in self.element_model.ope_value}
166
+ ope_value
159
167
  )
160
168
  elif self.drive_type == DriveTypeEnum.ANDROID.value:
161
169
  self.element_result_model.ass_msg = self.a_assertion_element(
162
170
  self.element_model.name,
163
171
  self.element_model.ope_key,
164
- {i.f: i.v for i in self.element_model.ope_value}
172
+ ope_value
165
173
  )
166
174
  else:
167
175
  pass
168
176
  except MangoAutomationError as error:
169
177
  self.element_result_model.ass_msg = error.msg
170
178
  raise error
171
- self.element_result_model.ope_value = {i.f: i.v for i in self.element_model.ope_value if i.d}
179
+ self.element_result_model.ope_value = self.element_model.ope_value
180
+ for i in self.element_result_model.ope_value:
181
+ if not isinstance(i.v, str):
182
+ i.v = str(i.v)
172
183
 
173
184
  async def __sql(self):
174
- if not self.element_data:
175
- sql = self.base_data.test_data.replace(self.element_model.sql)
176
- key_list = self.element_model.key_list
177
- else:
178
- sql = self.base_data.test_data.replace(self.element_data.get('sql'))
179
- key_list = self.element_data.get('key_list')
180
- if self.base_data.mysql_connect:
185
+ async def run(sql, key_list):
181
186
  result_list: list[dict] = self.base_data.mysql_connect.condition_execute(sql)
182
- if isinstance(result_list, list):
183
- for result in result_list:
184
- try:
185
- for value, key in zip(result, key_list):
186
- self.base_data.test_data.set_cache(key, result.get(value))
187
- except SyntaxError as error:
188
- self.base_data.log.debug(
189
- f'SQL执行失败-1,类型:{type(error)},失败详情:{error},失败明细:{traceback.format_exc()}')
190
- raise MangoAutomationError(*ERROR_MSG_0038)
187
+ self.base_data.log.debug(f'sql参数->key:{sql},value:{result_list}')
188
+ if not isinstance(result_list, list) and not len(result_list) > 0:
189
+ raise MangoAutomationError(*ERROR_MSG_0036, value=(self.element_model.sql_execute,))
190
+ self.base_data.test_data.set_sql_cache(key_list, result_list[0])
191
191
 
192
- if not result_list:
193
- raise MangoAutomationError(*ERROR_MSG_0036, value=(self.element_model.sql,))
192
+ if self.base_data.mysql_connect:
193
+ for i in self.element_model.sql_execute:
194
+ await run(i.get('sql'), i.get('key_list'))
194
195
 
195
196
  async def __custom(self):
196
- if not self.element_data:
197
- key = self.element_model.key
198
- value = self.element_model.value
199
- else:
200
- key = self.element_data.get('key')
201
- value = self.element_data.get('value')
202
- self.base_data.test_data.set_cache(key, self.base_data.test_data.replace(value))
197
+ for i in self.element_model.custom:
198
+ self.base_data.test_data.set_cache(i.get('key'), self.base_data.test_data.replace(i.get('value')))
199
+
200
+ async def __condition(self):
201
+ error_list = []
202
+ for i in self.element_list_model:
203
+ try:
204
+ condition_value = self.base_data.test_data.replace(i.condition_value)
205
+ self.base_data.log.debug(f'执行条件判断数据:{self.element_model.id},{condition_value}')
206
+ await self.__ass(condition_value)
207
+ self.element_result_model.next_node_id = i.id
208
+ return
209
+ except Exception as error:
210
+ self.base_data.log.debug(f'节点判断中-错误:{error},明细:{traceback.print_exc()}')
211
+ error_list.append(error)
212
+ raise error_list[0]
213
+
214
+ async def __python_code(self):
215
+ self.base_data.log.debug(f'执行python函数:{self.element_model.func}')
216
+ global_namespace = {}
217
+ exec(self.element_model.func, global_namespace)
218
+ global_namespace['func'](self)
203
219
 
204
220
  async def __ope_value(self, is_ass: bool = False):
205
221
  try:
@@ -212,17 +228,34 @@ class AsyncElement(AsyncWebDevice, AndroidDriver):
212
228
  '_type': self.element_model.type,
213
229
  'exp': self.element_model.elements[random_element].exp,
214
230
  'loc': self.element_model.elements[random_element].loc,
215
- 'sub': self.element_model.sub
231
+ 'sub': self.element_model.elements[random_element].sub
216
232
  }
217
233
  if self.drive_type == DriveTypeEnum.WEB.value:
218
234
  loc, ele_quantity, element_text = await self.web_find_ele(
219
- **find_params, is_iframe=self.element_model.is_iframe)
235
+ **find_params, is_iframe=self.element_model.elements[random_element].is_iframe)
220
236
  elif self.drive_type == DriveTypeEnum.ANDROID.value:
221
237
  loc, ele_quantity, element_text = self.a_find_ele(**find_params)
222
238
  else:
223
239
  loc, ele_quantity, element_text = None, 0, None
224
- self.element_result_model.elements[random_element].ele_quantity = ele_quantity
225
- self.element_result_model.elements[random_element].element_text = element_text
240
+ new_element = ElementListResultModel(
241
+ exp=self.element_model.elements[random_element].exp,
242
+ loc=self.element_model.elements[random_element].loc,
243
+ sub=self.element_model.elements[random_element].sub,
244
+ ele_quantity=ele_quantity,
245
+ element_text=element_text,
246
+ is_iframe=self.element_model.elements[random_element].is_iframe
247
+ )
248
+
249
+ element_exists = any(
250
+ existing.exp == new_element.exp and
251
+ existing.loc == new_element.loc and
252
+ existing.sub == new_element.sub and
253
+ existing.is_iframe == new_element.is_iframe
254
+ for existing in self.element_result_model.elements
255
+ )
256
+
257
+ if not element_exists:
258
+ self.element_result_model.elements.append(new_element)
226
259
  if is_ass:
227
260
  if callable(getattr(AsyncWebAssertion, self.element_model.ope_key, None)):
228
261
  i.v = loc
@@ -230,10 +263,6 @@ class AsyncElement(AsyncWebDevice, AndroidDriver):
230
263
  i.v = element_text
231
264
  else:
232
265
  i.v = loc
233
- elif self.element_data:
234
- for f, v in self.element_data.items():
235
- if f == i.f:
236
- i.v = self.base_data.test_data.replace(v)
237
266
  i.v = self.base_data.test_data.replace(i.v)
238
267
 
239
268
  except AttributeError as error:
@@ -28,8 +28,9 @@ class SyncElement(SyncWebDevice, AndroidDriver):
28
28
  super().__init__(base_data)
29
29
  self.drive_type = drive_type
30
30
  self.element_model: Optional[ElementModel | None] = None
31
- self.element_data: dict | None = None
32
31
  self.element_result_model: Optional[ElementResultModel | None] = None
32
+ self.element_list_model: Optional[list[ElementModel] | None] = None
33
+ self.test_data = self.base_data.test_data
33
34
 
34
35
  def open_device(self, is_open: bool = False):
35
36
  if self.drive_type == DriveTypeEnum.WEB.value:
@@ -42,21 +43,20 @@ class SyncElement(SyncWebDevice, AndroidDriver):
42
43
  self.base_data.log.error(f'不存在这个类型,如果是非管理员看到这种提示,请联系管理员')
43
44
  raise Exception('不存在的设备类型')
44
45
 
45
- def element_main(self, element_model: ElementModel, element_data: dict | None = None) -> ElementResultModel:
46
+ def element_main(self,
47
+ element_model: ElementModel,
48
+ element_list_model: list[ElementModel] | None = None) -> ElementResultModel:
46
49
  self.element_model = element_model
47
- self.element_data = element_data
50
+ self.element_list_model = element_list_model
48
51
  self.element_result_model = ElementResultModel(
49
52
  id=self.element_model.id,
50
53
  name=self.element_model.name,
51
- sub=self.element_model.sub,
52
54
  sleep=self.element_model.sleep,
53
55
 
54
- type=self.element_model.type,
56
+ type=self.element_model.type.value,
55
57
  ope_key=self.element_model.ope_key,
56
- sql=self.element_model.sql,
57
- key_list=self.element_model.key_list,
58
- key=self.element_model.key,
59
- value=self.element_model.value,
58
+ sql_execute=self.element_model.sql_execute,
59
+ custom=self.element_model.custom,
60
60
 
61
61
  status=StatusEnum.FAIL.value,
62
62
  )
@@ -91,14 +91,18 @@ class SyncElement(SyncWebDevice, AndroidDriver):
91
91
  @sync_retry()
92
92
  def __main(self):
93
93
  self.base_data.verify_equipment(self.drive_type)
94
- if self.element_model.type == ElementOperationEnum.OPE.value:
94
+ if self.element_model.type == ElementOperationEnum.OPE:
95
95
  self.__ope()
96
- elif self.element_model.type == ElementOperationEnum.ASS.value:
96
+ elif self.element_model.type == ElementOperationEnum.ASS:
97
97
  self.__ass()
98
- elif self.element_model.type == ElementOperationEnum.SQL.value:
98
+ elif self.element_model.type == ElementOperationEnum.SQL:
99
99
  self.__sql()
100
- elif self.element_model.type == ElementOperationEnum.CUSTOM.value:
100
+ elif self.element_model.type == ElementOperationEnum.CUSTOM:
101
101
  self.__custom()
102
+ elif self.element_model.type == ElementOperationEnum.CONDITION:
103
+ self.__condition()
104
+ elif self.element_model.type == ElementOperationEnum.PYTHON_CODE:
105
+ self.__python_code()
102
106
  else:
103
107
  raise MangoAutomationError(*ERROR_MSG_0015)
104
108
 
@@ -106,11 +110,9 @@ class SyncElement(SyncWebDevice, AndroidDriver):
106
110
  try:
107
111
  for i in self.element_model.elements:
108
112
  i.loc = self.base_data.test_data.replace(i.loc)
109
- self.element_result_model.elements.append(ElementListResultModel(exp=i.exp, loc=i.loc))
113
+ i.sub = self.base_data.test_data.replace(i.sub)
110
114
  self.element_model.sleep = self.base_data.test_data.replace(self.element_model.sleep)
111
115
  self.element_result_model.sleep = self.element_model.sleep
112
- self.element_model.sub = self.base_data.test_data.replace(self.element_model.sub)
113
- self.element_result_model.sub = self.element_model.sub
114
116
 
115
117
  except MangoAutomationError as error:
116
118
  self.base_data.log.error(f'操作元素解析数据失败,类型:{type(error)}, 详情:{error}')
@@ -144,62 +146,76 @@ class SyncElement(SyncWebDevice, AndroidDriver):
144
146
  )
145
147
  else:
146
148
  pass
147
- self.element_result_model.ope_value = {i.f: i.v for i in self.element_model.ope_value if i.d}
149
+ self.element_result_model.ope_value = self.element_model.ope_value
150
+ for i in self.element_result_model.ope_value:
151
+ if not isinstance(i.v, str):
152
+ i.v = str(i.v)
148
153
 
149
- def __ass(self):
154
+ async def __ass(self, _ope_value: dict | None = None):
150
155
  if self.element_model.ope_value is None:
151
156
  raise MangoAutomationError(*ERROR_MSG_0054)
152
157
  self.__ope_value(True)
158
+ ope_value = {i.f: i.v for i in self.element_model.ope_value}
159
+ if _ope_value is not None:
160
+ ope_value.update(_ope_value)
153
161
  try:
154
162
  if self.drive_type == DriveTypeEnum.WEB.value:
155
163
  self.element_result_model.ass_msg = self.web_assertion_element(
156
164
  self.element_model.name,
157
165
  self.element_model.ope_key,
158
- {i.f: i.v for i in self.element_model.ope_value}
166
+ ope_value
159
167
  )
160
168
  elif self.drive_type == DriveTypeEnum.ANDROID.value:
161
169
  self.element_result_model.ass_msg = self.a_assertion_element(
162
170
  self.element_model.name,
163
171
  self.element_model.ope_key,
164
- {i.f: i.v for i in self.element_model.ope_value}
172
+ ope_value
165
173
  )
166
174
  else:
167
175
  pass
168
176
  except MangoAutomationError as error:
169
177
  self.element_result_model.ass_msg = error.msg
170
178
  raise error
171
- self.element_result_model.ope_value = {i.f: i.v for i in self.element_model.ope_value if i.d}
179
+ self.element_result_model.ope_value = self.element_model.ope_value
180
+ for i in self.element_result_model.ope_value:
181
+ if not isinstance(i.v, str):
182
+ i.v = str(i.v)
172
183
 
173
184
  def __sql(self):
174
- if not self.element_data:
175
- sql = self.base_data.test_data.replace(self.element_model.sql)
176
- key_list = self.element_model.key_list
177
- else:
178
- sql = self.base_data.test_data.replace(self.element_data.get('sql'))
179
- key_list = self.element_data.get('key_list')
180
- if self.base_data.mysql_connect:
185
+ def run(sql, key_list):
181
186
  result_list: list[dict] = self.base_data.mysql_connect.condition_execute(sql)
182
- if isinstance(result_list, list):
183
- for result in result_list:
184
- try:
185
- for value, key in zip(result, key_list):
186
- self.base_data.test_data.set_cache(key, result.get(value))
187
- except SyntaxError as error:
188
- self.base_data.log.debug(
189
- f'SQL执行失败-1,类型:{type(error)},失败详情:{error},失败明细:{traceback.format_exc()}')
190
- raise MangoAutomationError(*ERROR_MSG_0038)
187
+ self.base_data.log.debug(f'sql参数->key:{sql},value:{result_list}')
188
+ if not isinstance(result_list, list) and not len(result_list) > 0:
189
+ raise MangoAutomationError(*ERROR_MSG_0036, value=(self.element_model.sql_execute,))
190
+ self.base_data.test_data.set_sql_cache(key_list, result_list[0])
191
191
 
192
- if not result_list:
193
- raise MangoAutomationError(*ERROR_MSG_0036, value=(self.element_model.sql,))
192
+ if self.base_data.mysql_connect:
193
+ for i in self.element_model.sql_execute:
194
+ run(i.get('sql'), i.get('key_list'))
194
195
 
195
196
  def __custom(self):
196
- if not self.element_data:
197
- key = self.element_model.key
198
- value = self.element_model.value
199
- else:
200
- key = self.element_data.get('key')
201
- value = self.element_data.get('value')
202
- self.base_data.test_data.set_cache(key, self.base_data.test_data.replace(value))
197
+ for i in self.element_model.custom:
198
+ self.base_data.test_data.set_cache(i.get('key'), self.base_data.test_data.replace(i.get('value')))
199
+
200
+ def __condition(self):
201
+ error_list = []
202
+ for i in self.element_list_model:
203
+ try:
204
+ condition_value = self.base_data.test_data.replace(i.condition_value)
205
+ self.base_data.log.debug(f'执行条件判断数据:{self.element_model.id},{condition_value}')
206
+ self.__ass(condition_value)
207
+ self.element_result_model.next_node_id = i.id
208
+ return
209
+ except Exception as error:
210
+ self.base_data.log.debug(f'节点判断中-错误:{error},明细:{traceback.print_exc()}')
211
+ error_list.append(error)
212
+ raise error_list[0]
213
+
214
+ def __python_code(self):
215
+ self.base_data.log.debug(f'执行python函数:{self.element_model.func}')
216
+ global_namespace = {}
217
+ exec(self.element_model.func, global_namespace)
218
+ global_namespace['func'](self)
203
219
 
204
220
  def __ope_value(self, is_ass: bool = False):
205
221
  try:
@@ -212,17 +228,34 @@ class SyncElement(SyncWebDevice, AndroidDriver):
212
228
  '_type': self.element_model.type,
213
229
  'exp': self.element_model.elements[random_element].exp,
214
230
  'loc': self.element_model.elements[random_element].loc,
215
- 'sub': self.element_model.sub
231
+ 'sub': self.element_model.elements[random_element].sub
216
232
  }
217
233
  if self.drive_type == DriveTypeEnum.WEB.value:
218
- loc, ele_quantity, element_text = self.web_find_ele(**find_params,
219
- is_iframe=self.element_model.is_iframe)
234
+ loc, ele_quantity, element_text = self.web_find_ele(
235
+ **find_params,is_iframe=self.element_model.is_iframe)
220
236
  elif self.drive_type == DriveTypeEnum.ANDROID.value:
221
237
  loc, ele_quantity, element_text = self.a_find_ele(**find_params)
222
238
  else:
223
239
  loc, ele_quantity, element_text = None, 0, None
224
- self.element_result_model.elements[random_element].ele_quantity = ele_quantity
225
- self.element_result_model.elements[random_element].element_text = element_text
240
+ new_element = ElementListResultModel(
241
+ exp=self.element_model.elements[random_element].exp,
242
+ loc=self.element_model.elements[random_element].loc,
243
+ sub=self.element_model.elements[random_element].sub,
244
+ ele_quantity=ele_quantity,
245
+ element_text=element_text,
246
+ is_iframe=self.element_model.elements[random_element].is_iframe
247
+ )
248
+
249
+ element_exists = any(
250
+ existing.exp == new_element.exp and
251
+ existing.loc == new_element.loc and
252
+ existing.sub == new_element.sub and
253
+ existing.is_iframe == new_element.is_iframe
254
+ for existing in self.element_result_model.elements
255
+ )
256
+
257
+ if not element_exists:
258
+ self.element_result_model.elements.append(new_element)
226
259
  if is_ass:
227
260
  if callable(getattr(SyncWebAssertion, self.element_model.ope_key, None)):
228
261
  i.v = loc
@@ -230,11 +263,7 @@ class SyncElement(SyncWebDevice, AndroidDriver):
230
263
  i.v = element_text
231
264
  else:
232
265
  i.v = loc
233
- elif self.element_data:
234
- for f, v in self.element_data.items():
235
- if f == i.f:
236
- i.v = self.base_data.test_data.replace(v)
237
- i.v = self.base_data.test_data.replace(i.v)
266
+ i.v = self.base_data.test_data.replace(i.v)
238
267
 
239
268
  except AttributeError as error:
240
269
  self.base_data.log.debug(
@@ -126,7 +126,7 @@ class AsyncWebDevice(AsyncWebBrowser,
126
126
  raise MangoAutomationError(*ERROR_MSG_0023)
127
127
  if not ele_list:
128
128
  raise MangoAutomationError(*ERROR_MSG_0023)
129
- if not ele_list and _type == ElementOperationEnum.OPE.value:
129
+ if not ele_list and _type == ElementOperationEnum.OPE:
130
130
  raise MangoAutomationError(*ERROR_MSG_0029, value=(name, loc))
131
131
  try:
132
132
  count = len(ele_list)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.1
2
2
  Name: mangoautomation
3
- Version: 1.0.60
3
+ Version: 1.1.21
4
4
  Summary: 测试工具
5
5
  Home-page: https://gitee.com/mao-peng/testkit
6
6
  Author: 毛鹏
@@ -18,14 +18,6 @@ Requires-Dist: uiautomator2>=3.2.5
18
18
  Requires-Dist: mangotools>=1.1.42
19
19
  Requires-Dist: adbutils~=2.8.9
20
20
  Requires-Dist: uiautodev>=0.9.0
21
- Dynamic: author
22
- Dynamic: author-email
23
- Dynamic: classifier
24
- Dynamic: description
25
- Dynamic: home-page
26
- Dynamic: license-file
27
- Dynamic: requires-dist
28
- Dynamic: summary
29
21
 
30
22
  # testkit
31
23
 
@@ -1,6 +1,6 @@
1
1
  from setuptools import setup, find_packages
2
2
 
3
- __version__ = '1.0.60'
3
+ __version__ = '1.1.21'
4
4
 
5
5
  with open("README.md", "r", encoding='utf-8') as fh:
6
6
  long_description = fh.read()
@@ -0,0 +1,8 @@
1
+ # -*- coding: utf-8 -*-
2
+ # @Project: 芒果测试平台
3
+ # @Description:
4
+ # @Time : 2025-08-31 17:41
5
+ # @Author : 毛鹏
6
+ loc = 'await page.cdeadapage.'
7
+ cleaned_loc = loc.replace('page.', '').replace('await', '')
8
+ print(cleaned_loc)
@@ -1,12 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # @Project: 芒果测试平台
3
- # @Description:
4
- # @Time : 2025-08-31 17:41
5
- # @Author : 毛鹏
6
- import json
7
- from mangoautomation.uidrive import *
8
- from mangotools.decorator import func_info
9
-
10
- print(json.dumps(func_info, ensure_ascii=False, indent=4))
11
- with open('ope.json', 'w') as f:
12
- f.write(json.dumps(func_info, ensure_ascii=False, indent=4))