Kea2-python 1.0.6b0__tar.gz → 1.1.0__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.
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/Kea2_python.egg-info/PKG-INFO +6 -2
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/Kea2_python.egg-info/SOURCES.txt +3 -7
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/PKG-INFO +6 -2
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/README.md +5 -1
- kea2_python-1.1.0/kea2/__init__.py +8 -0
- kea2_python-1.1.0/kea2/assets/monkeyq.jar +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/quicktest.py +41 -22
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/cli.py +10 -106
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/fastbotManager.py +4 -4
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/kea2_api.py +7 -3
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/keaUtils.py +316 -478
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/kea_launcher.py +4 -26
- kea2_python-1.1.0/kea2/report/__init__.py +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/report/bug_report_generator.py +151 -40
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/report/mixin.py +28 -13
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/report/report_merger.py +281 -12
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/report/templates/bug_report_template.html +347 -107
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/report/templates/merged_bug_report_template.html +545 -276
- kea2_python-1.1.0/kea2/result.py +259 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/resultSyncer.py +2 -1
- kea2_python-1.1.0/kea2/state.py +22 -0
- kea2_python-1.1.0/kea2/typedefs.py +32 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/u2Driver.py +5 -4
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/utils.py +56 -1
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/pyproject.toml +1 -1
- kea2_python-1.0.6b0/kea2/__init__.py +0 -3
- kea2_python-1.0.6b0/kea2/absDriver.py +0 -56
- kea2_python-1.0.6b0/kea2/assets/monkeyq.jar +0 -0
- kea2_python-1.0.6b0/kea2/fastbotx/ActivityTimes.py +0 -52
- kea2_python-1.0.6b0/kea2/fastbotx/ReuseEntry.py +0 -74
- kea2_python-1.0.6b0/kea2/fastbotx/ReuseModel.py +0 -63
- kea2_python-1.0.6b0/kea2/fastbotx/__init__.py +0 -7
- kea2_python-1.0.6b0/kea2/fbm_parser.py +0 -871
- kea2_python-1.0.6b0/kea2/fs_lock.py +0 -131
- kea2_python-1.0.6b0/kea2/mixin.py +0 -22
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/Kea2_python.egg-info/dependency_links.txt +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/Kea2_python.egg-info/entry_points.txt +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/Kea2_python.egg-info/requires.txt +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/Kea2_python.egg-info/top_level.txt +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/LICENSE +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/adbUtils.py +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/config_version.json +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot-thirdpart.jar +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_configs/abl.strings +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_configs/awl.strings +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_configs/max.config +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_configs/max.fuzzing.strings +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_configs/max.schema.strings +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_configs/max.strings +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_configs/max.tree.pruning +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_configs/teardown.py +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_configs/widget.block.py +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_libs/x86/libfastbot_native.so +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/fastbot_libs/x86_64/libfastbot_native.so +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/framework.jar +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/assets/kea2-thirdpart.jar +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/logWatcher.py +0 -0
- /kea2_python-1.0.6b0/kea2/report/__init__.py → /kea2_python-1.1.0/kea2/mixin.py +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/report/utils.py +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/kea2/version_manager.py +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/setup.cfg +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/tests/test_u2Selector.py +0 -0
- {kea2_python-1.0.6b0 → kea2_python-1.1.0}/tests/test_xpath.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Kea2-python
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.1.0
|
|
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
|
|
@@ -290,7 +290,7 @@ Some notes:
|
|
|
290
290
|
3. You need to insert the following code template into your existing test cases: Here, you can add your own hook logic in the commented sections, including starting or stopping the appium session, cleaning up instances, etc. This depends on how you want to design the setup and teardown. Apart from that, you only need to configure the `option` parameter and `configs_path` parameter(where your directory `configs` located, btw, `configs`'s location dependon where you executed `kea2 init`), then pass it to the `run_kea2_testing` function.
|
|
291
291
|
|
|
292
292
|
```python
|
|
293
|
-
from kea2 import Kea2Tester, Options
|
|
293
|
+
from kea2 import Kea2Tester, Options
|
|
294
294
|
|
|
295
295
|
if os.environ.get('KEA2_HYBRID_MODE', '').lower() == 'true':
|
|
296
296
|
'''
|
|
@@ -327,6 +327,10 @@ if os.environ.get('KEA2_HYBRID_MODE', '').lower() == 'true':
|
|
|
327
327
|
Kea2 automatically generates a HTML test report after each testing session. You can find the report in `output/` under your working directory.
|
|
328
328
|
|
|
329
329
|
You can also manually generate the test report by `kea2 report` (see `kea2 report -h` for details).
|
|
330
|
+
Use `-s/--sync` to sync data from device before generating the report, and `-p/--path` to point to one or more result directories.
|
|
331
|
+
For example:
|
|
332
|
+
`kea2 report -p output/res_YYYYMMDDHH_xxxxxx`
|
|
333
|
+
`kea2 report -s -p output/res_YYYYMMDDHH_xxxxxx`
|
|
330
334
|
|
|
331
335
|
You can also merge the test report from multiple testing sessions by `kea2 merge` (see `kea2 merge -h` for details).
|
|
332
336
|
The merged test report is quite useful if you would test your apps for multiple sessions.
|
|
@@ -8,18 +8,18 @@ Kea2_python.egg-info/entry_points.txt
|
|
|
8
8
|
Kea2_python.egg-info/requires.txt
|
|
9
9
|
Kea2_python.egg-info/top_level.txt
|
|
10
10
|
kea2/__init__.py
|
|
11
|
-
kea2/absDriver.py
|
|
12
11
|
kea2/adbUtils.py
|
|
13
12
|
kea2/cli.py
|
|
14
13
|
kea2/fastbotManager.py
|
|
15
|
-
kea2/fbm_parser.py
|
|
16
|
-
kea2/fs_lock.py
|
|
17
14
|
kea2/kea2_api.py
|
|
18
15
|
kea2/keaUtils.py
|
|
19
16
|
kea2/kea_launcher.py
|
|
20
17
|
kea2/logWatcher.py
|
|
21
18
|
kea2/mixin.py
|
|
19
|
+
kea2/result.py
|
|
22
20
|
kea2/resultSyncer.py
|
|
21
|
+
kea2/state.py
|
|
22
|
+
kea2/typedefs.py
|
|
23
23
|
kea2/u2Driver.py
|
|
24
24
|
kea2/utils.py
|
|
25
25
|
kea2/version_manager.py
|
|
@@ -42,10 +42,6 @@ kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so
|
|
|
42
42
|
kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so
|
|
43
43
|
kea2/assets/fastbot_libs/x86/libfastbot_native.so
|
|
44
44
|
kea2/assets/fastbot_libs/x86_64/libfastbot_native.so
|
|
45
|
-
kea2/fastbotx/ActivityTimes.py
|
|
46
|
-
kea2/fastbotx/ReuseEntry.py
|
|
47
|
-
kea2/fastbotx/ReuseModel.py
|
|
48
|
-
kea2/fastbotx/__init__.py
|
|
49
45
|
kea2/report/__init__.py
|
|
50
46
|
kea2/report/bug_report_generator.py
|
|
51
47
|
kea2/report/mixin.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Kea2-python
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.1.0
|
|
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
|
|
@@ -290,7 +290,7 @@ Some notes:
|
|
|
290
290
|
3. You need to insert the following code template into your existing test cases: Here, you can add your own hook logic in the commented sections, including starting or stopping the appium session, cleaning up instances, etc. This depends on how you want to design the setup and teardown. Apart from that, you only need to configure the `option` parameter and `configs_path` parameter(where your directory `configs` located, btw, `configs`'s location dependon where you executed `kea2 init`), then pass it to the `run_kea2_testing` function.
|
|
291
291
|
|
|
292
292
|
```python
|
|
293
|
-
from kea2 import Kea2Tester, Options
|
|
293
|
+
from kea2 import Kea2Tester, Options
|
|
294
294
|
|
|
295
295
|
if os.environ.get('KEA2_HYBRID_MODE', '').lower() == 'true':
|
|
296
296
|
'''
|
|
@@ -327,6 +327,10 @@ if os.environ.get('KEA2_HYBRID_MODE', '').lower() == 'true':
|
|
|
327
327
|
Kea2 automatically generates a HTML test report after each testing session. You can find the report in `output/` under your working directory.
|
|
328
328
|
|
|
329
329
|
You can also manually generate the test report by `kea2 report` (see `kea2 report -h` for details).
|
|
330
|
+
Use `-s/--sync` to sync data from device before generating the report, and `-p/--path` to point to one or more result directories.
|
|
331
|
+
For example:
|
|
332
|
+
`kea2 report -p output/res_YYYYMMDDHH_xxxxxx`
|
|
333
|
+
`kea2 report -s -p output/res_YYYYMMDDHH_xxxxxx`
|
|
330
334
|
|
|
331
335
|
You can also merge the test report from multiple testing sessions by `kea2 merge` (see `kea2 merge -h` for details).
|
|
332
336
|
The merged test report is quite useful if you would test your apps for multiple sessions.
|
|
@@ -275,7 +275,7 @@ Some notes:
|
|
|
275
275
|
3. You need to insert the following code template into your existing test cases: Here, you can add your own hook logic in the commented sections, including starting or stopping the appium session, cleaning up instances, etc. This depends on how you want to design the setup and teardown. Apart from that, you only need to configure the `option` parameter and `configs_path` parameter(where your directory `configs` located, btw, `configs`'s location dependon where you executed `kea2 init`), then pass it to the `run_kea2_testing` function.
|
|
276
276
|
|
|
277
277
|
```python
|
|
278
|
-
from kea2 import Kea2Tester, Options
|
|
278
|
+
from kea2 import Kea2Tester, Options
|
|
279
279
|
|
|
280
280
|
if os.environ.get('KEA2_HYBRID_MODE', '').lower() == 'true':
|
|
281
281
|
'''
|
|
@@ -312,6 +312,10 @@ if os.environ.get('KEA2_HYBRID_MODE', '').lower() == 'true':
|
|
|
312
312
|
Kea2 automatically generates a HTML test report after each testing session. You can find the report in `output/` under your working directory.
|
|
313
313
|
|
|
314
314
|
You can also manually generate the test report by `kea2 report` (see `kea2 report -h` for details).
|
|
315
|
+
Use `-s/--sync` to sync data from device before generating the report, and `-p/--path` to point to one or more result directories.
|
|
316
|
+
For example:
|
|
317
|
+
`kea2 report -p output/res_YYYYMMDDHH_xxxxxx`
|
|
318
|
+
`kea2 report -s -p output/res_YYYYMMDDHH_xxxxxx`
|
|
315
319
|
|
|
316
320
|
You can also merge the test report from multiple testing sessions by `kea2 merge` (see `kea2 merge -h` for details).
|
|
317
321
|
The merged test report is quite useful if you would test your apps for multiple sessions.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from .keaUtils import KeaTestRunner, HybridTestRunner, keaTestLoader
|
|
2
|
+
from .keaUtils import Options
|
|
3
|
+
from .keaUtils import precondition, prob, max_tries, interruptable
|
|
4
|
+
from .keaUtils import kea2_breakpoint
|
|
5
|
+
from .state import state, invariant
|
|
6
|
+
from .kea2_api import Kea2Tester
|
|
7
|
+
from .u2Driver import U2Driver
|
|
8
|
+
from .state import state
|
|
Binary file
|
|
@@ -2,39 +2,43 @@ import unittest
|
|
|
2
2
|
import uiautomator2 as u2
|
|
3
3
|
|
|
4
4
|
from time import sleep
|
|
5
|
-
from kea2 import precondition, prob, KeaTestRunner, Options
|
|
6
|
-
from kea2.u2Driver import U2Driver
|
|
5
|
+
from kea2 import precondition, prob, KeaTestRunner, Options, keaTestLoader, invariant
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
class Omni_Notes_Sample(unittest.TestCase):
|
|
9
|
+
d: u2.Device
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
@classmethod
|
|
12
|
+
def setUpClass(cls):
|
|
13
|
+
"""Here you can setup the initialize setting for uiautomator2
|
|
14
|
+
"""
|
|
15
|
+
print("Setting driver settings")
|
|
16
|
+
cls.d.settings["wait_timeout"] = 5.0
|
|
17
|
+
cls.d.settings["operation_delay"] = (0, 1.0)
|
|
18
|
+
|
|
19
|
+
@prob(0.5)
|
|
15
20
|
@precondition(
|
|
16
21
|
lambda self: self.d(description="Navigate up").exists
|
|
17
22
|
)
|
|
18
|
-
def
|
|
23
|
+
def navigate_up(self):
|
|
19
24
|
print("Navigate back")
|
|
20
25
|
self.d(description="Navigate up").click()
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@prob(0.2)
|
|
26
|
+
|
|
27
|
+
@prob(0.5)
|
|
24
28
|
@precondition(
|
|
25
|
-
lambda self: self.d(description="drawer closed").exists
|
|
29
|
+
lambda self: self.d(description="drawer closed").exists and
|
|
30
|
+
not self.d(text="Omni Notes Alpha").exists
|
|
26
31
|
)
|
|
27
|
-
def
|
|
32
|
+
def open_drawer(self):
|
|
28
33
|
print("Open drawer")
|
|
29
34
|
self.d(description="drawer closed").click()
|
|
30
|
-
sleep(0.5)
|
|
31
35
|
|
|
32
|
-
@prob(0.
|
|
36
|
+
@prob(0.7) # The probability of executing the function when precondition is satisfied.
|
|
33
37
|
@precondition(
|
|
34
38
|
lambda self: self.d(text="Omni Notes Alpha").exists
|
|
35
39
|
and self.d(text="Settings").exists
|
|
36
40
|
)
|
|
37
|
-
def
|
|
41
|
+
def go_to_privacy_settings(self):
|
|
38
42
|
"""
|
|
39
43
|
The ability to jump out of the UI tarpits
|
|
40
44
|
|
|
@@ -45,14 +49,13 @@ class Omni_Notes_Sample(unittest.TestCase):
|
|
|
45
49
|
"""
|
|
46
50
|
print("trying to click Settings")
|
|
47
51
|
self.d(text="Settings").click()
|
|
48
|
-
sleep(0.5)
|
|
49
52
|
print("trying to click Privacy")
|
|
50
53
|
self.d(text="Privacy").click()
|
|
51
54
|
|
|
52
55
|
@precondition(
|
|
53
56
|
lambda self: self.d(resourceId="it.feio.android.omninotes.alpha:id/search_src_text").exists
|
|
54
57
|
)
|
|
55
|
-
def
|
|
58
|
+
def rotation_should_not_close_the_search_input(self):
|
|
56
59
|
"""
|
|
57
60
|
The ability to make assertion to find functional bug
|
|
58
61
|
|
|
@@ -65,11 +68,28 @@ class Omni_Notes_Sample(unittest.TestCase):
|
|
|
65
68
|
"""
|
|
66
69
|
print("rotate the device")
|
|
67
70
|
self.d.set_orientation("l")
|
|
68
|
-
sleep(2)
|
|
69
71
|
self.d.set_orientation("n")
|
|
70
|
-
|
|
71
|
-
assert self.d(resourceId="it.feio.android.omninotes.alpha:id/search_src_text").exists()
|
|
72
|
+
assert self.d(resourceId="it.feio.android.omninotes.alpha:id/search_src_text").exists
|
|
72
73
|
|
|
74
|
+
@invariant
|
|
75
|
+
def search_button_and_search_input_box_should_not_exists_at_the_same_time(self):
|
|
76
|
+
"""Search input box and search button should not exists at the same time
|
|
77
|
+
"""
|
|
78
|
+
search_input_box_exists = self.d(resourceId="it.feio.android.omninotes.alpha:id/search_src_text").exists
|
|
79
|
+
serach_button_exists = self.d(resourceId="it.feio.android.omninotes.alpha:id/menu_search").exists
|
|
80
|
+
if search_input_box_exists or serach_button_exists:
|
|
81
|
+
assert search_input_box_exists ^ serach_button_exists
|
|
82
|
+
|
|
83
|
+
@precondition(lambda self: "camera" in self.d.app_current().get("package", ""))
|
|
84
|
+
def exit_camera(self):
|
|
85
|
+
"""Exit camera app if it is launched
|
|
86
|
+
(fastbot can't exit camera app by itself, we use kea2 to exit it to aviod getting stuck in camera)
|
|
87
|
+
"""
|
|
88
|
+
print("Exiting camera app")
|
|
89
|
+
pkg_camera = self.d.app_current().get("package", "")
|
|
90
|
+
print(f"Current package: {pkg_camera}")
|
|
91
|
+
if "camera" in pkg_camera:
|
|
92
|
+
self.d.app_stop(pkg_camera)
|
|
73
93
|
|
|
74
94
|
URL = "https://github.com/federicoiosue/Omni-Notes/releases/download/6.2.0_alpha/OmniNotes-alphaRelease-6.2.0.apk"
|
|
75
95
|
FALL_BACK_URL = "https://gitee.com/XixianLiang/Kea2/raw/main/omninotes.apk"
|
|
@@ -112,7 +132,6 @@ if __name__ == "__main__":
|
|
|
112
132
|
KeaTestRunner.setOptions(
|
|
113
133
|
Options(
|
|
114
134
|
driverName="d",
|
|
115
|
-
Driver=U2Driver,
|
|
116
135
|
packageNames=[PACKAGE_NAME],
|
|
117
136
|
# serial="emulator-5554", # specify the serial
|
|
118
137
|
maxStep=50,
|
|
@@ -123,4 +142,4 @@ if __name__ == "__main__":
|
|
|
123
142
|
agent="u2" # 'native' for running the vanilla Fastbot, 'u2' for running Kea2
|
|
124
143
|
)
|
|
125
144
|
)
|
|
126
|
-
unittest.main(testRunner=KeaTestRunner)
|
|
145
|
+
unittest.main(testRunner=KeaTestRunner, testLoader=keaTestLoader)
|
|
@@ -58,6 +58,8 @@ def cmd_report(args):
|
|
|
58
58
|
from .report.bug_report_generator import BugReportGenerator
|
|
59
59
|
report_dirs = args.path
|
|
60
60
|
|
|
61
|
+
sync_data = args.sync
|
|
62
|
+
|
|
61
63
|
for report_dir in report_dirs:
|
|
62
64
|
report_dir = Path(report_dir).resolve()
|
|
63
65
|
|
|
@@ -66,7 +68,7 @@ def cmd_report(args):
|
|
|
66
68
|
continue
|
|
67
69
|
|
|
68
70
|
logger.debug(f"Generating test report from directory: {report_dir}")
|
|
69
|
-
BugReportGenerator(report_dir).generate_report()
|
|
71
|
+
BugReportGenerator(report_dir, sync_data).generate_report()
|
|
70
72
|
|
|
71
73
|
|
|
72
74
|
def cmd_merge(args):
|
|
@@ -103,90 +105,7 @@ def cmd_merge(args):
|
|
|
103
105
|
print(f"📈 Merged {merge_summary.get('merged_directories', 0)} directories", flush=True)
|
|
104
106
|
|
|
105
107
|
except Exception as e:
|
|
106
|
-
logger.error(f"Error during merge operation: {e}")
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def cmd_mergefbm(args):
|
|
110
|
-
"""Merge all FBM files in the specified folder and its subfolders using sum mode"""
|
|
111
|
-
from .fbm_parser import FBMMerger
|
|
112
|
-
import glob
|
|
113
|
-
import shutil
|
|
114
|
-
|
|
115
|
-
try:
|
|
116
|
-
# Validate input path
|
|
117
|
-
input_path = Path(args.path).resolve()
|
|
118
|
-
if not input_path.exists():
|
|
119
|
-
logger.error(f"Input directory does not exist: {input_path}")
|
|
120
|
-
return
|
|
121
|
-
if not input_path.is_dir():
|
|
122
|
-
logger.error(f"Input path is not a directory: {input_path}")
|
|
123
|
-
return
|
|
124
|
-
|
|
125
|
-
# Find all FBM files in the directory and its subdirectories
|
|
126
|
-
fbm_files = glob.glob(str(input_path / "**" / "*.fbm"), recursive=True)
|
|
127
|
-
|
|
128
|
-
if not fbm_files:
|
|
129
|
-
logger.error(f"No FBM files found in {input_path} or its subdirectories")
|
|
130
|
-
return
|
|
131
|
-
|
|
132
|
-
logger.debug(f"Found {len(fbm_files)} FBM files to merge:")
|
|
133
|
-
for fbm_file in fbm_files:
|
|
134
|
-
logger.debug(f" - {fbm_file}")
|
|
135
|
-
|
|
136
|
-
# Set default output file if not provided
|
|
137
|
-
if not args.output:
|
|
138
|
-
output_file = input_path / "merged.fbm"
|
|
139
|
-
else:
|
|
140
|
-
output_file = Path(args.output).resolve()
|
|
141
|
-
|
|
142
|
-
# Initialize merger
|
|
143
|
-
merger = FBMMerger()
|
|
144
|
-
|
|
145
|
-
# Handle different cases
|
|
146
|
-
if len(fbm_files) == 1:
|
|
147
|
-
# Only one file, just copy it to output
|
|
148
|
-
shutil.copyfile(fbm_files[0], output_file)
|
|
149
|
-
logger.info(f"Only one FBM file found, copied to {output_file}")
|
|
150
|
-
else:
|
|
151
|
-
# Merge files iteratively: start with the first file and merge with each subsequent file
|
|
152
|
-
# Create a temporary file for the intermediate merged result
|
|
153
|
-
temp_output = input_path / f".tmp_merged.fbm"
|
|
154
|
-
|
|
155
|
-
# Start with the first file as the initial merged result
|
|
156
|
-
shutil.copyfile(fbm_files[0], temp_output)
|
|
157
|
-
|
|
158
|
-
# Iterate through the remaining files and merge them one by one
|
|
159
|
-
for i in range(1, len(fbm_files)):
|
|
160
|
-
current_file = fbm_files[i]
|
|
161
|
-
next_temp = input_path / f".tmp_merged_{i}.fbm"
|
|
162
|
-
|
|
163
|
-
logger.debug(f"Merging {temp_output} and {current_file} into {next_temp}")
|
|
164
|
-
success = merger.merge(str(temp_output), str(current_file), str(next_temp), merge_mode='sum')
|
|
165
|
-
|
|
166
|
-
if not success:
|
|
167
|
-
logger.error(f"Failed to merge {temp_output} and {current_file}")
|
|
168
|
-
# Clean up temporary files
|
|
169
|
-
for f in [temp_output, next_temp]:
|
|
170
|
-
if f.exists() and f.name.startswith(".tmp_"):
|
|
171
|
-
f.unlink()
|
|
172
|
-
return
|
|
173
|
-
|
|
174
|
-
# Remove the previous temporary file and update to the new one
|
|
175
|
-
temp_output.unlink()
|
|
176
|
-
temp_output = next_temp
|
|
177
|
-
|
|
178
|
-
# Move the final merged file to the output location
|
|
179
|
-
if temp_output != output_file:
|
|
180
|
-
temp_output.replace(output_file)
|
|
181
|
-
|
|
182
|
-
print(f"✅ All FBM files merged successfully!", flush=True)
|
|
183
|
-
print(f"📊 Merged FBM file: {output_file}", flush=True)
|
|
184
|
-
print(f"📈 Merged {len(fbm_files)} FBM files", flush=True)
|
|
185
|
-
|
|
186
|
-
except Exception as e:
|
|
187
|
-
logger.error(f"Error during FBM merge operation: {e}")
|
|
188
|
-
import traceback
|
|
189
|
-
logger.debug(traceback.format_exc())
|
|
108
|
+
logger.error(f"Error during merge operation: {e}")
|
|
190
109
|
|
|
191
110
|
|
|
192
111
|
def cmd_run(args):
|
|
@@ -219,6 +138,12 @@ _commands = [
|
|
|
219
138
|
nargs="+",
|
|
220
139
|
required=True,
|
|
221
140
|
help="Root directory path of the test results to generate report from"
|
|
141
|
+
),
|
|
142
|
+
dict(
|
|
143
|
+
name=["sync_data"],
|
|
144
|
+
args=["-s", "--sync"],
|
|
145
|
+
action="store_true",
|
|
146
|
+
help="Sync data from device before generating report"
|
|
222
147
|
)
|
|
223
148
|
]
|
|
224
149
|
),
|
|
@@ -243,27 +168,6 @@ _commands = [
|
|
|
243
168
|
help="Output directory for merged report (optional)"
|
|
244
169
|
)
|
|
245
170
|
]
|
|
246
|
-
),
|
|
247
|
-
dict(
|
|
248
|
-
action=cmd_mergefbm,
|
|
249
|
-
command="mergefbm",
|
|
250
|
-
help="merge all FBM files in the specified folder and its subfolders using sum mode",
|
|
251
|
-
flags=[
|
|
252
|
-
dict(
|
|
253
|
-
name=["path"],
|
|
254
|
-
args=["-p", "--path"],
|
|
255
|
-
type=str,
|
|
256
|
-
required=True,
|
|
257
|
-
help="Path to the folder containing FBM files to merge"
|
|
258
|
-
),
|
|
259
|
-
dict(
|
|
260
|
-
name=["output"],
|
|
261
|
-
args=["-o", "--output"],
|
|
262
|
-
type=str,
|
|
263
|
-
required=False,
|
|
264
|
-
help="Output file path for merged FBM file (optional, default: merged.fbm in the input folder)"
|
|
265
|
-
)
|
|
266
|
-
]
|
|
267
171
|
)
|
|
268
172
|
]
|
|
269
173
|
|
|
@@ -16,7 +16,8 @@ from .adbUtils import ADBDevice, ADBStreamShell_V2
|
|
|
16
16
|
|
|
17
17
|
from typing import IO, TYPE_CHECKING, Dict
|
|
18
18
|
if TYPE_CHECKING:
|
|
19
|
-
from .keaUtils import Options
|
|
19
|
+
from .keaUtils import Options
|
|
20
|
+
from .typedefs import PropertyExecutionInfo
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
logger = getLogger(__name__)
|
|
@@ -114,6 +115,7 @@ class FastbotManager:
|
|
|
114
115
|
data={
|
|
115
116
|
"propName": execution_info.propName,
|
|
116
117
|
"startStepsCount": execution_info.startStepsCount,
|
|
118
|
+
"kind": execution_info.kind,
|
|
117
119
|
"state": execution_info.state,
|
|
118
120
|
}
|
|
119
121
|
)
|
|
@@ -235,7 +237,7 @@ class FastbotManager:
|
|
|
235
237
|
|
|
236
238
|
outfile = open(self.log_file, "w", encoding="utf-8", buffering=1)
|
|
237
239
|
|
|
238
|
-
logger.info("Options info: {}".format(
|
|
240
|
+
logger.info("Options info: {}".format(self.options.to_dict()))
|
|
239
241
|
logger.info("Launching fastbot with shell command:\n{}".format(" ".join(full_cmd)))
|
|
240
242
|
logger.info("Fastbot log will be saved to {}".format(outfile.name))
|
|
241
243
|
|
|
@@ -263,5 +265,3 @@ class FastbotManager:
|
|
|
263
265
|
self.thread.join()
|
|
264
266
|
|
|
265
267
|
|
|
266
|
-
|
|
267
|
-
|
|
@@ -106,11 +106,15 @@ class Kea2Tester:
|
|
|
106
106
|
|
|
107
107
|
output_dir = self.options.output_dir
|
|
108
108
|
|
|
109
|
-
from .
|
|
109
|
+
from .utils import StampManager
|
|
110
110
|
|
|
111
111
|
bug_report_path = output_dir / "bug_report.html"
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
stamp_manager = StampManager()
|
|
113
|
+
stamp = stamp_manager.stamp or self.options.log_stamp
|
|
114
|
+
result_name = stamp_manager.result_file.name if stamp_manager.result_file else f"result_{stamp}.json"
|
|
115
|
+
log_name = stamp_manager.log_file.name if stamp_manager.log_file else f"fastbot_{stamp}.log"
|
|
116
|
+
result_json_path = output_dir / result_name
|
|
117
|
+
log_file_path = output_dir / log_name
|
|
114
118
|
|
|
115
119
|
return {
|
|
116
120
|
'executed': True,
|