kyapp 0.0.2__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.
- kyapp-0.0.2/PKG-INFO +30 -0
- kyapp-0.0.2/demo/config.py +4 -0
- kyapp-0.0.2/demo/pages/__init__.py +4 -0
- kyapp-0.0.2/demo/pages/home_page.py +9 -0
- kyapp-0.0.2/demo/pages/login_page.py +68 -0
- kyapp-0.0.2/demo/run.py +17 -0
- kyapp-0.0.2/demo/tests/__init__.py +0 -0
- kyapp-0.0.2/demo/tests/test_go_me.py +23 -0
- kyapp-0.0.2/kyapp/__init__.py +13 -0
- kyapp-0.0.2/kyapp/case.py +100 -0
- kyapp-0.0.2/kyapp/cli.py +41 -0
- kyapp-0.0.2/kyapp/core/__init__.py +4 -0
- kyapp-0.0.2/kyapp/core/adr/__init__.py +13 -0
- kyapp-0.0.2/kyapp/core/adr/case.py +108 -0
- kyapp-0.0.2/kyapp/core/adr/driver.py +154 -0
- kyapp-0.0.2/kyapp/core/adr/element.py +291 -0
- kyapp-0.0.2/kyapp/core/adr/page.py +12 -0
- kyapp-0.0.2/kyapp/core/adr/remote_adb.py +73 -0
- kyapp-0.0.2/kyapp/core/adr/remote_driver.py +179 -0
- kyapp-0.0.2/kyapp/core/img/__init__.py +4 -0
- kyapp-0.0.2/kyapp/core/img/driver.py +43 -0
- kyapp-0.0.2/kyapp/core/img/element.py +66 -0
- kyapp-0.0.2/kyapp/core/ios/__init__.py +15 -0
- kyapp-0.0.2/kyapp/core/ios/case.py +117 -0
- kyapp-0.0.2/kyapp/core/ios/driver.py +193 -0
- kyapp-0.0.2/kyapp/core/ios/elem.py +221 -0
- kyapp-0.0.2/kyapp/core/ios/local_wda.py +113 -0
- kyapp-0.0.2/kyapp/core/ios/page.py +11 -0
- kyapp-0.0.2/kyapp/core/ios/remote_driver.py +220 -0
- kyapp-0.0.2/kyapp/core/ios/remote_wda.py +58 -0
- kyapp-0.0.2/kyapp/core/ocr/__init__.py +9 -0
- kyapp-0.0.2/kyapp/core/ocr/driver.py +63 -0
- kyapp-0.0.2/kyapp/core/ocr/element.py +62 -0
- kyapp-0.0.2/kyapp/element.py +118 -0
- kyapp-0.0.2/kyapp/page.py +12 -0
- kyapp-0.0.2/kyapp/running/__init__.py +0 -0
- kyapp-0.0.2/kyapp/running/conf.py +12 -0
- kyapp-0.0.2/kyapp/running/conf.yml +19 -0
- kyapp-0.0.2/kyapp/running/runner.py +49 -0
- kyapp-0.0.2/kyapp/utils/__init__.py +1 -0
- kyapp-0.0.2/kyapp/utils/aes_util.py +49 -0
- kyapp-0.0.2/kyapp/utils/allure_util.py +213 -0
- kyapp-0.0.2/kyapp/utils/base64_util.py +25 -0
- kyapp-0.0.2/kyapp/utils/common.py +53 -0
- kyapp-0.0.2/kyapp/utils/config.py +135 -0
- kyapp-0.0.2/kyapp/utils/cv_util.py +114 -0
- kyapp-0.0.2/kyapp/utils/dingtalk.py +56 -0
- kyapp-0.0.2/kyapp/utils/excel_util.py +103 -0
- kyapp-0.0.2/kyapp/utils/log.py +12 -0
- kyapp-0.0.2/kyapp/utils/mail.py +47 -0
- kyapp-0.0.2/kyapp/utils/mysql_util.py +76 -0
- kyapp-0.0.2/kyapp/utils/nacos_util.py +54 -0
- kyapp-0.0.2/kyapp/utils/pytest_util.py +89 -0
- kyapp-0.0.2/kyapp/utils/swagger_util.py +197 -0
- kyapp-0.0.2/kyapp.egg-info/PKG-INFO +30 -0
- kyapp-0.0.2/kyapp.egg-info/SOURCES.txt +60 -0
- kyapp-0.0.2/kyapp.egg-info/dependency_links.txt +1 -0
- kyapp-0.0.2/kyapp.egg-info/entry_points.txt +2 -0
- kyapp-0.0.2/kyapp.egg-info/requires.txt +12 -0
- kyapp-0.0.2/kyapp.egg-info/top_level.txt +1 -0
- kyapp-0.0.2/setup.cfg +4 -0
- kyapp-0.0.2/setup.py +48 -0
kyapp-0.0.2/PKG-INFO
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kyapp
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: 安卓/IOS自动化测试框架
|
|
5
|
+
Home-page: https://gitee.com/bluepang2021/kyapp_project
|
|
6
|
+
Author: 杨康
|
|
7
|
+
Author-email: 772840356@qq.com
|
|
8
|
+
Platform: Android/IOS
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Requires-Dist: click==8.1.7
|
|
12
|
+
Requires-Dist: loguru==0.7.0
|
|
13
|
+
Requires-Dist: PyYAML==6.0.1
|
|
14
|
+
Requires-Dist: allure-pytest==2.9.45
|
|
15
|
+
Requires-Dist: pytest==6.2.5
|
|
16
|
+
Requires-Dist: pytest-xdist==2.5.0
|
|
17
|
+
Requires-Dist: pytest-rerunfailures==10.2
|
|
18
|
+
Requires-Dist: pytest-repeat==0.9.3
|
|
19
|
+
Requires-Dist: uiviewer==1.1.3
|
|
20
|
+
Requires-Dist: uiautomator2==3.2.4
|
|
21
|
+
Requires-Dist: tidevice==0.12.10
|
|
22
|
+
Requires-Dist: facebook-wda==1.5.0
|
|
23
|
+
Dynamic: author
|
|
24
|
+
Dynamic: author-email
|
|
25
|
+
Dynamic: classifier
|
|
26
|
+
Dynamic: home-page
|
|
27
|
+
Dynamic: platform
|
|
28
|
+
Dynamic: requires-dist
|
|
29
|
+
Dynamic: requires-python
|
|
30
|
+
Dynamic: summary
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@Author: kang.yang
|
|
3
|
+
@Date: 2024/9/14 09:44
|
|
4
|
+
"""
|
|
5
|
+
from config import Config
|
|
6
|
+
from kyapp import Page, Elem, logger
|
|
7
|
+
from pages.home_page import HomePage
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class LoginPage(Page):
|
|
11
|
+
reselect_ok = Elem(
|
|
12
|
+
title='地区偏移提示',
|
|
13
|
+
adr=('resourceId', 'com.lute.momcozy:id/btnNegative'),
|
|
14
|
+
ios=('label', 'OK')
|
|
15
|
+
)
|
|
16
|
+
welcome_text = Elem(
|
|
17
|
+
title='欢迎语',
|
|
18
|
+
adr=('text', 'Welcome to Momcozy'),
|
|
19
|
+
ios=('text', 'Welcome to Momcozy')
|
|
20
|
+
)
|
|
21
|
+
account_input = Elem(
|
|
22
|
+
title='账号输入框',
|
|
23
|
+
adr=('resourceId', 'com.lute.momcozy:id/etAccount'),
|
|
24
|
+
ios=('className', 'TextField'),
|
|
25
|
+
)
|
|
26
|
+
pwd_input = Elem(
|
|
27
|
+
title='密码输入框',
|
|
28
|
+
adr=('resourceId', 'com.lute.momcozy:id/etPassword'),
|
|
29
|
+
ios=('className', 'SecureTextField')
|
|
30
|
+
)
|
|
31
|
+
login_btn = Elem(
|
|
32
|
+
title='登录按钮',
|
|
33
|
+
adr=('resourceId', 'com.lute.momcozy:id/btnLogin'),
|
|
34
|
+
ios=('label', 'Log In'),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class LoginApi:
|
|
39
|
+
|
|
40
|
+
def __init__(self, driver):
|
|
41
|
+
self.driver = driver
|
|
42
|
+
self.login_page = LoginPage(self.driver)
|
|
43
|
+
self.home_page = HomePage(self.driver)
|
|
44
|
+
|
|
45
|
+
def login_status_check(self, timeout=5):
|
|
46
|
+
if self.home_page.me_tab.exists(timeout=timeout):
|
|
47
|
+
return True
|
|
48
|
+
return False
|
|
49
|
+
|
|
50
|
+
def country_change_dialog_check(self):
|
|
51
|
+
if self.login_page.reselect_ok.exists():
|
|
52
|
+
self.login_page.reselect_ok.click()
|
|
53
|
+
|
|
54
|
+
def pwd_login(self):
|
|
55
|
+
self.login_page.account_input.clear()
|
|
56
|
+
self.login_page.account_input.input(Config.EMAIL)
|
|
57
|
+
self.login_page.pwd_input.input(Config.PASSWORD)
|
|
58
|
+
self.login_page.welcome_text.click()
|
|
59
|
+
self.country_change_dialog_check()
|
|
60
|
+
self.login_page.login_btn.click()
|
|
61
|
+
|
|
62
|
+
def login(self):
|
|
63
|
+
if self.login_status_check():
|
|
64
|
+
logger.info('已登录')
|
|
65
|
+
else:
|
|
66
|
+
logger.info('未登录,进行登录')
|
|
67
|
+
self.pwd_login()
|
|
68
|
+
assert self.login_status_check(timeout=30)
|
kyapp-0.0.2/demo/run.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import kyapp
|
|
2
|
+
from pages.login_page import LoginApi
|
|
3
|
+
from pages.home_page import HomePage
|
|
4
|
+
|
|
5
|
+
class TestAdrDemo(kyapp.TestCase):
|
|
6
|
+
def start(self):
|
|
7
|
+
self.start_app(force=True)
|
|
8
|
+
LoginApi(self.dr).login()
|
|
9
|
+
self.home_page = HomePage(self.dr)
|
|
10
|
+
|
|
11
|
+
def test_go_me(self):
|
|
12
|
+
self.sleep(10)
|
|
13
|
+
self.home_page.me_tab.click()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from .running.runner import main
|
|
2
|
+
from .running.conf import App
|
|
3
|
+
from .utils.config import FileConfig
|
|
4
|
+
from .utils.pytest_util import *
|
|
5
|
+
from .utils.allure_util import *
|
|
6
|
+
from .utils.log import logger
|
|
7
|
+
from .page import Page
|
|
8
|
+
from .element import Elem
|
|
9
|
+
from .case import TestCase
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__version__ = "0.0.2"
|
|
13
|
+
__description__ = "安卓/IOS自动化测试框架"
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@Author: kang.yang
|
|
3
|
+
@Date: 2023/10/26 09:48
|
|
4
|
+
"""
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
from .core.adr.driver import Driver as AdrDriver
|
|
8
|
+
from .core.ios.driver import Driver as IosDriver
|
|
9
|
+
|
|
10
|
+
from .running.conf import App
|
|
11
|
+
from .utils.log import logger
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestCase:
|
|
15
|
+
"""
|
|
16
|
+
测试用例基类,所有测试用例需要继承该类
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
dr = None
|
|
20
|
+
|
|
21
|
+
# ---------------------初始化-------------------------------
|
|
22
|
+
def start_class(self):
|
|
23
|
+
"""
|
|
24
|
+
Hook method for setup_class fixture
|
|
25
|
+
:return:
|
|
26
|
+
"""
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
def end_class(self):
|
|
30
|
+
"""
|
|
31
|
+
Hook method for teardown_class fixture
|
|
32
|
+
:return:
|
|
33
|
+
"""
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def setup_class(cls):
|
|
38
|
+
try:
|
|
39
|
+
cls().start_class()
|
|
40
|
+
except BaseException as e:
|
|
41
|
+
logger.error(f"start_class Exception: {e}")
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def teardown_class(cls):
|
|
45
|
+
try:
|
|
46
|
+
cls().end_class()
|
|
47
|
+
except BaseException as e:
|
|
48
|
+
logger.error(f"end_class Exception: {e}")
|
|
49
|
+
|
|
50
|
+
def start(self):
|
|
51
|
+
"""
|
|
52
|
+
Hook method for setup_method fixture
|
|
53
|
+
:return:
|
|
54
|
+
"""
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
def end(self):
|
|
58
|
+
"""
|
|
59
|
+
Hook method for teardown_method fixture
|
|
60
|
+
:return:
|
|
61
|
+
"""
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
def setup_method(self):
|
|
65
|
+
did = App.did
|
|
66
|
+
pkg = App.pkg
|
|
67
|
+
if App.platform == 'ios':
|
|
68
|
+
self.dr = IosDriver(udid=did, bundle_id=pkg)
|
|
69
|
+
else:
|
|
70
|
+
self.dr = AdrDriver(serial=did, package=pkg)
|
|
71
|
+
|
|
72
|
+
self.start()
|
|
73
|
+
|
|
74
|
+
def teardown_method(self):
|
|
75
|
+
self.end()
|
|
76
|
+
if App.platform == 'ios':
|
|
77
|
+
self.dr.close()
|
|
78
|
+
print('休眠5s,防止释放设备过慢的情况!')
|
|
79
|
+
self.sleep(5)
|
|
80
|
+
|
|
81
|
+
# 公共方法
|
|
82
|
+
@staticmethod
|
|
83
|
+
def sleep(n: float):
|
|
84
|
+
logger.info(f"暂停: {n}s")
|
|
85
|
+
time.sleep(n)
|
|
86
|
+
|
|
87
|
+
def shot(self, name: str, delay=0):
|
|
88
|
+
if delay:
|
|
89
|
+
self.sleep(delay)
|
|
90
|
+
self.dr.shot(name)
|
|
91
|
+
|
|
92
|
+
def start_app(self, force=True):
|
|
93
|
+
if force:
|
|
94
|
+
self.stop_app()
|
|
95
|
+
self.dr.start_app()
|
|
96
|
+
|
|
97
|
+
def stop_app(self):
|
|
98
|
+
self.dr.stop_app()
|
|
99
|
+
|
|
100
|
+
|
kyapp-0.0.2/kyapp/cli.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from . import __version__
|
|
3
|
+
|
|
4
|
+
@click.group()
|
|
5
|
+
@click.version_option(version=__version__, help="Show version.")
|
|
6
|
+
# 老是变,等最后定下来再搞,目前也没啥用
|
|
7
|
+
def main():
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# @main.command()
|
|
12
|
+
# @click.option('-p', '--platform', help="Specify the platform.")
|
|
13
|
+
# def create(platform):
|
|
14
|
+
# """
|
|
15
|
+
# 创建新项目,老是变,先注释掉
|
|
16
|
+
# @param platform: 平台,如api、android、ios、web
|
|
17
|
+
# @return:
|
|
18
|
+
# """
|
|
19
|
+
# create_scaffold(platform)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# @main.command()
|
|
23
|
+
# @click.option('-p', '--platform', help="Specify the platform.")
|
|
24
|
+
# @click.option('-u', '--url', help="Specify the url.")
|
|
25
|
+
# def inspector(platform, url):
|
|
26
|
+
# """
|
|
27
|
+
# 获取元素定位信息
|
|
28
|
+
# @param platform: 平台,android、ios、web
|
|
29
|
+
# @param url:针对web,需要录制的页面的url
|
|
30
|
+
# @return:
|
|
31
|
+
# """
|
|
32
|
+
# import os
|
|
33
|
+
# if platform in ['android', 'ios', 'web']:
|
|
34
|
+
# os.system('weditor')
|
|
35
|
+
# elif platform == 'web':
|
|
36
|
+
# if not url:
|
|
37
|
+
# raise KeyError('url不能为空')
|
|
38
|
+
# os.system(f'playwright codegen {url}')
|
|
39
|
+
# else:
|
|
40
|
+
# raise KeyError('只支持android、ios、web')
|
|
41
|
+
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@Author: kang.yang
|
|
3
|
+
@Date: 2023/10/26 09:48
|
|
4
|
+
"""
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
from .driver import Driver
|
|
8
|
+
from .remote_driver import RemoteDriver
|
|
9
|
+
|
|
10
|
+
from kyapp.running.conf import App
|
|
11
|
+
from kyapp.utils.log import logger
|
|
12
|
+
|
|
13
|
+
class TestCase:
|
|
14
|
+
"""
|
|
15
|
+
测试用例基类,所有测试用例需要继承该类
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
dr = None
|
|
19
|
+
|
|
20
|
+
# ---------------------初始化-------------------------------
|
|
21
|
+
def start_class(self):
|
|
22
|
+
"""
|
|
23
|
+
Hook method for setup_class fixture
|
|
24
|
+
:return:
|
|
25
|
+
"""
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
def end_class(self):
|
|
29
|
+
"""
|
|
30
|
+
Hook method for teardown_class fixture
|
|
31
|
+
:return:
|
|
32
|
+
"""
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def setup_class(cls):
|
|
37
|
+
try:
|
|
38
|
+
cls().start_class()
|
|
39
|
+
except BaseException as e:
|
|
40
|
+
logger.error(f"start_class Exception: {e}")
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def teardown_class(cls):
|
|
44
|
+
try:
|
|
45
|
+
cls().end_class()
|
|
46
|
+
except BaseException as e:
|
|
47
|
+
logger.error(f"end_class Exception: {e}")
|
|
48
|
+
|
|
49
|
+
def start(self):
|
|
50
|
+
"""
|
|
51
|
+
Hook method for setup_method fixture
|
|
52
|
+
:return:
|
|
53
|
+
"""
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
def end(self):
|
|
57
|
+
"""
|
|
58
|
+
Hook method for teardown_method fixture
|
|
59
|
+
:return:
|
|
60
|
+
"""
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
def setup_method(self):
|
|
64
|
+
|
|
65
|
+
# 驱动初始化
|
|
66
|
+
if App.sonic_host is not None:
|
|
67
|
+
self.dr = RemoteDriver(
|
|
68
|
+
serial=App.did,
|
|
69
|
+
package=App.pkg,
|
|
70
|
+
sonic_host=App.sonic_host,
|
|
71
|
+
sonic_user=App.sonic_user,
|
|
72
|
+
sonic_pwd=App.sonic_pwd
|
|
73
|
+
)
|
|
74
|
+
else:
|
|
75
|
+
self.dr = Driver(
|
|
76
|
+
serial=App.did,
|
|
77
|
+
package=App.pkg
|
|
78
|
+
)
|
|
79
|
+
# 解锁设备
|
|
80
|
+
self.dr.unlock()
|
|
81
|
+
|
|
82
|
+
self.start()
|
|
83
|
+
|
|
84
|
+
def teardown_method(self):
|
|
85
|
+
self.end()
|
|
86
|
+
if isinstance(self.dr, RemoteDriver):
|
|
87
|
+
self.dr.close()
|
|
88
|
+
|
|
89
|
+
# 公共方法
|
|
90
|
+
@staticmethod
|
|
91
|
+
def sleep(n: float):
|
|
92
|
+
logger.info(f"暂停: {n}s")
|
|
93
|
+
time.sleep(n)
|
|
94
|
+
|
|
95
|
+
def shot(self, name: str, delay=0):
|
|
96
|
+
if delay:
|
|
97
|
+
self.sleep(delay)
|
|
98
|
+
self.dr.shot(name)
|
|
99
|
+
|
|
100
|
+
def start_app(self, force=True):
|
|
101
|
+
if force:
|
|
102
|
+
self.stop_app()
|
|
103
|
+
self.dr.start_app()
|
|
104
|
+
|
|
105
|
+
def stop_app(self):
|
|
106
|
+
self.dr.stop_app()
|
|
107
|
+
|
|
108
|
+
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import allure
|
|
2
|
+
import uiautomator2 as u2
|
|
3
|
+
|
|
4
|
+
from kyapp.utils.log import logger
|
|
5
|
+
from kyapp.utils.common import general_file_path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Driver:
|
|
9
|
+
"""
|
|
10
|
+
u2库代码地址:https://github.com/openatx/uiautomator2
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self, serial: str, package: str = None):
|
|
14
|
+
"""
|
|
15
|
+
@param serial: 设备序列号,通过adb devices获取,或者通过关于手机-序列号获取
|
|
16
|
+
@param package: 应用包名,通过adb shell pm list packages获取
|
|
17
|
+
"""
|
|
18
|
+
logger.info(f"初始化本地设备连接: {serial}")
|
|
19
|
+
self.package = package
|
|
20
|
+
self.d = u2.connect(serial)
|
|
21
|
+
|
|
22
|
+
def uninstall_app(self, package: str = None):
|
|
23
|
+
"""
|
|
24
|
+
卸载应用
|
|
25
|
+
@param package: 应用包名
|
|
26
|
+
@return:
|
|
27
|
+
"""
|
|
28
|
+
if self.package is None:
|
|
29
|
+
if package is None:
|
|
30
|
+
raise KeyError('package不能为空')
|
|
31
|
+
else:
|
|
32
|
+
self.package = package
|
|
33
|
+
logger.info(f"卸载应用: {self.package}")
|
|
34
|
+
self.d.app_uninstall(self.package)
|
|
35
|
+
|
|
36
|
+
def install_app(self, apk_url, package: str = None):
|
|
37
|
+
"""
|
|
38
|
+
安装应用
|
|
39
|
+
@param apk_url: apk链接
|
|
40
|
+
@param package: 应用包名
|
|
41
|
+
@return:
|
|
42
|
+
"""
|
|
43
|
+
if self.package is None:
|
|
44
|
+
if package is None:
|
|
45
|
+
raise KeyError('package不能为空')
|
|
46
|
+
else:
|
|
47
|
+
self.package = package
|
|
48
|
+
self.d.app_uninstall(self.package)
|
|
49
|
+
logger.info(f"安装应用: {apk_url}")
|
|
50
|
+
self.d.app_install(apk_url)
|
|
51
|
+
|
|
52
|
+
def start_app(self, package: str = None):
|
|
53
|
+
"""
|
|
54
|
+
启动应用
|
|
55
|
+
@param package: 应用包名
|
|
56
|
+
@return:
|
|
57
|
+
"""
|
|
58
|
+
if self.package is None:
|
|
59
|
+
if package is None:
|
|
60
|
+
raise KeyError('package不能为空')
|
|
61
|
+
else:
|
|
62
|
+
self.package = package
|
|
63
|
+
logger.info(f"启动应用: {self.package}")
|
|
64
|
+
self.d.app_start(package_name=self.package, use_monkey=True)
|
|
65
|
+
|
|
66
|
+
def stop_app(self, package: str = None):
|
|
67
|
+
"""
|
|
68
|
+
停止应用
|
|
69
|
+
@param package: 应用包名
|
|
70
|
+
@return:
|
|
71
|
+
"""
|
|
72
|
+
if self.package is None:
|
|
73
|
+
if package is None:
|
|
74
|
+
raise KeyError('package不能为空')
|
|
75
|
+
else:
|
|
76
|
+
self.package = package
|
|
77
|
+
logger.info(f"停止应用: {self.package}")
|
|
78
|
+
self.d.app_stop(self.package)
|
|
79
|
+
|
|
80
|
+
def shot(self, file_name: str = None):
|
|
81
|
+
"""
|
|
82
|
+
截图
|
|
83
|
+
@param file_name: 截图保存后的文件名
|
|
84
|
+
@return:
|
|
85
|
+
"""
|
|
86
|
+
file_path = general_file_path(file_name)
|
|
87
|
+
logger.info(f"截图保存至: {file_path}")
|
|
88
|
+
self.d.screenshot(file_path)
|
|
89
|
+
|
|
90
|
+
logger.info("截图上传allure报告")
|
|
91
|
+
allure.attach.file(
|
|
92
|
+
file_path,
|
|
93
|
+
attachment_type=allure.attachment_type.PNG,
|
|
94
|
+
name=f"{file_path}",
|
|
95
|
+
)
|
|
96
|
+
return file_path
|
|
97
|
+
|
|
98
|
+
def click(self, x, y):
|
|
99
|
+
"""
|
|
100
|
+
点击坐标
|
|
101
|
+
@param x: 横坐标
|
|
102
|
+
@param y: 纵坐标
|
|
103
|
+
@return:
|
|
104
|
+
"""
|
|
105
|
+
self.d.click(x, y)
|
|
106
|
+
|
|
107
|
+
def input(self, *args, **kwargs):
|
|
108
|
+
"""
|
|
109
|
+
输入
|
|
110
|
+
@param args:
|
|
111
|
+
@param kwargs:
|
|
112
|
+
@return:
|
|
113
|
+
"""
|
|
114
|
+
self.d.send_keys(*args, **kwargs)
|
|
115
|
+
|
|
116
|
+
def unlock(self):
|
|
117
|
+
"""
|
|
118
|
+
设备解锁
|
|
119
|
+
@return:
|
|
120
|
+
"""
|
|
121
|
+
self.d.unlock()
|
|
122
|
+
|
|
123
|
+
def shell(self, *args, **kwargs):
|
|
124
|
+
"""
|
|
125
|
+
执行adb shell
|
|
126
|
+
@param args:
|
|
127
|
+
@param kwargs:
|
|
128
|
+
@return:
|
|
129
|
+
"""
|
|
130
|
+
self.d.shell(*args, **kwargs)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|