Kea2-python 0.0.1b0__tar.gz → 0.0.1b2__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 Kea2-python might be problematic. Click here for more details.
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/Kea2_python.egg-info/PKG-INFO +30 -36
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/Kea2_python.egg-info/SOURCES.txt +0 -1
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/PKG-INFO +30 -36
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/README.md +29 -35
- kea2_python-0.0.1b2/kea2/__init__.py +4 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/absDriver.py +4 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/adbUtils.py +34 -1
- kea2_python-0.0.1b2/kea2/assets/monkeyq.jar +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/quicktest.py +3 -3
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/cli.py +2 -1
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/keaUtils.py +90 -19
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/kea_launcher.py +23 -3
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/u2Driver.py +15 -5
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/pyproject.toml +1 -1
- kea2_python-0.0.1b0/kea2/__init__.py +0 -4
- kea2_python-0.0.1b0/kea2/assets/fastbot_configs/ADBKeyBoard.apk +0 -0
- kea2_python-0.0.1b0/kea2/assets/monkeyq.jar +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/Kea2_python.egg-info/dependency_links.txt +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/Kea2_python.egg-info/entry_points.txt +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/Kea2_python.egg-info/requires.txt +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/Kea2_python.egg-info/top_level.txt +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/LICENSE +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot-thirdpart.jar +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_configs/abl.strings +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_configs/awl.strings +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_configs/max.config +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_configs/max.fuzzing.strings +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_configs/max.schema.strings +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_configs/max.strings +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_configs/max.tree.pruning +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_configs/widget.block.py +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_libs/x86/libfastbot_native.so +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_libs/x86_64/libfastbot_native.so +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/framework.jar +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/u2.jar +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/logWatcher.py +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/utils.py +0 -0
- {kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Kea2-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.1b2
|
|
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
|
|
@@ -16,6 +16,10 @@ Dynamic: license-file
|
|
|
16
16
|
[](https://pepy.tech/projects/kea2-python)
|
|
17
17
|

|
|
18
18
|
|
|
19
|
+
<div>
|
|
20
|
+
<img src="https://github.com/user-attachments/assets/58f68b00-cc9c-4620-9e2e-66c43cf7caae" style="border-radius: 14px; width: 20%; height: 20%;"/>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
19
23
|
Kea2 is an easy-to-use Python library for supporting, customizing and improving automated UI testing for mobile apps. The library is currently built on top of [Fastbot](https://github.com/bytedance/Fastbot_Android) and [uiautomator2](https://github.com/openatx/uiautomator2), and targeting [Android](https://en.wikipedia.org/wiki/Android_(operating_system)) apps.
|
|
20
24
|
|
|
21
25
|
### Kea2 has three important features:
|
|
@@ -57,13 +61,14 @@ In the future, Kea2 will be extended to support
|
|
|
57
61
|
Running requirements/environment:
|
|
58
62
|
- support Windows, MacOS and Linux
|
|
59
63
|
- python 3.8+
|
|
64
|
+
- Android 4.4+
|
|
60
65
|
- Android SDK installed
|
|
61
66
|
- **VPN closed** (Features 2 and 3 required)
|
|
62
67
|
|
|
63
68
|
|
|
64
69
|
Install Kea2 by `pip`:
|
|
65
70
|
```bash
|
|
66
|
-
python3 -m pip install
|
|
71
|
+
python3 -m pip install kea2-python
|
|
67
72
|
```
|
|
68
73
|
|
|
69
74
|
Find Kea2's additional options by running
|
|
@@ -300,31 +305,6 @@ class MyFirstTest(unittest.TestCase):
|
|
|
300
305
|
|
|
301
306
|
You can read [Kea - Write your fisrt property](https://kea-docs.readthedocs.io/en/latest/part-keaUserManuel/first_property.html) for more details.
|
|
302
307
|
|
|
303
|
-
### Notes
|
|
304
|
-
Currently, in `@precondition` decorator and `widgets.block.py`. We only support basic selector (No parent-child relationship) in uiautomator2. The Script body in the function fully support uiautomator2.
|
|
305
|
-
|
|
306
|
-
| | **Support** | **Not support** |
|
|
307
|
-
| -- | -- | -- |
|
|
308
|
-
| **Selctor** | `d(text="1").exist` | `d(text="1").child(text="2").exist` |
|
|
309
|
-
|
|
310
|
-
If you need to specify `parent-child` relation ship in `@precondition`, specify it in xpath.
|
|
311
|
-
|
|
312
|
-
for example:
|
|
313
|
-
|
|
314
|
-
```python
|
|
315
|
-
# Do not use:
|
|
316
|
-
# @precondition(lambda self:
|
|
317
|
-
# self.d(className="android.widget.ListView").child(text="Bluetooth")
|
|
318
|
-
# ):
|
|
319
|
-
# ...
|
|
320
|
-
|
|
321
|
-
# Use
|
|
322
|
-
@precondition(lambda self:
|
|
323
|
-
self.d.xpath('//android.widget.ListView/*[@text="Bluetooth"]')
|
|
324
|
-
):
|
|
325
|
-
...
|
|
326
|
-
```
|
|
327
|
-
|
|
328
308
|
|
|
329
309
|
## Launching Kea2
|
|
330
310
|
|
|
@@ -349,16 +329,17 @@ kea2 run -s "emulator-5554" -p it.feio.android.omninotes.alpha --agent u2 --runn
|
|
|
349
329
|
kea2 run -s "emulator-5554" -p it.feio.android.omninotes.alpha --agent u2 --running-minutes 10 --throttle 200 --driver-name d unittest discover -s mytests/omni_notes
|
|
350
330
|
```
|
|
351
331
|
|
|
352
|
-
| arg | meaning |
|
|
353
|
-
| --- | --- |
|
|
354
|
-
| -s | The serial of your device, which can be found by `adb devices` |
|
|
355
|
-
| -p | The tested app's package name (e.g., com.example.app) |
|
|
356
|
-
| -o | The ouput directory for logs and results |
|
|
357
|
-
| --agent | {native, u2}. By default, `u2` is used and supports all the three important features of Kea2. If you hope to run the orignal Fastbot, please use `native`.|
|
|
358
|
-
| --running-minutes | The time (m) to run Kea2 |
|
|
359
|
-
| --max-step | The maxium number of monkey events to send (only available in `--agent u2`) |
|
|
360
|
-
| --throttle | The delay time (ms) between two monkey events |
|
|
332
|
+
| arg | meaning | default |
|
|
333
|
+
| --- | --- | --- |
|
|
334
|
+
| -s | The serial of your device, which can be found by `adb devices` | |
|
|
335
|
+
| -p | *The tested app's package name (e.g., com.example.app) |
|
|
336
|
+
| -o | The ouput directory for logs and results | `output` |
|
|
337
|
+
| --agent | {native, u2}. By default, `u2` is used and supports all the three important features of Kea2. If you hope to run the orignal Fastbot, please use `native`.| `u2` |
|
|
338
|
+
| --running-minutes | The time (m) to run Kea2 | `10` |
|
|
339
|
+
| --max-step | The maxium number of monkey events to send (only available in `--agent u2`) | `inf` |
|
|
340
|
+
| --throttle | The delay time (ms) between two monkey events | `200` |
|
|
361
341
|
| --driver-name | The name of driver used in the script. If `--driver-name d` is specified, you should use `d` to interact with a device, e..g, `self.d(..).click()`. |
|
|
342
|
+
| --log-stamp | the stamp for log file and result file, default: current time stamp | |
|
|
362
343
|
| unittest | Specify to load which scripts. This sub-command `unittest` is fully compatible with unittest. See `python3 -m unittest -h` for more options of unittest. This option is only available in `--agent u2`.
|
|
363
344
|
|
|
364
345
|
|
|
@@ -421,6 +402,8 @@ running_mins: int = 10
|
|
|
421
402
|
throttle: int = 200
|
|
422
403
|
# the output_dir for saving logs and results
|
|
423
404
|
output_dir: str = "output"
|
|
405
|
+
# the stamp for log file and result file, default: current time stamp
|
|
406
|
+
log_stamp: str = None
|
|
424
407
|
```
|
|
425
408
|
|
|
426
409
|
## Examining the running statistics of scripts .
|
|
@@ -465,6 +448,17 @@ Kea2 has been actively developed and maintained by the people in [ecnusse](https
|
|
|
465
448
|
- [uiautomator2](https://github.com/openatx/uiautomator2)
|
|
466
449
|
- [hypothesis](https://github.com/HypothesisWorks/hypothesis)
|
|
467
450
|
|
|
451
|
+
### Relevant papers of Kea2
|
|
452
|
+
|
|
453
|
+
> General and Practical Property-based Testing for Android Apps. ASE 2024. [pdf](https://dl.acm.org/doi/10.1145/3691620.3694986)
|
|
454
|
+
|
|
455
|
+
> An Empirical Study of Functional Bugs in Android Apps. ISSTA 2023. [pdf](https://dl.acm.org/doi/10.1145/3597926.3598138)
|
|
456
|
+
|
|
457
|
+
> Fastbot2: Reusable Automated Model-based GUI Testing for Android Enhanced by Reinforcement Learning. ASE 2022. [pdf](https://dl.acm.org/doi/10.1145/3551349.3559505)
|
|
458
|
+
|
|
459
|
+
> Guided, Stochastic Model-Based GUI Testing of Android Apps. ESEC/FSE 2017. [pdf](https://dl.acm.org/doi/10.1145/3106237.3106298)
|
|
460
|
+
|
|
461
|
+
|
|
468
462
|
[^1]: 不少UI自动化测试工具提供了“自定义事件序列”能力(如[Fastbot](https://github.com/bytedance/Fastbot_Android/blob/main/handbook-cn.md#%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6%E5%BA%8F%E5%88%97) 和[AppCrawler](https://github.com/seveniruby/AppCrawler)),但在实际使用中存在不少问题,如自定义能力有限、使用不灵活等。此前不少Fastbot用户抱怨过其“自定义事件序列”在使用中的问题,如[#209](https://github.com/bytedance/Fastbot_Android/issues/209), [#225](https://github.com/bytedance/Fastbot_Android/issues/225), [#286](https://github.com/bytedance/Fastbot_Android/issues/286)等。
|
|
469
463
|
|
|
470
464
|
[^2]: 在UI自动化测试过程中支持自动断言是一个很重要的能力,但几乎没有测试工具提供这样的能力。我们注意到[AppCrawler](https://ceshiren.com/t/topic/15801/5)的开发者曾经希望提供一种断言机制,得到了用户的热切响应,不少用户从21年就开始催更,但始终未能实现。
|
|
@@ -21,7 +21,6 @@ kea2/assets/framework.jar
|
|
|
21
21
|
kea2/assets/monkeyq.jar
|
|
22
22
|
kea2/assets/quicktest.py
|
|
23
23
|
kea2/assets/u2.jar
|
|
24
|
-
kea2/assets/fastbot_configs/ADBKeyBoard.apk
|
|
25
24
|
kea2/assets/fastbot_configs/abl.strings
|
|
26
25
|
kea2/assets/fastbot_configs/awl.strings
|
|
27
26
|
kea2/assets/fastbot_configs/max.config
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Kea2-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.1b2
|
|
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
|
|
@@ -16,6 +16,10 @@ Dynamic: license-file
|
|
|
16
16
|
[](https://pepy.tech/projects/kea2-python)
|
|
17
17
|

|
|
18
18
|
|
|
19
|
+
<div>
|
|
20
|
+
<img src="https://github.com/user-attachments/assets/58f68b00-cc9c-4620-9e2e-66c43cf7caae" style="border-radius: 14px; width: 20%; height: 20%;"/>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
19
23
|
Kea2 is an easy-to-use Python library for supporting, customizing and improving automated UI testing for mobile apps. The library is currently built on top of [Fastbot](https://github.com/bytedance/Fastbot_Android) and [uiautomator2](https://github.com/openatx/uiautomator2), and targeting [Android](https://en.wikipedia.org/wiki/Android_(operating_system)) apps.
|
|
20
24
|
|
|
21
25
|
### Kea2 has three important features:
|
|
@@ -57,13 +61,14 @@ In the future, Kea2 will be extended to support
|
|
|
57
61
|
Running requirements/environment:
|
|
58
62
|
- support Windows, MacOS and Linux
|
|
59
63
|
- python 3.8+
|
|
64
|
+
- Android 4.4+
|
|
60
65
|
- Android SDK installed
|
|
61
66
|
- **VPN closed** (Features 2 and 3 required)
|
|
62
67
|
|
|
63
68
|
|
|
64
69
|
Install Kea2 by `pip`:
|
|
65
70
|
```bash
|
|
66
|
-
python3 -m pip install
|
|
71
|
+
python3 -m pip install kea2-python
|
|
67
72
|
```
|
|
68
73
|
|
|
69
74
|
Find Kea2's additional options by running
|
|
@@ -300,31 +305,6 @@ class MyFirstTest(unittest.TestCase):
|
|
|
300
305
|
|
|
301
306
|
You can read [Kea - Write your fisrt property](https://kea-docs.readthedocs.io/en/latest/part-keaUserManuel/first_property.html) for more details.
|
|
302
307
|
|
|
303
|
-
### Notes
|
|
304
|
-
Currently, in `@precondition` decorator and `widgets.block.py`. We only support basic selector (No parent-child relationship) in uiautomator2. The Script body in the function fully support uiautomator2.
|
|
305
|
-
|
|
306
|
-
| | **Support** | **Not support** |
|
|
307
|
-
| -- | -- | -- |
|
|
308
|
-
| **Selctor** | `d(text="1").exist` | `d(text="1").child(text="2").exist` |
|
|
309
|
-
|
|
310
|
-
If you need to specify `parent-child` relation ship in `@precondition`, specify it in xpath.
|
|
311
|
-
|
|
312
|
-
for example:
|
|
313
|
-
|
|
314
|
-
```python
|
|
315
|
-
# Do not use:
|
|
316
|
-
# @precondition(lambda self:
|
|
317
|
-
# self.d(className="android.widget.ListView").child(text="Bluetooth")
|
|
318
|
-
# ):
|
|
319
|
-
# ...
|
|
320
|
-
|
|
321
|
-
# Use
|
|
322
|
-
@precondition(lambda self:
|
|
323
|
-
self.d.xpath('//android.widget.ListView/*[@text="Bluetooth"]')
|
|
324
|
-
):
|
|
325
|
-
...
|
|
326
|
-
```
|
|
327
|
-
|
|
328
308
|
|
|
329
309
|
## Launching Kea2
|
|
330
310
|
|
|
@@ -349,16 +329,17 @@ kea2 run -s "emulator-5554" -p it.feio.android.omninotes.alpha --agent u2 --runn
|
|
|
349
329
|
kea2 run -s "emulator-5554" -p it.feio.android.omninotes.alpha --agent u2 --running-minutes 10 --throttle 200 --driver-name d unittest discover -s mytests/omni_notes
|
|
350
330
|
```
|
|
351
331
|
|
|
352
|
-
| arg | meaning |
|
|
353
|
-
| --- | --- |
|
|
354
|
-
| -s | The serial of your device, which can be found by `adb devices` |
|
|
355
|
-
| -p | The tested app's package name (e.g., com.example.app) |
|
|
356
|
-
| -o | The ouput directory for logs and results |
|
|
357
|
-
| --agent | {native, u2}. By default, `u2` is used and supports all the three important features of Kea2. If you hope to run the orignal Fastbot, please use `native`.|
|
|
358
|
-
| --running-minutes | The time (m) to run Kea2 |
|
|
359
|
-
| --max-step | The maxium number of monkey events to send (only available in `--agent u2`) |
|
|
360
|
-
| --throttle | The delay time (ms) between two monkey events |
|
|
332
|
+
| arg | meaning | default |
|
|
333
|
+
| --- | --- | --- |
|
|
334
|
+
| -s | The serial of your device, which can be found by `adb devices` | |
|
|
335
|
+
| -p | *The tested app's package name (e.g., com.example.app) |
|
|
336
|
+
| -o | The ouput directory for logs and results | `output` |
|
|
337
|
+
| --agent | {native, u2}. By default, `u2` is used and supports all the three important features of Kea2. If you hope to run the orignal Fastbot, please use `native`.| `u2` |
|
|
338
|
+
| --running-minutes | The time (m) to run Kea2 | `10` |
|
|
339
|
+
| --max-step | The maxium number of monkey events to send (only available in `--agent u2`) | `inf` |
|
|
340
|
+
| --throttle | The delay time (ms) between two monkey events | `200` |
|
|
361
341
|
| --driver-name | The name of driver used in the script. If `--driver-name d` is specified, you should use `d` to interact with a device, e..g, `self.d(..).click()`. |
|
|
342
|
+
| --log-stamp | the stamp for log file and result file, default: current time stamp | |
|
|
362
343
|
| unittest | Specify to load which scripts. This sub-command `unittest` is fully compatible with unittest. See `python3 -m unittest -h` for more options of unittest. This option is only available in `--agent u2`.
|
|
363
344
|
|
|
364
345
|
|
|
@@ -421,6 +402,8 @@ running_mins: int = 10
|
|
|
421
402
|
throttle: int = 200
|
|
422
403
|
# the output_dir for saving logs and results
|
|
423
404
|
output_dir: str = "output"
|
|
405
|
+
# the stamp for log file and result file, default: current time stamp
|
|
406
|
+
log_stamp: str = None
|
|
424
407
|
```
|
|
425
408
|
|
|
426
409
|
## Examining the running statistics of scripts .
|
|
@@ -465,6 +448,17 @@ Kea2 has been actively developed and maintained by the people in [ecnusse](https
|
|
|
465
448
|
- [uiautomator2](https://github.com/openatx/uiautomator2)
|
|
466
449
|
- [hypothesis](https://github.com/HypothesisWorks/hypothesis)
|
|
467
450
|
|
|
451
|
+
### Relevant papers of Kea2
|
|
452
|
+
|
|
453
|
+
> General and Practical Property-based Testing for Android Apps. ASE 2024. [pdf](https://dl.acm.org/doi/10.1145/3691620.3694986)
|
|
454
|
+
|
|
455
|
+
> An Empirical Study of Functional Bugs in Android Apps. ISSTA 2023. [pdf](https://dl.acm.org/doi/10.1145/3597926.3598138)
|
|
456
|
+
|
|
457
|
+
> Fastbot2: Reusable Automated Model-based GUI Testing for Android Enhanced by Reinforcement Learning. ASE 2022. [pdf](https://dl.acm.org/doi/10.1145/3551349.3559505)
|
|
458
|
+
|
|
459
|
+
> Guided, Stochastic Model-Based GUI Testing of Android Apps. ESEC/FSE 2017. [pdf](https://dl.acm.org/doi/10.1145/3106237.3106298)
|
|
460
|
+
|
|
461
|
+
|
|
468
462
|
[^1]: 不少UI自动化测试工具提供了“自定义事件序列”能力(如[Fastbot](https://github.com/bytedance/Fastbot_Android/blob/main/handbook-cn.md#%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6%E5%BA%8F%E5%88%97) 和[AppCrawler](https://github.com/seveniruby/AppCrawler)),但在实际使用中存在不少问题,如自定义能力有限、使用不灵活等。此前不少Fastbot用户抱怨过其“自定义事件序列”在使用中的问题,如[#209](https://github.com/bytedance/Fastbot_Android/issues/209), [#225](https://github.com/bytedance/Fastbot_Android/issues/225), [#286](https://github.com/bytedance/Fastbot_Android/issues/286)等。
|
|
469
463
|
|
|
470
464
|
[^2]: 在UI自动化测试过程中支持自动断言是一个很重要的能力,但几乎没有测试工具提供这样的能力。我们注意到[AppCrawler](https://ceshiren.com/t/topic/15801/5)的开发者曾经希望提供一种断言机制,得到了用户的热切响应,不少用户从21年就开始催更,但始终未能实现。
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
[](https://pepy.tech/projects/kea2-python)
|
|
5
5
|

|
|
6
6
|
|
|
7
|
+
<div>
|
|
8
|
+
<img src="https://github.com/user-attachments/assets/58f68b00-cc9c-4620-9e2e-66c43cf7caae" style="border-radius: 14px; width: 20%; height: 20%;"/>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
7
11
|
Kea2 is an easy-to-use Python library for supporting, customizing and improving automated UI testing for mobile apps. The library is currently built on top of [Fastbot](https://github.com/bytedance/Fastbot_Android) and [uiautomator2](https://github.com/openatx/uiautomator2), and targeting [Android](https://en.wikipedia.org/wiki/Android_(operating_system)) apps.
|
|
8
12
|
|
|
9
13
|
### Kea2 has three important features:
|
|
@@ -45,13 +49,14 @@ In the future, Kea2 will be extended to support
|
|
|
45
49
|
Running requirements/environment:
|
|
46
50
|
- support Windows, MacOS and Linux
|
|
47
51
|
- python 3.8+
|
|
52
|
+
- Android 4.4+
|
|
48
53
|
- Android SDK installed
|
|
49
54
|
- **VPN closed** (Features 2 and 3 required)
|
|
50
55
|
|
|
51
56
|
|
|
52
57
|
Install Kea2 by `pip`:
|
|
53
58
|
```bash
|
|
54
|
-
python3 -m pip install
|
|
59
|
+
python3 -m pip install kea2-python
|
|
55
60
|
```
|
|
56
61
|
|
|
57
62
|
Find Kea2's additional options by running
|
|
@@ -288,31 +293,6 @@ class MyFirstTest(unittest.TestCase):
|
|
|
288
293
|
|
|
289
294
|
You can read [Kea - Write your fisrt property](https://kea-docs.readthedocs.io/en/latest/part-keaUserManuel/first_property.html) for more details.
|
|
290
295
|
|
|
291
|
-
### Notes
|
|
292
|
-
Currently, in `@precondition` decorator and `widgets.block.py`. We only support basic selector (No parent-child relationship) in uiautomator2. The Script body in the function fully support uiautomator2.
|
|
293
|
-
|
|
294
|
-
| | **Support** | **Not support** |
|
|
295
|
-
| -- | -- | -- |
|
|
296
|
-
| **Selctor** | `d(text="1").exist` | `d(text="1").child(text="2").exist` |
|
|
297
|
-
|
|
298
|
-
If you need to specify `parent-child` relation ship in `@precondition`, specify it in xpath.
|
|
299
|
-
|
|
300
|
-
for example:
|
|
301
|
-
|
|
302
|
-
```python
|
|
303
|
-
# Do not use:
|
|
304
|
-
# @precondition(lambda self:
|
|
305
|
-
# self.d(className="android.widget.ListView").child(text="Bluetooth")
|
|
306
|
-
# ):
|
|
307
|
-
# ...
|
|
308
|
-
|
|
309
|
-
# Use
|
|
310
|
-
@precondition(lambda self:
|
|
311
|
-
self.d.xpath('//android.widget.ListView/*[@text="Bluetooth"]')
|
|
312
|
-
):
|
|
313
|
-
...
|
|
314
|
-
```
|
|
315
|
-
|
|
316
296
|
|
|
317
297
|
## Launching Kea2
|
|
318
298
|
|
|
@@ -337,16 +317,17 @@ kea2 run -s "emulator-5554" -p it.feio.android.omninotes.alpha --agent u2 --runn
|
|
|
337
317
|
kea2 run -s "emulator-5554" -p it.feio.android.omninotes.alpha --agent u2 --running-minutes 10 --throttle 200 --driver-name d unittest discover -s mytests/omni_notes
|
|
338
318
|
```
|
|
339
319
|
|
|
340
|
-
| arg | meaning |
|
|
341
|
-
| --- | --- |
|
|
342
|
-
| -s | The serial of your device, which can be found by `adb devices` |
|
|
343
|
-
| -p | The tested app's package name (e.g., com.example.app) |
|
|
344
|
-
| -o | The ouput directory for logs and results |
|
|
345
|
-
| --agent | {native, u2}. By default, `u2` is used and supports all the three important features of Kea2. If you hope to run the orignal Fastbot, please use `native`.|
|
|
346
|
-
| --running-minutes | The time (m) to run Kea2 |
|
|
347
|
-
| --max-step | The maxium number of monkey events to send (only available in `--agent u2`) |
|
|
348
|
-
| --throttle | The delay time (ms) between two monkey events |
|
|
320
|
+
| arg | meaning | default |
|
|
321
|
+
| --- | --- | --- |
|
|
322
|
+
| -s | The serial of your device, which can be found by `adb devices` | |
|
|
323
|
+
| -p | *The tested app's package name (e.g., com.example.app) |
|
|
324
|
+
| -o | The ouput directory for logs and results | `output` |
|
|
325
|
+
| --agent | {native, u2}. By default, `u2` is used and supports all the three important features of Kea2. If you hope to run the orignal Fastbot, please use `native`.| `u2` |
|
|
326
|
+
| --running-minutes | The time (m) to run Kea2 | `10` |
|
|
327
|
+
| --max-step | The maxium number of monkey events to send (only available in `--agent u2`) | `inf` |
|
|
328
|
+
| --throttle | The delay time (ms) between two monkey events | `200` |
|
|
349
329
|
| --driver-name | The name of driver used in the script. If `--driver-name d` is specified, you should use `d` to interact with a device, e..g, `self.d(..).click()`. |
|
|
330
|
+
| --log-stamp | the stamp for log file and result file, default: current time stamp | |
|
|
350
331
|
| unittest | Specify to load which scripts. This sub-command `unittest` is fully compatible with unittest. See `python3 -m unittest -h` for more options of unittest. This option is only available in `--agent u2`.
|
|
351
332
|
|
|
352
333
|
|
|
@@ -409,6 +390,8 @@ running_mins: int = 10
|
|
|
409
390
|
throttle: int = 200
|
|
410
391
|
# the output_dir for saving logs and results
|
|
411
392
|
output_dir: str = "output"
|
|
393
|
+
# the stamp for log file and result file, default: current time stamp
|
|
394
|
+
log_stamp: str = None
|
|
412
395
|
```
|
|
413
396
|
|
|
414
397
|
## Examining the running statistics of scripts .
|
|
@@ -453,6 +436,17 @@ Kea2 has been actively developed and maintained by the people in [ecnusse](https
|
|
|
453
436
|
- [uiautomator2](https://github.com/openatx/uiautomator2)
|
|
454
437
|
- [hypothesis](https://github.com/HypothesisWorks/hypothesis)
|
|
455
438
|
|
|
439
|
+
### Relevant papers of Kea2
|
|
440
|
+
|
|
441
|
+
> General and Practical Property-based Testing for Android Apps. ASE 2024. [pdf](https://dl.acm.org/doi/10.1145/3691620.3694986)
|
|
442
|
+
|
|
443
|
+
> An Empirical Study of Functional Bugs in Android Apps. ISSTA 2023. [pdf](https://dl.acm.org/doi/10.1145/3597926.3598138)
|
|
444
|
+
|
|
445
|
+
> Fastbot2: Reusable Automated Model-based GUI Testing for Android Enhanced by Reinforcement Learning. ASE 2022. [pdf](https://dl.acm.org/doi/10.1145/3551349.3559505)
|
|
446
|
+
|
|
447
|
+
> Guided, Stochastic Model-Based GUI Testing of Android Apps. ESEC/FSE 2017. [pdf](https://dl.acm.org/doi/10.1145/3106237.3106298)
|
|
448
|
+
|
|
449
|
+
|
|
456
450
|
[^1]: 不少UI自动化测试工具提供了“自定义事件序列”能力(如[Fastbot](https://github.com/bytedance/Fastbot_Android/blob/main/handbook-cn.md#%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6%E5%BA%8F%E5%88%97) 和[AppCrawler](https://github.com/seveniruby/AppCrawler)),但在实际使用中存在不少问题,如自定义能力有限、使用不灵活等。此前不少Fastbot用户抱怨过其“自定义事件序列”在使用中的问题,如[#209](https://github.com/bytedance/Fastbot_Android/issues/209), [#225](https://github.com/bytedance/Fastbot_Android/issues/225), [#286](https://github.com/bytedance/Fastbot_Android/issues/286)等。
|
|
457
451
|
|
|
458
452
|
[^2]: 在UI自动化测试过程中支持自动断言是一个很重要的能力,但几乎没有测试工具提供这样的能力。我们注意到[AppCrawler](https://ceshiren.com/t/topic/15801/5)的开发者曾经希望提供一种断言机制,得到了用户的热切响应,不少用户从21年就开始催更,但始终未能实现。
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import subprocess
|
|
2
|
-
from typing import List, Optional
|
|
2
|
+
from typing import List, Optional, Set
|
|
3
|
+
from .utils import getLogger
|
|
4
|
+
|
|
5
|
+
logger = getLogger(__name__)
|
|
6
|
+
|
|
3
7
|
|
|
4
8
|
def run_adb_command(cmd: List[str], timeout=10):
|
|
5
9
|
"""
|
|
@@ -13,6 +17,7 @@ def run_adb_command(cmd: List[str], timeout=10):
|
|
|
13
17
|
str: The standard output from the command. If an error occurs, returns None.
|
|
14
18
|
"""
|
|
15
19
|
full_cmd = ["adb"] + cmd
|
|
20
|
+
logger.debug(f"{' '.join(full_cmd)}")
|
|
16
21
|
try:
|
|
17
22
|
result = subprocess.run(full_cmd, capture_output=True, text=True, timeout=timeout)
|
|
18
23
|
if result.returncode != 0:
|
|
@@ -218,6 +223,34 @@ def remove_all_forwards(device: Optional[str] = None):
|
|
|
218
223
|
return run_adb_command(["-s", device, "forward", "--remove-all"])
|
|
219
224
|
|
|
220
225
|
|
|
226
|
+
@ensure_device
|
|
227
|
+
def get_packages(device: Optional[str] = None) -> Set[str]:
|
|
228
|
+
"""
|
|
229
|
+
Retrieves packages that match the specified regular expression pattern.
|
|
230
|
+
|
|
231
|
+
Parameters:
|
|
232
|
+
pattern (str): Regular expression pattern to match package names.
|
|
233
|
+
device (str, optional): The device serial number. If None, it is resolved automatically.
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
set: A set of package names that match the pattern.
|
|
237
|
+
"""
|
|
238
|
+
import re
|
|
239
|
+
|
|
240
|
+
cmd = ["-s", device, "shell", "pm", "list", "packages"]
|
|
241
|
+
output = run_adb_command(cmd)
|
|
242
|
+
|
|
243
|
+
packages = set()
|
|
244
|
+
if output:
|
|
245
|
+
compiled_pattern = re.compile(r"package:(.+)\n")
|
|
246
|
+
matches = compiled_pattern.findall(output)
|
|
247
|
+
for match in matches:
|
|
248
|
+
if match:
|
|
249
|
+
packages.add(match)
|
|
250
|
+
|
|
251
|
+
return packages
|
|
252
|
+
|
|
253
|
+
|
|
221
254
|
if __name__ == '__main__':
|
|
222
255
|
# For testing: print the list of currently connected devices.
|
|
223
256
|
devices = get_devices()
|
|
Binary file
|
|
@@ -57,7 +57,7 @@ PACKAGE_NAME = "it.feio.android.omninotes.alpha"
|
|
|
57
57
|
FILE_NAME = "omninotes.apk"
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
def check_installation():
|
|
60
|
+
def check_installation(serial=None):
|
|
61
61
|
import os
|
|
62
62
|
from pathlib import Path
|
|
63
63
|
if not os.path.exists(Path(".") / FILE_NAME):
|
|
@@ -65,7 +65,7 @@ def check_installation():
|
|
|
65
65
|
import urllib.request
|
|
66
66
|
urllib.request.urlretrieve(URL, FILE_NAME)
|
|
67
67
|
|
|
68
|
-
d = u2.connect()
|
|
68
|
+
d = u2.connect(serial)
|
|
69
69
|
# automatically install omni-notes
|
|
70
70
|
if PACKAGE_NAME not in d.app_list():
|
|
71
71
|
print("[INFO] Installing omninotes.", flush=True)
|
|
@@ -74,7 +74,7 @@ def check_installation():
|
|
|
74
74
|
|
|
75
75
|
|
|
76
76
|
if __name__ == "__main__":
|
|
77
|
-
check_installation()
|
|
77
|
+
check_installation(serial=None)
|
|
78
78
|
KeaTestRunner.setOptions(
|
|
79
79
|
Options(
|
|
80
80
|
driverName="d",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
from __future__ import absolute_import, print_function
|
|
5
5
|
import sys
|
|
6
|
-
from
|
|
6
|
+
from .utils import getProjectRoot, getLogger
|
|
7
7
|
from .kea_launcher import run
|
|
8
8
|
import argparse
|
|
9
9
|
|
|
@@ -99,6 +99,7 @@ def main():
|
|
|
99
99
|
args = parser.parse_args()
|
|
100
100
|
|
|
101
101
|
import logging
|
|
102
|
+
logging.basicConfig(level=logging.INFO)
|
|
102
103
|
if args.debug:
|
|
103
104
|
logging.basicConfig(level=logging.DEBUG)
|
|
104
105
|
logger.debug("args: %s", args)
|
|
@@ -19,9 +19,10 @@ from .utils import TimeStamp, getProjectRoot, getLogger
|
|
|
19
19
|
from .u2Driver import StaticU2UiObject
|
|
20
20
|
import uiautomator2 as u2
|
|
21
21
|
import types
|
|
22
|
+
|
|
22
23
|
PRECONDITIONS_MARKER = "preconds"
|
|
23
24
|
PROP_MARKER = "prop"
|
|
24
|
-
|
|
25
|
+
MAX_TRIES_MARKER = "max_tries"
|
|
25
26
|
|
|
26
27
|
logger = getLogger(__name__)
|
|
27
28
|
|
|
@@ -30,14 +31,14 @@ logger = getLogger(__name__)
|
|
|
30
31
|
PropName = NewType("PropName", str)
|
|
31
32
|
PropertyStore = NewType("PropertyStore", Dict[PropName, TestCase])
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
LOGFILE = f"fastbot_{
|
|
35
|
-
RESFILE = f"result_{
|
|
34
|
+
STAMP = TimeStamp().getTimeStamp()
|
|
35
|
+
LOGFILE = f"fastbot_{STAMP}.log"
|
|
36
|
+
RESFILE = f"result_{STAMP}.json"
|
|
36
37
|
|
|
37
38
|
def precondition(precond: Callable[[Any], bool]) -> Callable:
|
|
38
39
|
"""the decorator @precondition
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
@precondition specifies when the property could be executed.
|
|
41
42
|
A property could have multiple preconditions, each of which is specified by @precondition.
|
|
42
43
|
"""
|
|
43
44
|
def accept(f):
|
|
@@ -56,7 +57,7 @@ def precondition(precond: Callable[[Any], bool]) -> Callable:
|
|
|
56
57
|
def prob(p: float):
|
|
57
58
|
"""the decorator @prob
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
@prob specify the propbability of execution when a property is satisfied.
|
|
60
61
|
"""
|
|
61
62
|
p = float(p)
|
|
62
63
|
if not 0 < p <= 1.0:
|
|
@@ -73,6 +74,26 @@ def prob(p: float):
|
|
|
73
74
|
return accept
|
|
74
75
|
|
|
75
76
|
|
|
77
|
+
def max_tries(n: int):
|
|
78
|
+
"""the decorator @max_tries
|
|
79
|
+
|
|
80
|
+
@max_tries specify the maximum tries of executing a property.
|
|
81
|
+
"""
|
|
82
|
+
n = int(n)
|
|
83
|
+
if not n > 0:
|
|
84
|
+
raise ValueError("The maxium tries should be a positive integer.")
|
|
85
|
+
def accept(f):
|
|
86
|
+
@wraps(f)
|
|
87
|
+
def precondition_wrapper(*args, **kwargs):
|
|
88
|
+
return f(*args, **kwargs)
|
|
89
|
+
|
|
90
|
+
setattr(precondition_wrapper, MAX_TRIES_MARKER, n)
|
|
91
|
+
|
|
92
|
+
return precondition_wrapper
|
|
93
|
+
|
|
94
|
+
return accept
|
|
95
|
+
|
|
96
|
+
|
|
76
97
|
@dataclass
|
|
77
98
|
class Options:
|
|
78
99
|
"""
|
|
@@ -96,10 +117,34 @@ class Options:
|
|
|
96
117
|
throttle: int = 200
|
|
97
118
|
# the output_dir for saving logs and results
|
|
98
119
|
output_dir: str = "output"
|
|
120
|
+
# the stamp for log file and result file, default: current time stamp
|
|
121
|
+
log_stamp: str = None
|
|
122
|
+
# the profiling period to get the coverage result.
|
|
123
|
+
profile_period: int = None
|
|
124
|
+
|
|
125
|
+
def __setattr__(self, name, value):
|
|
126
|
+
if value is None:
|
|
127
|
+
return
|
|
128
|
+
super().__setattr__(name, value)
|
|
99
129
|
|
|
100
130
|
def __post_init__(self):
|
|
101
131
|
if self.serial and self.Driver:
|
|
102
132
|
self.Driver.setDeviceSerial(self.serial)
|
|
133
|
+
if self.log_stamp:
|
|
134
|
+
global LOGFILE, RESFILE
|
|
135
|
+
LOGFILE = f"fastbot_{self.log_stamp}.log"
|
|
136
|
+
RESFILE = f"result_{self.log_stamp}.json"
|
|
137
|
+
_check_package_installation(self.serial, self.packageNames)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _check_package_installation(serial, packageNames):
|
|
141
|
+
from .adbUtils import get_packages
|
|
142
|
+
installed_packages = get_packages(device=serial)
|
|
143
|
+
|
|
144
|
+
for package in packageNames:
|
|
145
|
+
if package not in installed_packages:
|
|
146
|
+
logger.error(f"package {package} not installed. Abort.")
|
|
147
|
+
raise ValueError("package not installed")
|
|
103
148
|
|
|
104
149
|
|
|
105
150
|
@dataclass
|
|
@@ -151,6 +196,9 @@ class JsonResult(TextTestResult):
|
|
|
151
196
|
super().addError(test, err)
|
|
152
197
|
self.res[getFullPropName(test)].error += 1
|
|
153
198
|
|
|
199
|
+
def getExcuted(self, test: TestCase):
|
|
200
|
+
return self.res[getFullPropName(test)].executed
|
|
201
|
+
|
|
154
202
|
|
|
155
203
|
def activateFastbot(options: Options, port=None) -> threading.Thread:
|
|
156
204
|
"""
|
|
@@ -227,7 +275,7 @@ def startFastbotService(options: Options) -> threading.Thread:
|
|
|
227
275
|
"reuseq",
|
|
228
276
|
"--running-minutes", f"{options.running_mins}",
|
|
229
277
|
"--throttle", f"{options.throttle}",
|
|
230
|
-
"--bugreport", "--output-directory", "/sdcard/fastbot_report"
|
|
278
|
+
"--bugreport", "--output-directory", "/sdcard/fastbot_report",
|
|
231
279
|
"-v", "-v", "-v"
|
|
232
280
|
]
|
|
233
281
|
|
|
@@ -274,6 +322,8 @@ class KeaTestRunner(TextTestRunner):
|
|
|
274
322
|
global LOGFILE, RESFILE
|
|
275
323
|
LOGFILE = output_dir / Path(LOGFILE)
|
|
276
324
|
RESFILE = output_dir / Path(RESFILE)
|
|
325
|
+
logger.debug(f"Log file: {LOGFILE}")
|
|
326
|
+
logger.debug(f"Result file: {RESFILE}")
|
|
277
327
|
|
|
278
328
|
def run(self, test):
|
|
279
329
|
|
|
@@ -322,18 +372,20 @@ class KeaTestRunner(TextTestRunner):
|
|
|
322
372
|
check_alive(port=self.scriptDriver.lport)
|
|
323
373
|
|
|
324
374
|
end_by_remote = False
|
|
325
|
-
|
|
326
|
-
while
|
|
375
|
+
self.stepsCount = 0
|
|
376
|
+
while self.stepsCount < self.options.maxStep:
|
|
327
377
|
|
|
328
|
-
|
|
378
|
+
self.stepsCount += 1
|
|
329
379
|
print("[INFO] Sending monkeyEvent {}".format(
|
|
330
|
-
f"({
|
|
331
|
-
else f"({
|
|
380
|
+
f"({self.stepsCount} / {self.options.maxStep})" if self.options.maxStep != float("inf")
|
|
381
|
+
else f"({self.stepsCount})"
|
|
332
382
|
)
|
|
333
383
|
, flush=True)
|
|
334
384
|
|
|
335
385
|
try:
|
|
336
|
-
|
|
386
|
+
xml_raw = self.stepMonkey()
|
|
387
|
+
stat = self._getStat()
|
|
388
|
+
propsSatisfiedPrecond = self.getValidProperties(xml_raw, result)
|
|
337
389
|
except requests.ConnectionError:
|
|
338
390
|
print(
|
|
339
391
|
"[INFO] Exploration times up (--running-minutes)."
|
|
@@ -425,9 +477,12 @@ class KeaTestRunner(TextTestRunner):
|
|
|
425
477
|
"""
|
|
426
478
|
block_widgets: List[str] = self._getBlockedWidgets()
|
|
427
479
|
URL = f"http://localhost:{self.scriptDriver.lport}/stepMonkey"
|
|
480
|
+
logger.debug(f"Sending request: {URL}")
|
|
481
|
+
logger.debug(f"Blocking widgets: {block_widgets}")
|
|
428
482
|
r = requests.post(
|
|
429
483
|
url=URL,
|
|
430
484
|
json={
|
|
485
|
+
"steps_count": self.stepsCount,
|
|
431
486
|
"block_widgets": block_widgets
|
|
432
487
|
}
|
|
433
488
|
)
|
|
@@ -440,14 +495,15 @@ class KeaTestRunner(TextTestRunner):
|
|
|
440
495
|
"""
|
|
441
496
|
send a stop monkey request to the server and get the xml string.
|
|
442
497
|
"""
|
|
443
|
-
|
|
498
|
+
URL = f"http://localhost:{self.scriptDriver.lport}/stopMonkey"
|
|
499
|
+
logger.debug(f"Sending request: {URL}")
|
|
500
|
+
r = requests.get(URL)
|
|
444
501
|
|
|
445
502
|
res = r.content.decode(encoding="utf-8")
|
|
446
503
|
print(f"[Server INFO] {res}", flush=True)
|
|
447
504
|
|
|
448
|
-
def getValidProperties(self) -> PropertyStore:
|
|
505
|
+
def getValidProperties(self, xml_raw: str, result: JsonResult) -> PropertyStore:
|
|
449
506
|
|
|
450
|
-
xml_raw = self.stepMonkey()
|
|
451
507
|
staticCheckerDriver = self.options.Driver.getStaticChecker(hierarchy=xml_raw)
|
|
452
508
|
|
|
453
509
|
validProps: PropertyStore = dict()
|
|
@@ -470,9 +526,22 @@ class KeaTestRunner(TextTestRunner):
|
|
|
470
526
|
break
|
|
471
527
|
# if all the precond passed. make it the candidate prop.
|
|
472
528
|
if valid:
|
|
529
|
+
logger.debug(f"precond satisfied: {getFullPropName(test)}")
|
|
530
|
+
if result.getExcuted(test) >= getattr(prop, MAX_TRIES_MARKER, float("inf")):
|
|
531
|
+
logger.debug(f"{getFullPropName(test)} has reached its max_tries. Skip.")
|
|
532
|
+
continue
|
|
473
533
|
validProps[propName] = test
|
|
474
534
|
return validProps
|
|
475
535
|
|
|
536
|
+
def _getStat(self):
|
|
537
|
+
# profile when reaching the profile period
|
|
538
|
+
if (self.options.profile_period and
|
|
539
|
+
self.stepsCount % self.options.profile_period == 0
|
|
540
|
+
):
|
|
541
|
+
URL = f"http://localhost:{self.scriptDriver.lport}/getStat"
|
|
542
|
+
r = requests.get(URL)
|
|
543
|
+
res = json.loads(r.content)
|
|
544
|
+
|
|
476
545
|
def collectAllProperties(self, test: TestSuite):
|
|
477
546
|
"""collect all the properties to prepare for PBT
|
|
478
547
|
"""
|
|
@@ -570,6 +639,8 @@ class KeaTestRunner(TextTestRunner):
|
|
|
570
639
|
|
|
571
640
|
return blocked_widgets
|
|
572
641
|
|
|
573
|
-
def
|
|
574
|
-
|
|
575
|
-
|
|
642
|
+
def __del__(self):
|
|
643
|
+
"""tearDown method. Cleanup the env.
|
|
644
|
+
"""
|
|
645
|
+
if self.options.Driver:
|
|
646
|
+
self.options.Driver.tearDown()
|
|
@@ -76,6 +76,22 @@ def _set_runner_parser(subparsers: "argparse._SubParsersAction[argparse.Argument
|
|
|
76
76
|
help="The name of driver in script.",
|
|
77
77
|
)
|
|
78
78
|
|
|
79
|
+
parser.add_argument(
|
|
80
|
+
"--log-stamp",
|
|
81
|
+
dest="log_stamp",
|
|
82
|
+
type=str,
|
|
83
|
+
required=False,
|
|
84
|
+
help="the stamp for log file and result file, default: current time stamp",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
parser.add_argument(
|
|
88
|
+
"--profile-period",
|
|
89
|
+
dest="profile_period",
|
|
90
|
+
type=int,
|
|
91
|
+
required=False,
|
|
92
|
+
help="Steps to profile the testing statistics.",
|
|
93
|
+
)
|
|
94
|
+
|
|
79
95
|
parser.add_argument(
|
|
80
96
|
"extra",
|
|
81
97
|
nargs=argparse.REMAINDER,
|
|
@@ -112,6 +128,7 @@ def parse_args(argv: List):
|
|
|
112
128
|
args = parser.parse_args(argv)
|
|
113
129
|
return args
|
|
114
130
|
|
|
131
|
+
|
|
115
132
|
def _sanitize_args(args):
|
|
116
133
|
if args.agent == "u2" and not args.driver_name:
|
|
117
134
|
if args.extra == []:
|
|
@@ -119,6 +136,7 @@ def _sanitize_args(args):
|
|
|
119
136
|
else:
|
|
120
137
|
raise ValueError("--driver-name should be specified when customizing script in --agent u2")
|
|
121
138
|
|
|
139
|
+
|
|
122
140
|
def run(args=None):
|
|
123
141
|
if args is None:
|
|
124
142
|
args = parse_args(sys.argv[1:])
|
|
@@ -136,9 +154,11 @@ def run(args=None):
|
|
|
136
154
|
Driver=U2Driver,
|
|
137
155
|
packageNames=args.package_names,
|
|
138
156
|
serial=args.serial,
|
|
139
|
-
running_mins=args.running_minutes
|
|
140
|
-
maxStep=args.max_step
|
|
141
|
-
throttle=args.throttle_ms
|
|
157
|
+
running_mins=args.running_minutes,
|
|
158
|
+
maxStep=args.max_step,
|
|
159
|
+
throttle=args.throttle_ms,
|
|
160
|
+
log_stamp=args.log_stamp,
|
|
161
|
+
profile_period=args.profile_period,
|
|
142
162
|
)
|
|
143
163
|
|
|
144
164
|
KeaTestRunner.setOptions(options)
|
|
@@ -8,7 +8,7 @@ from typing import Dict, List, Union
|
|
|
8
8
|
from lxml import etree
|
|
9
9
|
from .absDriver import AbstractScriptDriver, AbstractStaticChecker, AbstractDriver
|
|
10
10
|
from .adbUtils import list_forwards, remove_forward, create_forward
|
|
11
|
-
from .utils import TimeStamp
|
|
11
|
+
from .utils import TimeStamp, getLogger
|
|
12
12
|
|
|
13
13
|
TIME_STAMP = TimeStamp().getTimeStamp()
|
|
14
14
|
|
|
@@ -16,6 +16,8 @@ import logging
|
|
|
16
16
|
logging.getLogger("urllib3").setLevel(logging.INFO)
|
|
17
17
|
logging.getLogger("uiautomator2").setLevel(logging.INFO)
|
|
18
18
|
|
|
19
|
+
logger = getLogger(__name__)
|
|
20
|
+
|
|
19
21
|
"""
|
|
20
22
|
The definition of U2ScriptDriver
|
|
21
23
|
"""
|
|
@@ -57,16 +59,13 @@ class U2ScriptDriver(AbstractScriptDriver):
|
|
|
57
59
|
setattr(self.d._dev, "msg", "meta")
|
|
58
60
|
print(f"[U2] local port: {lport}", flush=True)
|
|
59
61
|
return lport
|
|
60
|
-
|
|
62
|
+
|
|
61
63
|
self._remove_remote_port(8090)
|
|
62
64
|
self.d.lport = get_u2_forward_port()
|
|
63
65
|
self._remove_remote_port(9008)
|
|
64
66
|
|
|
65
67
|
return self.d
|
|
66
68
|
|
|
67
|
-
def tearDown(self):
|
|
68
|
-
self.d.stop_uiautomator()
|
|
69
|
-
|
|
70
69
|
def _remove_remote_port(self, port:int):
|
|
71
70
|
"""remove the forward port
|
|
72
71
|
"""
|
|
@@ -76,6 +75,11 @@ class U2ScriptDriver(AbstractScriptDriver):
|
|
|
76
75
|
forward_local = forward["local"]
|
|
77
76
|
remove_forward(local_spec=forward_local, device=self.deviceSerial)
|
|
78
77
|
|
|
78
|
+
def tearDown(self):
|
|
79
|
+
logger.debug("U2Driver tearDown: stop_uiautomator")
|
|
80
|
+
self.d.stop_uiautomator()
|
|
81
|
+
logger.debug("U2Driver tearDown: remove forward")
|
|
82
|
+
self._remove_remote_port(8090)
|
|
79
83
|
|
|
80
84
|
"""
|
|
81
85
|
The definition of U2StaticChecker
|
|
@@ -231,6 +235,7 @@ class U2StaticDevice(u2.Device):
|
|
|
231
235
|
|
|
232
236
|
def __getattr__(self, attr):
|
|
233
237
|
"""Proxy other methods to script_driver"""
|
|
238
|
+
logger.debug(f"{attr} not exists in static checker, proxy to script_driver.")
|
|
234
239
|
return getattr(self._script_driver, attr)
|
|
235
240
|
|
|
236
241
|
class _XPathEntry(u2.xpath.XPathEntry):
|
|
@@ -293,6 +298,10 @@ class U2Driver(AbstractDriver):
|
|
|
293
298
|
self.staticChecker = U2StaticChecker()
|
|
294
299
|
return self.staticChecker.getInstance(hierarchy)
|
|
295
300
|
|
|
301
|
+
@classmethod
|
|
302
|
+
def tearDown(self):
|
|
303
|
+
self.scriptDriver.tearDown()
|
|
304
|
+
|
|
296
305
|
|
|
297
306
|
"""
|
|
298
307
|
Other Utils
|
|
@@ -311,6 +320,7 @@ def forward_port(self, remote: Union[int, str]) -> int:
|
|
|
311
320
|
return int(f.local[len("tcp:") :])
|
|
312
321
|
local_port = get_free_port()
|
|
313
322
|
self.forward("tcp:" + str(local_port), remote)
|
|
323
|
+
logger.debug(f"forwading port: tcp:{local_port} -> {remote}")
|
|
314
324
|
return local_port
|
|
315
325
|
|
|
316
326
|
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so
RENAMED
|
File without changes
|
|
File without changes
|
{kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_libs/x86/libfastbot_native.so
RENAMED
|
File without changes
|
{kea2_python-0.0.1b0 → kea2_python-0.0.1b2}/kea2/assets/fastbot_libs/x86_64/libfastbot_native.so
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|