Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

kuto

Package Overview
Dependencies
Maintainers
1
Versions
69
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

kuto - npm Package Compare versions

Comparing version
0.0.64
to
0.0.65
+1
-2
demo/tests/test_adr.py

@@ -32,4 +32,3 @@ import kuto

kuto.main(
platform='android',
device_id="UJK0220521066836",
devices=["85WKMBHQFEK76T8D"],
pkg_name='com.qizhidao.clientapp',

@@ -36,0 +35,0 @@ )

@@ -45,5 +45,3 @@ import kuto

"""仅执行本模块"""
kuto.main(
platform="api",
host='https://app-test.qizhidao.com'
)
kuto.main(host='https://app-test.qizhidao.com')

@@ -29,4 +29,3 @@ """

kuto.main(
platform='android',
device_id='UJK0220521066836',
devices=['UJK0220521066836'],
pkg_name='com.tencent.mm'

@@ -33,0 +32,0 @@ )

@@ -16,2 +16,3 @@ import kuto

def test_go_setting(self):
self.index_page.adBtn.click_exists(timeout=5)
self.index_page.myTab.click()

@@ -24,5 +25,6 @@ self.my_page.settingBtn.click()

"""仅执行本模块"""
from kuto.ios.common import get_connected
kuto.main(
platform="ios",
device_id="00008101-000E646A3C29003A",
devices=get_connected(),
pkg_name='com.qizhidao.company'

@@ -29,0 +31,0 @@ )

@@ -27,5 +27,2 @@ """

"""仅执行本模块"""
kuto.main(
platform='mac',
pkg_name='Calculator',
)
kuto.main(pkg_name='Calculator')

@@ -28,4 +28,3 @@ """

kuto.main(
platform='ios',
device_id='00008101-000E646A3C29003A',
devices=['00008101-000E646A3C29003A'],
pkg_name='com.tencent.xin'

@@ -32,0 +31,0 @@ )

@@ -26,7 +26,4 @@ """

"""仅执行本模块"""
kuto.main(
platform="web",
brow="chrome",
host="https://www-test.qizhidao.com"
)
kuto.main(host="https://www-test.qizhidao.com")

@@ -27,5 +27,3 @@ """

"""仅执行本模块"""
kuto.main(
platform='win',
pkg_name='calc.exe',
)
kuto.main(pkg_name='calc.exe')
Metadata-Version: 2.1
Name: kuto
Version: 0.0.64
Version: 0.0.65
Summary: 全平台自动化测试框架

@@ -5,0 +5,0 @@ Home-page: https://gitee.com/bluepang2021/kuto

@@ -13,2 +13,3 @@ requests-toolbelt==0.10.1

psutil==5.9.5
PyYAML~=6.0

@@ -39,3 +40,2 @@ [android]

XlsxWriter==3.0.2
PyYAML~=6.0

@@ -42,0 +42,0 @@ [web]

@@ -66,3 +66,2 @@ README.md

kuto/running/conf.yml
kuto/running/free_devices.yml
kuto/running/runner.py

@@ -69,0 +68,0 @@ kuto/testdata/__init__.py

@@ -13,3 +13,3 @@ from allure import *

__version__ = "0.0.64"
__version__ = "0.0.65"
__description__ = "全平台自动化测试框架"

@@ -9,3 +9,3 @@ import time

from kuto.utils.config import config, free_config
from kuto.utils.config import config
from kuto.utils.log import logger

@@ -66,6 +66,6 @@ from kuto.utils.exceptions import KError

with FileLock("session.lock"):
device_id = free_config.get_random_device()
device_id = config.get_random_device()
if device_id:
logger.info(f"获取空闲设备成功: {device_id}")
logger.info(f"剩余空闲设备列表: {free_config.get_all_device()}")
logger.info(f"剩余空闲设备列表: {config.get_all_device()}")
break

@@ -77,3 +77,3 @@ logger.info("未找到空闲设备,休息3秒")

logger.info(f"获取空闲设备失败!!!")
logger.info(f"剩余空闲设备列表: {free_config.get_all_device()}")
logger.info(f"剩余空闲设备列表: {config.get_all_device()}")
raise KError("获取空闲设备失败!!!")

@@ -97,6 +97,6 @@

with FileLock("session.lock"):
devices = free_config.get('devices')
devices = config.get_app('devices')
if device_id not in devices:
free_config.add_devices([self.driver.device_id])
logger.info(f"剩余空闲设备列表: {free_config.get_all_device()}")
config.add_devices([self.driver.device_id])
logger.info(f"剩余空闲设备列表: {config.get_all_device()}")

@@ -103,0 +103,0 @@ take_time = time.time() - self.start_time

@@ -11,3 +11,3 @@ """

def get_connected_adr_devices():
def get_connected():
"""获取当前连接的手机列表"""

@@ -14,0 +14,0 @@ cmd = 'adb devices'

@@ -12,3 +12,2 @@ import os

from kuto.utils.exceptions import KError
from kuto.android.common import get_connected_adr_devices

@@ -25,4 +24,3 @@

if not self.device_id:
# 未传入设备id时,获取已连接设备
self.device_id = get_connected_adr_devices()[0]
raise KError("设备id不能为空")

@@ -29,0 +27,0 @@ self.d = u2.connect(self.device_id)

@@ -9,3 +9,4 @@ import typing

from kuto.utils.log import logger
from kuto.utils.common import calculate_time, draw_red_by_coordinate
from kuto.utils.common import calculate_time, \
draw_red_by_coordinate

@@ -12,0 +13,0 @@

@@ -41,3 +41,3 @@ # @Time : 2022/2/22 9:35

# 从配置文件中读取域名
host = config.get_api("base_url")
host = config.get_common("base_url")
# 如果接口路径不以http开头,把域名写到key为url的位置参数中或者第一个参数中

@@ -62,12 +62,8 @@ if "url" in kwargs:

# 请求头处理,写入登录态
# 从配置文件获取登录用户和游客的请求头
if kwargs.get("login", True):
login_header: dict = config.get_api("login")
else:
login_header: dict = config.get_api("visit")
# 把用例脚本中设置的请求头加进来
default_headers = config.get_common("headers")
if default_headers:
kwargs["headers"] = default_headers
header_user_set = kwargs.pop("headers", {})
login_header.update(header_user_set)
# 把组装好的请求头装回到kwargs当中
kwargs["headers"] = login_header
if header_user_set:
kwargs["headers"] = header_user_set

@@ -140,11 +136,11 @@ # 更新超时时间

@request
def get(self, url, params=None, verify=False, login=True, **kwargs):
def get(self, url, params=None, verify=False, **kwargs):
return requests.get(url, params=params, verify=verify, **kwargs)
@request
def post(self, url, data=None, json=None, verify=False, login=True, **kwargs):
def post(self, url, data=None, json=None, verify=False, **kwargs):
return requests.post(url, data=data, json=json, verify=verify, **kwargs)
@request
def put(self, url, data=None, json=None, verify=False, login=True, **kwargs):
def put(self, url, data=None, json=None, verify=False, **kwargs):
if json is not None:

@@ -155,3 +151,3 @@ data = json_util.dumps(json)

@request
def delete(self, url, verify=False, login=True, **kwargs):
def delete(self, url, verify=False, **kwargs):
return requests.delete(url, verify=verify, **kwargs)

@@ -158,0 +154,0 @@

@@ -8,3 +8,3 @@ import time

from kuto.ios.driver import Driver
from kuto.utils.config import config, free_config
from kuto.utils.config import config
from kuto.utils.log import logger

@@ -65,6 +65,6 @@ from kuto.utils.exceptions import KError

with FileLock("session.lock"):
device_id = free_config.get_random_device()
device_id = config.get_random_device()
if device_id:
logger.info(f"获取空闲设备成功: {device_id}")
logger.info(f"剩余空闲设备列表: {free_config.get_all_device()}")
logger.info(f"剩余空闲设备列表: {config.get_all_device()}")
break

@@ -76,3 +76,3 @@ logger.info("未找到空闲设备,休息3秒")

logger.info(f"获取空闲设备失败!!!")
logger.info(f"剩余空闲设备列表: {free_config.get_all_device()}")
logger.info(f"剩余空闲设备列表: {config.get_all_device()}")
raise KError("获取空闲设备失败!!!")

@@ -96,6 +96,6 @@

with FileLock("session.lock"):
devices = free_config.get('devices')
devices = config.get_app('devices')
if device_id not in devices:
free_config.add_devices([self.driver.device_id])
logger.info(f"剩余空闲设备列表: {free_config.get_all_device()}")
config.add_devices([self.driver.device_id])
logger.info(f"剩余空闲设备列表: {config.get_all_device()}")

@@ -102,0 +102,0 @@ take_time = time.time() - self.start_time

@@ -8,3 +8,3 @@ import os

def get_connected_ios_devices():
def get_connected():
"""获取当前连接的设备列表"""

@@ -11,0 +11,0 @@ cmd = 'tidevice list'

@@ -9,3 +9,3 @@ import shutil

from kuto.utils.common import screenshot_util
from kuto.ios.common import TideviceUtil, get_connected_ios_devices
from kuto.ios.common import TideviceUtil

@@ -33,17 +33,15 @@

logger.info("初始化ios驱动")
if not pkg_name:
self.pkg_name = pkg_name
if not self.pkg_name:
raise KError('应用包名不能为空')
self.pkg_name = pkg_name
if device_id is None:
self.device_id = get_connected_ios_devices()[0]
self.device_id = device_id
if not self.device_id:
raise KError("设备id不能为空")
if 'http' in self.device_id:
self.wda_url = self.device_id
else:
self.port = self.device_id.split("-")[0][-4:]
self.wda_url = f"http://localhost:{self.port}"
else:
self.device_id = device_id
if 'http' in self.device_id:
self.wda_url = self.device_id
else:
self.port = self.device_id.split("-")[0][-4:]
self.wda_url = f"http://localhost:{self.port}"

@@ -50,0 +48,0 @@ self.d = wda.Client(self.wda_url)

@@ -1,14 +0,10 @@

api:
base_url: null
login: {}
visit: {}
app:
auto_start: false
device_id: null
devices: []
pkg_name: null
common:
base_url: null
headers: {}
web:
base_url: null
browser_name: chrome
cookies: null
browser_name: null
headless: false
state: null
import inspect
import json
import os
import pytest
import psutil
from kuto.utils.config import config, free_config
from kuto.utils.config import config
from kuto.utils.log import logger
from kuto.android.common import get_connected_adr_devices
from kuto.ios.common import get_connected_ios_devices

@@ -18,82 +14,46 @@

def __init__(self,
platform: str = None,
device_id=None,
case_path: str = None,
host: str = None,
headers: dict = None,
rerun: int = 0,
xdist: bool = False,
devices: list = None,
pkg_name: str = None,
start: bool = True,
brow: str = None,
headless: bool = False,
path: str = None,
rerun: int = 0,
xdist: bool = False,
host: str = None,
headers: dict = None,
state: dict = None,
cookies: list = None
brow_name: str = None,
headless: bool = False
):
"""
@param platform: 测试平台,android、ios、web、api、mac、win
@param device_id: 设备id,针对安卓和ios,可以是str和list,
@param devices: 设备id,针对安卓和ios,
对安卓和ios来说也可以是远程服务
@param pkg_name: 应用包名,针对安卓和ios
@param pkg_name: 应用包名,针对安卓、ios、mac、win
@param start: 是否默认启动应用,针对安卓和ios
@param brow: 浏览器类型,chrome、firefox、webkit
@param path: 用例目录,None默认代表当前文件
@param brow_name: 浏览器类型,chrome、firefox、webkit
@param case_path: 用例目录,None默认代表当前文件
@param rerun: 失败重试次数
@param xdist: 是否使用多进程执行
@param host: 域名,针对接口和web
@param headers: {
"login": {},
"visit": {}
}
@param state: 通过playwright的storage_state方法获取
@param cookies:
@param headers: {"token": "xxx"}
@param headless: 是否使用无头模式
"""
# api参数保存
config.set_api("base_url", host)
if headers:
if 'login' not in headers.keys():
raise KeyError("without login key!!!")
login_ = headers.pop('login', {})
config.set_api('login', login_)
visit_ = headers.pop('visit', {})
config.set_api('visit', visit_)
# 公共参数保存
config.set_common("base_url", host)
config.set_common("headers", headers)
# app参数保存
# 增加一段逻辑支持多进程以及设备调度
# 把所有的设备id加入到空闲设备列表中(用文件保存)
free_devices = []
if device_id is None:
# 获取当前连接的手机列表
if platform == "android":
free_devices = get_connected_adr_devices()
elif platform == "ios":
free_devices = get_connected_ios_devices()
free_config.add_devices(free_devices)
else:
if isinstance(device_id, str):
free_devices = [device_id]
free_config.add_devices(free_devices)
if isinstance(device_id, list):
if xdist is True:
# 如果需要并发,才把所有设备放入空闲列表
free_devices = device_id
free_config.add_devices(free_devices)
else:
# 如果不需要并发,把第一个设备放入空闲列表
free_devices = device_id[0:1]
free_config.add_devices(free_devices)
config.set_app("devices", devices)
config.set_app("pkg_name", pkg_name)
config.set_app("auto_start", start)
# web参数保存
config.set_web("base_url", host)
config.set_web("browser_name", brow)
config.set_web("browser_name", brow_name)
config.set_web("headless", headless)
if state:
config.set_web("state", json.dumps(state))
if cookies:
config.set_web("cookies", json.dumps(cookies))
# 执行用例
# logger.info('执行用例')
if path is None:
cmd_list = [
'-sv',
'--reruns', str(rerun),
'--alluredir', 'report', '--clean-alluredir'
]
if case_path is None:
stack_t = inspect.stack()

@@ -109,23 +69,10 @@ ins = inspect.getframeinfo(stack_t[1][0])

this_file = file_path
path = os.path.join(file_dir, this_file)
cmd_list = [
'-sv',
'--reruns', str(rerun),
'--alluredir', 'report', '--clean-alluredir'
]
if path:
cmd_list.insert(0, path)
case_path = os.path.join(file_dir, this_file)
cmd_list.insert(0, case_path)
if xdist:
if platform in ["android", "ios"]:
if len(free_devices) > 1:
# 设备数大于1才开启多进程
n = len(free_devices)
cpu_count = psutil.cpu_count()
if n > cpu_count:
n = cpu_count
cmd_list.insert(1, '-n')
cmd_list.insert(2, str(n))
else:
cmd_list.insert(1, '-n')
cmd_list.insert(2, 'auto')
cmd_list.insert(1, '-n')
cmd_list.insert(2, 'auto')
logger.info(cmd_list)

@@ -135,10 +82,6 @@ pytest.main(cmd_list)

# api参数保存
config.set_api("base_url", None)
config.set_api('login', {})
config.set_api('visit', {})
config.set_common("base_url", None)
config.set_common('headers', {})
# app参数保存
# 增加一段逻辑支持多进程以及设备调度
# 清空空闲设备列表
free_config.clear_devices()
config.set_app("device_id", None)
config.set_app("devices", [])
config.set_app("pkg_name", None)

@@ -148,7 +91,4 @@ config.set_app("auto_start", False)

# web参数保存
config.set_web("base_url", None)
config.set_web("browser_name", "chrome")
config.set_web("browser_name", None)
config.set_web("headless", False)
config.set_web("state", None)
config.set_web("cookies", None)

@@ -155,0 +95,0 @@

@@ -19,2 +19,5 @@ import os

def get_common(self, key):
return self.get('common', key)
def get_api(self, key):

@@ -36,2 +39,5 @@ return self.get('api', key)

def set_common(self, key, value):
self.set('common', key, value)
def set_api(self, key, value):

@@ -46,3 +52,27 @@ self.set('api', key, value)

def add_devices(self, devices: list):
old_devices = self.get_app("devices")
new_devices = old_devices + devices
self.set_app("devices", new_devices)
def set_devices(self, devices: list):
self.set_app("devices", devices)
def get_all_device(self):
return self.get_app("devices")
def get_random_device(self):
devices: list = self.get_all_device()
if devices:
device = random.choice(devices)
devices.remove(device)
self.set_devices(devices)
return device
return []
def clear_devices(self):
new_devices = []
self.set_app("devices", new_devices)
class FreeConfig:

@@ -49,0 +79,0 @@ def __init__(self):

@@ -65,8 +65,8 @@ import json

headless = config.get_web("headless")
state = config.get_web("state")
if state:
state_json = json.loads(state)
self.driver = Driver(browserName=browserName, headless=headless, state=state_json)
else:
self.driver = Driver(browserName=browserName, headless=headless)
# state = config.get_web("state")
# if state:
# state_json = json.loads(state)
# self.driver = Driver(browserName=browserName, headless=headless, state=state_json)
# else:
self.driver = Driver(browserName=browserName, headless=headless)

@@ -89,7 +89,7 @@ self.start()

def open_url(self, url=None):
def open_url(self, url=None, cookies=None):
"""浏览器打开页面"""
# 拼接域名
if url is None:
base_url = config.get_web("base_url")
base_url = config.get_common("base_url")
if not base_url:

@@ -100,3 +100,3 @@ raise KError('base_url is null')

if "http" not in url:
base_url = config.get_web("base_url")
base_url = config.get_common("base_url")
if not base_url:

@@ -107,4 +107,4 @@ raise KError('base_url is null')

self.driver.open_url(url)
# 设置cookies
cookies = config.get_web("cookies")
if cookies:

@@ -130,3 +130,3 @@ self.driver.set_cookies(cookies)

if url is None:
base_url = config.get_web("base_url")
base_url = config.get_common("base_url")
if not base_url:

@@ -137,3 +137,3 @@ raise KError('base_url is null')

if "http" not in url:
base_url = config.get_web("base_url")
base_url = config.get_common("base_url")
if not base_url:

@@ -140,0 +140,0 @@ raise KError('base_url is null')

@@ -82,6 +82,4 @@ """

if __name__ == '__main__':
driver1 = PlayWrightDriver(browserName="chrome")
driver1.open_url("https://patents.qizhidao.com/search/simple-result?from=simple&searchBtntype=searchBtn&businessSource=PC%E6%9F%A5%E4%B8%93%E5%88%A9&statement=%E4%BC%81%E7%9F%A5%E9%81%93")
time.sleep(5)
print(driver1.page.url)
pass
Metadata-Version: 2.1
Name: kuto
Version: 0.0.64
Version: 0.0.65
Summary: 全平台自动化测试框架

@@ -5,0 +5,0 @@ Home-page: https://gitee.com/bluepang2021/kuto

@@ -41,6 +41,7 @@ # -*- coding: utf-8 -*-

'filelock==3.12.2',
'psutil==5.9.5'
'psutil==5.9.5',
'PyYAML~=6.0'
],
extras_require={
"reader": ['pandas==1.3.4', 'openpyxl==3.0.9', 'XlsxWriter==3.0.2', 'PyYAML~=6.0'],
"reader": ['pandas==1.3.4', 'openpyxl==3.0.9', 'XlsxWriter==3.0.2'],
"encrypt": ["pycryptodome==3.14.1"],

@@ -47,0 +48,0 @@ "android": ['uiautomator2==2.16.23', 'opencv-python==4.6.0.66'],