Kea2-python 0.0.1b0__tar.gz → 0.0.1b1__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.

Files changed (39) hide show
  1. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/Kea2_python.egg-info/PKG-INFO +5 -1
  2. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/PKG-INFO +5 -1
  3. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/README.md +4 -0
  4. kea2_python-0.0.1b1/kea2/__init__.py +4 -0
  5. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/absDriver.py +4 -0
  6. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/adbUtils.py +5 -0
  7. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/quicktest.py +3 -3
  8. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/cli.py +1 -1
  9. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/keaUtils.py +54 -12
  10. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/kea_launcher.py +10 -1
  11. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/u2Driver.py +15 -5
  12. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/pyproject.toml +2 -2
  13. kea2_python-0.0.1b0/kea2/__init__.py +0 -4
  14. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/Kea2_python.egg-info/SOURCES.txt +0 -0
  15. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/Kea2_python.egg-info/dependency_links.txt +0 -0
  16. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/Kea2_python.egg-info/entry_points.txt +0 -0
  17. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/Kea2_python.egg-info/requires.txt +0 -0
  18. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/Kea2_python.egg-info/top_level.txt +0 -0
  19. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/LICENSE +0 -0
  20. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot-thirdpart.jar +0 -0
  21. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_configs/ADBKeyBoard.apk +0 -0
  22. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_configs/abl.strings +0 -0
  23. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_configs/awl.strings +0 -0
  24. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_configs/max.config +0 -0
  25. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_configs/max.fuzzing.strings +0 -0
  26. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_configs/max.schema.strings +0 -0
  27. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_configs/max.strings +0 -0
  28. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_configs/max.tree.pruning +0 -0
  29. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_configs/widget.block.py +0 -0
  30. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so +0 -0
  31. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so +0 -0
  32. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_libs/x86/libfastbot_native.so +0 -0
  33. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/fastbot_libs/x86_64/libfastbot_native.so +0 -0
  34. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/framework.jar +0 -0
  35. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/monkeyq.jar +0 -0
  36. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/assets/u2.jar +0 -0
  37. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/logWatcher.py +0 -0
  38. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/kea2/utils.py +0 -0
  39. {kea2_python-0.0.1b0 → kea2_python-0.0.1b1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Kea2-python
3
- Version: 0.0.1b0
3
+ Version: 0.0.1b1
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
  [![PyPI Downloads](https://static.pepy.tech/badge/kea2-python)](https://pepy.tech/projects/kea2-python)
17
17
  ![Python](https://img.shields.io/badge/python-3.8%2B-blue)
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Kea2-python
3
- Version: 0.0.1b0
3
+ Version: 0.0.1b1
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
  [![PyPI Downloads](https://static.pepy.tech/badge/kea2-python)](https://pepy.tech/projects/kea2-python)
17
17
  ![Python](https://img.shields.io/badge/python-3.8%2B-blue)
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:
@@ -4,6 +4,10 @@
4
4
  [![PyPI Downloads](https://static.pepy.tech/badge/kea2-python)](https://pepy.tech/projects/kea2-python)
5
5
  ![Python](https://img.shields.io/badge/python-3.8%2B-blue)
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:
@@ -0,0 +1,4 @@
1
+ from .keaUtils import KeaTestRunner, precondition, prob, max_tries, Options
2
+
3
+ import logging
4
+ logging.basicConfig(level=logging.DEBUG)
@@ -50,3 +50,7 @@ class AbstractDriver(abc.ABC):
50
50
  @abc.abstractmethod
51
51
  def getStaticChecker(self, hierarchy) -> AbstractStaticChecker:
52
52
  pass
53
+
54
+ @classmethod
55
+ @abc.abstractmethod
56
+ def tearDown(self): ...
@@ -1,5 +1,9 @@
1
1
  import subprocess
2
2
  from typing import List, Optional
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:
@@ -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 kea2.utils import getProjectRoot, getLogger
6
+ from .utils import getProjectRoot, getLogger
7
7
  from .kea_launcher import run
8
8
  import argparse
9
9
 
@@ -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
- TIME_STAMP = TimeStamp().getTimeStamp()
34
- LOGFILE = f"fastbot_{TIME_STAMP}.log"
35
- RESFILE = f"result_{TIME_STAMP}.json"
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
- The precondition specifies when the property could be executed.
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
- The prob specify the propbability of execution when a property is satisfied.
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,16 @@ 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
99
122
 
100
123
  def __post_init__(self):
101
124
  if self.serial and self.Driver:
102
125
  self.Driver.setDeviceSerial(self.serial)
126
+ if self.log_stamp:
127
+ global LOGFILE, RESFILE
128
+ LOGFILE = f"fastbot_{self.log_stamp}.log"
129
+ RESFILE = f"result_{self.log_stamp}.json"
103
130
 
104
131
 
105
132
  @dataclass
@@ -151,6 +178,9 @@ class JsonResult(TextTestResult):
151
178
  super().addError(test, err)
152
179
  self.res[getFullPropName(test)].error += 1
153
180
 
181
+ def getExcuted(self, test: TestCase):
182
+ return self.res[getFullPropName(test)].executed
183
+
154
184
 
155
185
  def activateFastbot(options: Options, port=None) -> threading.Thread:
156
186
  """
@@ -274,6 +304,8 @@ class KeaTestRunner(TextTestRunner):
274
304
  global LOGFILE, RESFILE
275
305
  LOGFILE = output_dir / Path(LOGFILE)
276
306
  RESFILE = output_dir / Path(RESFILE)
307
+ logger.debug(f"Log file: {LOGFILE}")
308
+ logger.debug(f"Result file: {RESFILE}")
277
309
 
278
310
  def run(self, test):
279
311
 
@@ -333,7 +365,7 @@ class KeaTestRunner(TextTestRunner):
333
365
  , flush=True)
334
366
 
335
367
  try:
336
- propsSatisfiedPrecond = self.getValidProperties()
368
+ propsSatisfiedPrecond = self.getValidProperties(result)
337
369
  except requests.ConnectionError:
338
370
  print(
339
371
  "[INFO] Exploration times up (--running-minutes)."
@@ -425,6 +457,8 @@ class KeaTestRunner(TextTestRunner):
425
457
  """
426
458
  block_widgets: List[str] = self._getBlockedWidgets()
427
459
  URL = f"http://localhost:{self.scriptDriver.lport}/stepMonkey"
460
+ logger.debug(f"Sending request: {URL}")
461
+ logger.debug(f"Blocking widgets: {block_widgets}")
428
462
  r = requests.post(
429
463
  url=URL,
430
464
  json={
@@ -440,12 +474,14 @@ class KeaTestRunner(TextTestRunner):
440
474
  """
441
475
  send a stop monkey request to the server and get the xml string.
442
476
  """
443
- r = requests.get(f"http://localhost:{self.scriptDriver.lport}/stopMonkey")
477
+ URL = f"http://localhost:{self.scriptDriver.lport}/stopMonkey"
478
+ logger.debug(f"Sending request: {URL}")
479
+ r = requests.get(URL)
444
480
 
445
481
  res = r.content.decode(encoding="utf-8")
446
482
  print(f"[Server INFO] {res}", flush=True)
447
483
 
448
- def getValidProperties(self) -> PropertyStore:
484
+ def getValidProperties(self, result: JsonResult) -> PropertyStore:
449
485
 
450
486
  xml_raw = self.stepMonkey()
451
487
  staticCheckerDriver = self.options.Driver.getStaticChecker(hierarchy=xml_raw)
@@ -470,6 +506,10 @@ class KeaTestRunner(TextTestRunner):
470
506
  break
471
507
  # if all the precond passed. make it the candidate prop.
472
508
  if valid:
509
+ logger.debug(f"precond satisfied: {getFullPropName(test)}")
510
+ if result.getExcuted(test) >= getattr(prop, MAX_TRIES_MARKER, float("inf")):
511
+ logger.debug(f"{getFullPropName(test)} has reached its max_tries. Skip.")
512
+ continue
473
513
  validProps[propName] = test
474
514
  return validProps
475
515
 
@@ -570,6 +610,8 @@ class KeaTestRunner(TextTestRunner):
570
610
 
571
611
  return blocked_widgets
572
612
 
573
- def tearDown(self):
574
- # TODO Add tearDown method (remove local port, etc.)
575
- pass
613
+ def __del__(self):
614
+ """tearDown method. Cleanup the env.
615
+ """
616
+ if self.options.Driver:
617
+ self.options.Driver.tearDown()
@@ -76,6 +76,14 @@ 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
+
79
87
  parser.add_argument(
80
88
  "extra",
81
89
  nargs=argparse.REMAINDER,
@@ -138,7 +146,8 @@ def run(args=None):
138
146
  serial=args.serial,
139
147
  running_mins=args.running_minutes if args.running_minutes else 10,
140
148
  maxStep=args.max_step if args.max_step else 500,
141
- throttle=args.throttle_ms if args.throttle_ms else 200
149
+ throttle=args.throttle_ms if args.throttle_ms else 200,
150
+ log_stamp=args.log_stamp
142
151
  )
143
152
 
144
153
  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
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "Kea2-python"
3
- version = "0.0.1b0"
3
+ version = "0.0.1b1"
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"
@@ -19,4 +19,4 @@ kea2 = "kea2.cli:main"
19
19
  include = ["kea2"]
20
20
 
21
21
  [tool.setuptools.package-data]
22
- kea2 = ["assets/**/*"]
22
+ kea2 = ["assets/**/*"]
@@ -1,4 +0,0 @@
1
- from .keaUtils import KeaTestRunner, precondition, prob, Options
2
-
3
- import logging
4
- logging.basicConfig(level=logging.DEBUG)
File without changes
File without changes