Kea2-python 1.2.0__tar.gz → 1.2.1__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.
Files changed (63) hide show
  1. {kea2_python-1.2.0 → kea2_python-1.2.1}/Kea2_python.egg-info/PKG-INFO +10 -9
  2. {kea2_python-1.2.0 → kea2_python-1.2.1}/PKG-INFO +10 -9
  3. {kea2_python-1.2.0 → kea2_python-1.2.1}/README.md +9 -8
  4. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/quicktest.py +22 -16
  5. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/report/bug_report_generator.py +15 -11
  6. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/report/widget_coverage.py +27 -12
  7. {kea2_python-1.2.0 → kea2_python-1.2.1}/pyproject.toml +1 -1
  8. {kea2_python-1.2.0 → kea2_python-1.2.1}/Kea2_python.egg-info/SOURCES.txt +0 -0
  9. {kea2_python-1.2.0 → kea2_python-1.2.1}/Kea2_python.egg-info/dependency_links.txt +0 -0
  10. {kea2_python-1.2.0 → kea2_python-1.2.1}/Kea2_python.egg-info/entry_points.txt +0 -0
  11. {kea2_python-1.2.0 → kea2_python-1.2.1}/Kea2_python.egg-info/requires.txt +0 -0
  12. {kea2_python-1.2.0 → kea2_python-1.2.1}/Kea2_python.egg-info/top_level.txt +0 -0
  13. {kea2_python-1.2.0 → kea2_python-1.2.1}/LICENSE +0 -0
  14. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/__init__.py +0 -0
  15. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/adbUtils.py +0 -0
  16. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/config_version.json +0 -0
  17. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot-thirdpart.jar +0 -0
  18. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_configs/abl.strings +0 -0
  19. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_configs/awl.strings +0 -0
  20. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_configs/max.config +0 -0
  21. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_configs/max.fuzzing.strings +0 -0
  22. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_configs/max.schema.strings +0 -0
  23. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_configs/max.strings +0 -0
  24. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_configs/max.tree.pruning +0 -0
  25. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_configs/teardown.py +0 -0
  26. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_configs/widget.block.py +0 -0
  27. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so +0 -0
  28. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so +0 -0
  29. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_libs/x86/libfastbot_native.so +0 -0
  30. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/fastbot_libs/x86_64/libfastbot_native.so +0 -0
  31. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/framework.jar +0 -0
  32. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/kea2-thirdpart.jar +0 -0
  33. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/assets/monkeyq.jar +0 -0
  34. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/cli.py +0 -0
  35. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/fastbotManager.py +0 -0
  36. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/fastbotx/ActivityTimes.py +0 -0
  37. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/fastbotx/ReuseEntry.py +0 -0
  38. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/fastbotx/ReuseModel.py +0 -0
  39. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/fastbotx/__init__.py +0 -0
  40. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/fbm_parser.py +0 -0
  41. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/fbm_plugin.py +0 -0
  42. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/fs_lock.py +0 -0
  43. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/kea2_api.py +0 -0
  44. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/keaUtils.py +0 -0
  45. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/kea_launcher.py +0 -0
  46. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/logWatcher.py +0 -0
  47. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/mixin.py +0 -0
  48. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/report/__init__.py +0 -0
  49. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/report/mixin.py +0 -0
  50. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/report/report_merger.py +0 -0
  51. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/report/templates/bug_report_template.html +0 -0
  52. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/report/templates/merged_bug_report_template.html +0 -0
  53. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/report/utils.py +0 -0
  54. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/result.py +0 -0
  55. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/resultSyncer.py +0 -0
  56. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/state.py +0 -0
  57. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/typedefs.py +0 -0
  58. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/u2Driver.py +0 -0
  59. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/utils.py +0 -0
  60. {kea2_python-1.2.0 → kea2_python-1.2.1}/kea2/version_manager.py +0 -0
  61. {kea2_python-1.2.0 → kea2_python-1.2.1}/setup.cfg +0 -0
  62. {kea2_python-1.2.0 → kea2_python-1.2.1}/tests/test_u2Selector.py +0 -0
  63. {kea2_python-1.2.0 → kea2_python-1.2.1}/tests/test_xpath.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Kea2-python
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary: A python library for supporting and customizing automated UI testing for mobile apps
5
5
  Author-email: Xixian Liang <xixian@stu.ecnu.edu.cn>
6
6
  Requires-Python: >=3.8
@@ -14,7 +14,7 @@ Requires-Dist: flatbuffers>=25.9.23
14
14
  Requires-Dist: packaging>=25.0
15
15
  Dynamic: license-file
16
16
 
17
-
17
+ <div align="center">
18
18
 
19
19
  [![PyPI](https://img.shields.io/pypi/v/kea2-python.svg)](https://pypi.python.org/pypi/kea2-python)
20
20
  [![PyPI Downloads](https://static.pepy.tech/badge/kea2-python)](https://pepy.tech/projects/kea2-python)
@@ -22,15 +22,16 @@ Dynamic: license-file
22
22
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ecnusse/Kea2)
23
23
 
24
24
  [<img src="https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white" />](https://github.com/ecnusse/Kea2)
25
- [<img src="https://img.shields.io/badge/Gitee-Mirror-333333?style=for-the-badge&logo=gitee&logoColor=white" />](https://gitee.com/XixianLiang/Kea2)
25
+ [<img src="https://img.shields.io/badge/Gitee-333333?style=for-the-badge&logo=gitee&logoColor=white" />](https://gitee.com/XixianLiang/Kea2)
26
26
 
27
- ### English | [简体中文](/README_cn.md)
27
+ **English | [简体中文](/README_cn.md)**
28
+
29
+ </br>
30
+
31
+ <img src="docs/images/kea2_logo.png" alt="kea_logo" style="border-radius: 14px; width: 20%; height: 20%;"/>
32
+
33
+ <a href="https://en.wikipedia.org/wiki/Kea">Kea2's logo: A large parrot skilled in finding "bugs"</a>
28
34
 
29
- <div align="center">
30
- <img src="docs/images/kea2_logo.png" alt="kea_logo" style="border-radius: 14px; width: 20%; height: 20%;"/>
31
- </div>
32
- <div align="center">
33
- <a href="https://en.wikipedia.org/wiki/Kea">Kea2's logo: A large parrot skilled in finding "bugs"</a>
34
35
  </div>
35
36
  </br>
36
37
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Kea2-python
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary: A python library for supporting and customizing automated UI testing for mobile apps
5
5
  Author-email: Xixian Liang <xixian@stu.ecnu.edu.cn>
6
6
  Requires-Python: >=3.8
@@ -14,7 +14,7 @@ Requires-Dist: flatbuffers>=25.9.23
14
14
  Requires-Dist: packaging>=25.0
15
15
  Dynamic: license-file
16
16
 
17
-
17
+ <div align="center">
18
18
 
19
19
  [![PyPI](https://img.shields.io/pypi/v/kea2-python.svg)](https://pypi.python.org/pypi/kea2-python)
20
20
  [![PyPI Downloads](https://static.pepy.tech/badge/kea2-python)](https://pepy.tech/projects/kea2-python)
@@ -22,15 +22,16 @@ Dynamic: license-file
22
22
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ecnusse/Kea2)
23
23
 
24
24
  [<img src="https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white" />](https://github.com/ecnusse/Kea2)
25
- [<img src="https://img.shields.io/badge/Gitee-Mirror-333333?style=for-the-badge&logo=gitee&logoColor=white" />](https://gitee.com/XixianLiang/Kea2)
25
+ [<img src="https://img.shields.io/badge/Gitee-333333?style=for-the-badge&logo=gitee&logoColor=white" />](https://gitee.com/XixianLiang/Kea2)
26
26
 
27
- ### English | [简体中文](/README_cn.md)
27
+ **English | [简体中文](/README_cn.md)**
28
+
29
+ </br>
30
+
31
+ <img src="docs/images/kea2_logo.png" alt="kea_logo" style="border-radius: 14px; width: 20%; height: 20%;"/>
32
+
33
+ <a href="https://en.wikipedia.org/wiki/Kea">Kea2's logo: A large parrot skilled in finding "bugs"</a>
28
34
 
29
- <div align="center">
30
- <img src="docs/images/kea2_logo.png" alt="kea_logo" style="border-radius: 14px; width: 20%; height: 20%;"/>
31
- </div>
32
- <div align="center">
33
- <a href="https://en.wikipedia.org/wiki/Kea">Kea2's logo: A large parrot skilled in finding "bugs"</a>
34
35
  </div>
35
36
  </br>
36
37
 
@@ -1,4 +1,4 @@
1
-
1
+ <div align="center">
2
2
 
3
3
  [![PyPI](https://img.shields.io/pypi/v/kea2-python.svg)](https://pypi.python.org/pypi/kea2-python)
4
4
  [![PyPI Downloads](https://static.pepy.tech/badge/kea2-python)](https://pepy.tech/projects/kea2-python)
@@ -6,15 +6,16 @@
6
6
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ecnusse/Kea2)
7
7
 
8
8
  [<img src="https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white" />](https://github.com/ecnusse/Kea2)
9
- [<img src="https://img.shields.io/badge/Gitee-Mirror-333333?style=for-the-badge&logo=gitee&logoColor=white" />](https://gitee.com/XixianLiang/Kea2)
9
+ [<img src="https://img.shields.io/badge/Gitee-333333?style=for-the-badge&logo=gitee&logoColor=white" />](https://gitee.com/XixianLiang/Kea2)
10
10
 
11
- ### English | [简体中文](/README_cn.md)
11
+ **English | [简体中文](/README_cn.md)**
12
+
13
+ </br>
14
+
15
+ <img src="docs/images/kea2_logo.png" alt="kea_logo" style="border-radius: 14px; width: 20%; height: 20%;"/>
16
+
17
+ <a href="https://en.wikipedia.org/wiki/Kea">Kea2's logo: A large parrot skilled in finding "bugs"</a>
12
18
 
13
- <div align="center">
14
- <img src="docs/images/kea2_logo.png" alt="kea_logo" style="border-radius: 14px; width: 20%; height: 20%;"/>
15
- </div>
16
- <div align="center">
17
- <a href="https://en.wikipedia.org/wiki/Kea">Kea2's logo: A large parrot skilled in finding "bugs"</a>
18
19
  </div>
19
20
  </br>
20
21
 
@@ -1,8 +1,7 @@
1
1
  import unittest
2
2
  import uiautomator2 as u2
3
3
 
4
- from time import sleep
5
- from kea2 import precondition, prob, KeaTestRunner, Options, keaTestLoader, invariant
4
+ from kea2 import precondition, prob, invariant
6
5
 
7
6
 
8
7
  import unittest
@@ -132,17 +131,24 @@ def check_installation(serial=None):
132
131
 
133
132
  if __name__ == "__main__":
134
133
  check_installation(serial=None)
135
- KeaTestRunner.setOptions(
136
- Options(
137
- driverName="d",
138
- packageNames=[PACKAGE_NAME],
139
- # serial="emulator-5554", # specify the serial
140
- maxStep=50,
141
- profile_period=10,
142
- take_screenshots=True, # whether to take screenshots, default is False
143
- # running_mins=10, # specify the maximal running time in minutes, default value is 10m
144
- # throttle=200, # specify the throttle in milliseconds, default value is 200ms
145
- agent="u2" # 'native' for running the vanilla Fastbot, 'u2' for running Kea2
146
- )
147
- )
148
- unittest.main(testRunner=KeaTestRunner, testLoader=keaTestLoader)
134
+ import signal
135
+ import subprocess
136
+ import sys
137
+ from pathlib import Path
138
+ start_dir = str(Path(__file__).parent)
139
+ file_name = str(Path(__file__).name)
140
+ CMD = [
141
+ "kea2", "run",
142
+ "-p", PACKAGE_NAME,
143
+ "--max-step", "50",
144
+ "--profile-period", "10",
145
+ "--take-screenshots",
146
+ "propertytest", "discover", "-s", start_dir, "-p", file_name
147
+ ]
148
+ try:
149
+ p = subprocess.Popen(CMD, stdout=sys.stdout, stderr=sys.stderr)
150
+ p.wait()
151
+ except KeyboardInterrupt:
152
+ p.wait()
153
+ finally:
154
+ sys.exit(p.returncode)
@@ -50,7 +50,7 @@ class ReportData(TypedDict):
50
50
  bugs_found: int
51
51
  invariant_violations_count: int
52
52
  executed_events: int
53
- total_testing_time: float
53
+ total_testing_time: str
54
54
  coverage: float
55
55
  widget_coverage_count: int
56
56
  total_activities_count: int
@@ -279,7 +279,7 @@ class BugReportGenerator(CrashAnrMixin, PathParserMixin, ScreenshotsMixin):
279
279
  "bugs_found": 0,
280
280
  "invariant_violations_count": 0,
281
281
  "executed_events": 0,
282
- "total_testing_time": 0,
282
+ "total_testing_time": "00:00:00",
283
283
  "coverage": 0,
284
284
  "widget_coverage_count": 0,
285
285
  "total_activities": [],
@@ -318,7 +318,8 @@ class BugReportGenerator(CrashAnrMixin, PathParserMixin, ScreenshotsMixin):
318
318
 
319
319
  current_property = None
320
320
  current_test = {}
321
- first_step_time = last_step_time = ""
321
+ first_step_time: Optional[str] = None
322
+ last_step_time: Optional[str] = None
322
323
  step_index = 0
323
324
  monkey_events_count = 0 # Track monkey events separately
324
325
  last_monkey_step_count = 0
@@ -411,20 +412,23 @@ class BugReportGenerator(CrashAnrMixin, PathParserMixin, ScreenshotsMixin):
411
412
  current_property, current_test, property_violations
412
413
  )
413
414
 
414
- # Store first and last step for time calculation
415
- if int(monkey_steps_count) == 1 and not first_step_time:
416
- first_step_time = step_data["Time"]
417
- last_step_time = step_data["Time"]
415
+ # Store first and last valid timestamps for testing duration calculation.
416
+ step_time = step_data.get("Time")
417
+ if step_time:
418
+ if first_step_time is None:
419
+ first_step_time = step_time
420
+ last_step_time = step_time
418
421
 
419
422
 
420
423
  # Calculate test time
421
424
  if first_step_time and last_step_time:
422
- def _get_datetime(raw_datetime) -> datetime:
423
- return datetime.strptime(raw_datetime, r"%Y-%m-%d %H:%M:%S.%f")
425
+ def _get_datetime(raw_datetime: str) -> datetime:
426
+ # Use fromisoformat for compatibility with/without microseconds.
427
+ return datetime.fromisoformat(raw_datetime)
424
428
 
425
429
  test_time = _get_datetime(last_step_time) - _get_datetime(first_step_time)
426
-
427
- total_seconds = int(test_time.total_seconds())
430
+
431
+ total_seconds = max(0, int(test_time.total_seconds()))
428
432
  hours, remainder = divmod(total_seconds, 3600)
429
433
  minutes, seconds = divmod(remainder, 60)
430
434
  data["total_testing_time"] = f"{hours:02d}:{minutes:02d}:{seconds:02d}"
@@ -20,6 +20,7 @@ class WidgetCoverage:
20
20
  AUTO_RESOURCE_ID = "<AUTO>"
21
21
  _profile_period: int
22
22
  _options: "Options"
23
+ _all_activities: Set[str] = None
23
24
 
24
25
  def __init__(self, output_dir, options:"Options"=None, profile_period:int=None):
25
26
  self.output_dir = Path(output_dir)
@@ -43,6 +44,16 @@ class WidgetCoverage:
43
44
  if options_data:
44
45
  self._options = Options.from_dict(options_data)
45
46
  return self._options
47
+
48
+ @property
49
+ def all_activities(self) -> Set[str]:
50
+ if self._all_activities is None:
51
+ with open(self.output_dir / "coverage.log") as f:
52
+ line = f.readline()
53
+ data = json.loads(line)
54
+ self._all_activities = set(data["totalActivities"])
55
+ return self._all_activities
56
+
46
57
 
47
58
  def generate_coverage_report(self):
48
59
  logger.info(
@@ -103,24 +114,28 @@ class WidgetCoverage:
103
114
  __record_coverage(final_steps_count)
104
115
 
105
116
  return triggered_widgets, coverage_records
106
-
107
- @catchException("Error getting widget representation")
108
- def __get_widget_repr(self, data):
109
- activity: str = data.get("Activity", "")
110
- if not activity:
111
- return ""
112
-
117
+
118
+ def is_activity_in_target_packages(self, activity: str) -> bool:
119
+ if self.all_activities:
120
+ return activity in self.all_activities
121
+ # Fallback
113
122
  # Check if activity matches any of the specified package names
114
123
  # filter out irrelevant widgets (not in the target packages)
115
124
  for pkg in self.options.packageNames:
116
125
  if pkg in activity:
117
- break
118
- # Handling the case where the activity string may not contain the full package name but can be inferred from the activity name itself
119
- # Example: com.example.app.MainActivity & com.example.app.alpha
126
+ return True
120
127
  pkg_name_from_activity = ".".join(_ for _ in activity.split(".") if "activity" not in _.lower())
121
128
  if pkg_name_from_activity in pkg:
122
- break
123
- else:
129
+ return True
130
+ return False
131
+
132
+ @catchException("Error getting widget representation")
133
+ def __get_widget_repr(self, data):
134
+ activity: str = data.get("Activity", "")
135
+ if not activity:
136
+ return ""
137
+
138
+ if not self.is_activity_in_target_packages(activity):
124
139
  return ""
125
140
 
126
141
  info_str = data.get("Info", "")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "Kea2-python"
3
- version = "1.2.0"
3
+ version = "1.2.1"
4
4
  description = "A python library for supporting and customizing automated UI testing for mobile apps"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.8"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes