This commit is contained in:
2026-04-22 12:01:26 +08:00
commit d7fea98ecd
15 changed files with 5622 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
__pycache__
doc.xlsx
.env
.config.json
logs

24
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,24 @@
exclude: "^assets|^test/"
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.11
hooks:
- id: ruff-check
args: [--fix]
- id: ruff-format
- repo: https://github.com/asottile/pyupgrade
rev: v3.20.0
hooks:
- id: pyupgrade
args: [--py312-plus]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
hooks:
- id: check-added-large-files
- id: check-toml
- id: check-yaml
exclude: "^helm/"
args: [--unsafe]
- id: check-merge-conflict

2589
.well-known/schema.json Normal file

File diff suppressed because it is too large Load Diff

1
README Normal file
View File

@@ -0,0 +1 @@
Honor

0
__init__.py Normal file
View File

120
conftest.py Normal file
View File

@@ -0,0 +1,120 @@
from typing import Callable, Literal
from glrocky.framework.schemas import (
TestSessionRuntime,
Device as _Device,
TestCaseExecutionState,
TestCaseRuntime,
)
from glrocky.framework.const_stash_keys import CASE_RUNTIME_CONFIG_KEY
import pytest
from glrocky.framework.schemas import TestCaseMertic as MetricItem
from glrocky.framework.schemas import TestCaseMetrics as MetricPacked
from glrocky.core.logger import core_logger
@pytest.fixture(scope="function")
def device_info(
request: pytest.FixtureRequest,
) -> _Device:
runtime: TestSessionRuntime | None = getattr(request.config, "project", None)
if runtime is None:
raise RuntimeError("unreachable!!!!!")
ret = runtime.devices[0] if runtime.devices else None
if not ret:
raise RuntimeError("no device found")
return ret
@pytest.fixture(scope="function", autouse=True)
def metric(record_metric: Callable[[MetricPacked], None]):
"""usage:
def test_g(metric):
metric.span() # optional
metric.add()
metric.add()
metric.send_all() # optianl
"""
class M:
def __init__(self):
self.data: list[tuple[str, str, int, list[MetricItem]]] = []
self.span()
def add(
self,
name: str,
value: float | int | str,
label: str | None = None,
type: Literal["number", "image", "video", "text"] = "text",
) -> None:
metric = MetricItem(
name=name, value=value, label=label or name, unit=None, type=type
)
self.data[-1][-1].append(metric)
def span(
self,
material_type: str = "default",
material_id: str = "default",
material_iteration: int = 1,
):
# DO NOT ADD DUPLICATE ITEM!!
if len(self.data):
last_span = self.data[-1]
if all(
(
last_span[0] == material_type,
last_span[1] == material_id,
last_span[2] == material_iteration,
)
):
core_logger.debug(
f"SKIP DUPLICATE SPAN:{material_type=},{material_id=},{material_iteration=}"
)
return
self.data.append((material_type, material_id, material_iteration, []))
core_logger.info(
f"added new span for metric:{material_type=},{material_id=},{material_iteration=}"
)
def send_all(
self,
):
if len(self.data) < 1:
core_logger.debug("no materics to send")
return # no span at all,skip
data = self.data[::-1]
self.data.clear() # TODO: not safe,to be improved
core_logger.info(f"{len(data)} metrics for send.")
while True:
if len(data) == 0:
break
item = data.pop()
material_type, material_id, material_iteration, metrics = (
item[0],
item[1],
item[2],
item[3],
)
if len(metrics) == 0:
core_logger.info("skip empty metrics")
continue
for_send = MetricPacked(
type=material_type,
material=material_id,
iteration=material_iteration,
metrics=metrics,
)
core_logger.info(f"rebuild metric:{for_send=}")
core_logger.info("sending metrics to executor...")
record_metric(for_send)
core_logger.info("sent")
_m = M()
yield _m
try:
_m.send_all()
except Exception as e:
raise RuntimeError(f"Cloud not send metric to server,Detail: {e}")

0
core/__init__.py Normal file
View File

82
core/metric_manager.py Normal file
View File

@@ -0,0 +1,82 @@
from pathlib import Path
class MetricManager:
def __init__(self, metric):
self.metric = metric
def new_span(self, m_type: str = "default", m_id: str = "default", m_iter: int = 1):
self.metric.span(m_type, m_id, m_iter)
def _smart_name_label(self, name: str, label: str | None) -> tuple[str, str]:
"""retruns: (name,label)"""
if not name:
raise ValueError()
if not name.strip():
raise ValueError("Empty name")
if label:
return name, label
for sep in ("|", ":"):
if sep in name:
_n, _l = name.split(sep, maxsplit=1)
return (_n, _l)
return name, name
def add_text_metric(self, name: str, value: str, label: str | None = None):
_n, _l = self._smart_name_label(name, label)
self.metric.add(
name=_n,
label=_l,
value=value,
type="text",
)
def add_number_metric(self, name: str, value: float, label: str | None = None):
_n, _l = self._smart_name_label(name, label)
self.metric.add(
name=_n,
label=_l,
value=value,
type="number",
)
def add_image_metric(self, name: str, value: Path | str, label: str | None = None):
_n, _l = self._smart_name_label(name, label)
self.metric.add(
name=_n,
label=_l,
value=str(value),
type="image",
)
def add_video_metric(self, name: str, value: Path | str, label: str | None = None):
_n, _l = self._smart_name_label(name, label)
self.metric.add(
name=_n,
label=_l,
value=value,
type="video",
)
def send(self):
self.metric.send_all()
def from_dict(self, the_dict: dict):
if not the_dict:
raise ValueError("dict is null")
for k, v in the_dict.items():
if isinstance(v, (int, float)):
self.add_number_metric(name=k, value=v)
elif isinstance(v, str):
self.add_text_metric(name=k, value=v)
elif isinstance(v, Path):
if v.suffix.lower() in (".jpg", ".png", ".gif", ".bmp"):
self.add_image_metric(name=k, value=str(v.resolve()))
elif v.suffix.lower() in (".mp4", ".mkv"):
self.add_video_metric(name=k, value=str(v.resolve()))
else:
self.add_text_metric(name=k, value=str(v.resolve()))
else:
raise NotImplementedError(f"{type(v)} not supported")

Binary file not shown.

62
justfile Normal file
View File

@@ -0,0 +1,62 @@
set shell := ["powershell.exe","-NoLogo","-NoProfile", "-c"] # windows
set dotenv-load
set quiet :=true
@_:
just --list
[group("build")]
generate-schema:
rm {{quote(".well-known"/"*.json")}}
@fd -e json -H "schema"
uv run --reinstall-package glrocky-sdk \
python -m \
pytest --co --generate-schema --continue-on-collection-errors -q
mv {{ quote (".well-known" / "schema_autogenerated.json")}} {{ quote (".well-known" / "schema.json")}}
@fd -e json -H "schema"
[group("qa")]
lint:
uvx ruff check --fix --unsafe-fixes .
uvx ruff format
[group("run")]
[doc("run a specific test,eg: j run 0101_02")]
run TEST:
uv run python -m pytest -sqv -k {{TEST}}
[group("clean")]
clean-pycache:
@rm.exe -rf .pytest_cache .mypy_cache .ruff_cache .coverage
rm.exe -rf log out
@fd -td -I "__pycache__" -x rm -rf '{}'
@echo "✅ Done"
[group("clean")]
clean-cache:
@rm.exe -rf .pytest_cache .mypy_cache .ruff_cache .coverage
[group("clean")]
clean-out-and-log:
rm.exe -rf logs/ out/
[group("clean")]
clean-all:
just clean-cache
just clean-out-and-log
just clean-pycache
[group("dev")]
[doc("invoke ipython with u2")]
debug-u2:
uvx --with uiautomator2 --with .packages/glrocky_sdk-0.1.2-py3-none-any.whl --directory . ipython
[group("dev")]
[doc("show android ui")]
debug-ui:
uvx uiviewer
[group("dev")]
[doc("start test executor server,from glrocky framework")]
debug-srv:
uv run api-test-server

76
pyproject.toml Normal file
View File

@@ -0,0 +1,76 @@
[project]
name = "honor-Phone-Test-Project-honor"
version = "0.3.1"
description = "honor_MEP-AN00手机用例集"
readme = "README.md"
authors = [{ name = "liumin", email = "liumin@glrocy.com" }]
requires-python = "==3.12.6"
dependencies = ["glrocky-sdk", "uvicorn>=0.34.2"]
[tool.pytest.ini_options]
minversion = "8.3.5"
#addopts = "--no-summary --no-header -rfEX --strict-markers --capture=tee-sys "
addopts = "--capture=tee-sys "
testpaths = ["scenarios"]
python_files = "tc_*.py"
markers = []
[tool.pyright]
venv = ".venv"
venvPath = "."
reportMissingTypeStubs = false
reportUnknownMemberType = false
[tool.uv.sources]
#glrocky-sdk = { path = "../../packages/glrocky-sdk" }
glrocky-sdk = { path = "./glrocky_sdk-0.4.3-py3-none-any.whl" }
[[tool.uv.index]]
url = "https://mirrors.aliyun.com/pypi/simple/"
default = true
[tool.glrocky]
remote_url = "https://gitea.glrocky.cn/aitest-scripts/honor.git"
branch = "MEP-AN00"
uuid = "157f58111-aaa9-4636-b476-739MEPAN0001"
[tool.glrocky.tags]
osName="android" #adb -s ASQH015919000148 shell "getprop ro.build.version.release"
osVersion="15"
brand="HONOR" #adb -s ASQH015919000148 shell "getprop ro.product.brand"
model="MEP-AN00" #adb -s ASQH015919000148 shell "getprop ro.product.model"
manufacturer="HONOR" #adb -s ASQH015919000148 shell "getprop ro.product.manufacturer"
[tool.glrocky.commands]
generateSchema = "uv run --reinstall-package glrocky-sdk pytest --co --generate-schema --continue-on-collection-errors"
startTest = "uv run pytest"
[tool.glrocky.requirements]
devices = [{ type = "phone", os = "android", count = 1 }]
[tool.glrocky.project_settings]
screen-record-extra-commands = [
"--window-x=1380",
"--window-y=50",
"--always-on-top",
"--disable-screensaver",
"--window-borderless",
"-m",
"600",
"--video-codec",
"h264",
"--video-bit-rate",
"5M",
"--max-fps",
"60",
"--time-limit",
"3600",
"--print-fps",
"--video-buffer",
"100",
"--no-audio-playback",
"--no-audio",
]
[dependency-groups]
dev = ["ruff>=0.12.2"]

0
scenarios/__init__.py Normal file
View File

483
scenarios/tc_generator.py Normal file
View File

@@ -0,0 +1,483 @@
import os
import re
import sys
import json
import time
import concurrent.futures
from dataclasses import dataclass
from pathlib import Path
from typing import Callable, Any
import pytest
import yaml
from glrocky.core.logger import logger
from glrocky.framework.marks import Marks as M
from glrocky.framework.schemas import Device
from glrocky.services.dify.dify import run_workflow
from loguru._logger import Logger
from pydantic import BaseModel, ConfigDict, Field, field_serializer, create_model
import socket
PRODUCTION_ENV_NAME = "GLROCKY_PRODUCTION_MODE"
PRODUCTION_EXECUTOR = "192.168.0.139"
YAML_FILE = Path(__file__).parent / "test_cases.yaml"
def _get_local_ip() -> str:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(("8.8.8.8", 80))
ip: str = s.getsockname()[0]
return str(ip)
finally:
s.close()
def _is_production_mode() -> bool:
env_val = os.getenv(PRODUCTION_ENV_NAME)
if env_val is not None:
return env_val.lower() in ("true", "yes", "1")
return _get_local_ip() == PRODUCTION_EXECUTOR
def pre_process_material(input: list[str]) -> str:
assert isinstance(input, list)
if not input:
return json.dumps([], ensure_ascii=False)
result = []
for text in input:
splited = _Q_PATTERN.split(text, maxsplit=50)
for part in splited:
if not part.strip():
continue
result.append(part.strip())
return json.dumps(result, ensure_ascii=False)
IS_PRODUCTION = _is_production_mode()
METRIC_FIELD_MAPPING: dict[str, str] = {
"result": "result|结果",
"_dify_result": "_dify_result|业务完成",
"_dify_message": "_dify_message|业务错误信息",
"resultText": "resultText|文本结果",
"recordVideo": "recordVideo|录像",
"recordAudio": "recordAudio|录音",
"screenshotList": "screenshotList|截图",
"firstToken": "firstToken|首字符时长",
"timeSeries": "timeSeries|时间序列",
"fileList": "fileList|文件",
}
IMAGE_EXTENSIONS = {".jpg", ".png", ".gif", ".bmp"}
VIDEO_EXTENSIONS = {".mp4", ".mkv"}
_Q_PATTERN = re.compile(r"Q\d+\s*[:\.]+\s*", flags=re.MULTILINE)
@dataclass
class _TimeoutCtx:
client: Any = None
task_id: str | None = None
def stop(self):
if self.client and self.task_id:
try:
logger.info(f"Stopping workflow: {self.task_id}")
self.client.stop_workflow(self.task_id)
logger.info(f"Stopped workflow: {self.task_id}")
except Exception as e:
logger.debug(f"Stop workflow failed: {e}")
class MetricManager:
def __init__(self, metric):
self.metric = metric
def new_span(self, m_type: str = "default", m_id: str = "default", m_iter: int = 1):
self.metric.span(m_type, m_id, m_iter)
def _smart_name_label(self, name: str, label: str | None) -> tuple[str, str]:
"""retruns: (name,label)"""
if not name or not name.strip():
raise ValueError("Empty name")
if label:
return name, label
sep = next((s for s in ("|", ":") if s in name), None)
if sep:
_n, _l = name.split(sep, maxsplit=1)
return (_n, _l)
return name, name
def _add_metric(self, name: str, value: Any, m_type: str, label: str | None = None):
_n, _l = self._smart_name_label(name, label)
self.metric.add(name=_n, label=_l, value=value, type=m_type)
def add_text_metric(self, name: str, value: str, label: str | None = None):
self._add_metric(name, value, "text", label)
def add_number_metric(self, name: str, value: float, label: str | None = None):
self._add_metric(name, value, "number", label)
def add_image_metric(self, name: str, value: Path | str, label: str | None = None):
self._add_metric(name, str(value), "image", label)
def add_video_metric(self, name: str, value: Path | str, label: str | None = None):
self._add_metric(name, value, "video", label)
def send(self):
self.metric.send_all()
def from_dict(self, the_dict: dict[str, Any]):
if not the_dict:
raise ValueError("dict is null")
for _k, v in the_dict.items():
k = METRIC_FIELD_MAPPING.get(_k, _k)
logger.info(k)
match v:
case None:
self.add_text_metric(name=k, value="")
case int() | float():
self.add_number_metric(name=k, value=v)
case str():
self.add_text_metric(name=k, value=v)
case Path():
match v.suffix.lower():
case s if s in IMAGE_EXTENSIONS:
self.add_image_metric(name=k, value=str(v.resolve()))
case s if s in VIDEO_EXTENSIONS:
self.add_video_metric(name=k, value=str(v.resolve()))
case _:
self.add_text_metric(name=k, value=str(v.resolve()))
case _:
raise TypeError(f"{type(v)} not supported")
class DifySettings(BaseModel):
difyUrl: str = Field(
title="Dify服务地址",
)
difyWorkflowId: str = Field(
title="Dify工作流ID",
)
difyApiKey: str = Field(
title="Dify API密钥",
)
class MaterialForDify(BaseModel):
paramGroupUuid: list[str] = Field(
default_factory=list, title="UUID", description="UUID"
)
inputTextList: list[str] = Field(
default_factory=list,
title="对话列表,支持多轮对话",
description="对话列表,支持多轮对话",
)
prompt: list[str] = Field(
default_factory=list, title="提示词", description="提示词"
)
model_config = ConfigDict(arbitrary_types_allowed=True) # allows uuid extra...
class DifyPayload(BaseModel):
inputTextList: list[str] | str
prompt: list[str] | str
deviceId: str
address: str
caseId: str
parameters: dict[str, Any] |str| None = None
@field_serializer("inputTextList")
def serialize_input_text(self, value: list[str] | str) -> str:
if isinstance(value, list):
return pre_process_material(value)
return value
@field_serializer("prompt")
def serialize_prompt_as_single_str(self, value: list[str] | str) -> str:
if isinstance(value, list):
return value[0] if len(value) > 0 else ""
return value
def create_dynamic_model(model_name: str, parameters: list[dict]) -> type[BaseModel]:
field_definitions = {}
for idx, param in enumerate(parameters):
name: str = (
param.get("name", "").strip() if isinstance(param.get("name"), str) else ""
)
if not name:
raise ValueError(f"参数定义错误: 第 {idx + 1} 个参数缺少 'name' 字段或为空")
label = (
param.get("label", "").strip()
if isinstance(param.get("label"), str)
else name
)
description = (
param.get("description", label).strip()
if isinstance(param.get("description"), str)
else label
)
param_type = (
param.get("type", "string").strip()
if isinstance(param.get("type"), str)
else "string"
)
if param_type not in ("string",):
raise ValueError(
f"参数 '{name}' 不支持的类型 '{param_type}',目前仅支持 'string'"
)
default = param.get("defaultValue", "")
if default and isinstance(default, str):
default = default.strip()
field_definitions[name] = (
str,
Field(default=default, title=label, description=description),
)
try:
model = create_model(model_name, __base__=BaseModel, **field_definitions)
model.model_config["extra"] = "ignore"
model()
return model
except Exception as e:
raise ValueError(f"创建参数模型 '{model_name}' 失败: {e}")
def call_dify(
case_meta_info: dict[str, str],
logger: Logger,
device_info: Device,
material: list[MaterialForDify],
dify_cfg: DifySettings,
metric,
material_reporter,
parameters: dict[str, Any] | None = None,
timeout_sec: int | None = None,
):
# logger.info(device_info.device_serial)
logger.info(dify_cfg)
event_callbacks: dict[str, Callable[..., None]] = {}
def on_node_started(_, __, d: dict[str, Any]):
logger.info(f"开始执行:{d.get('title', '')}")
logger.info(f"输入节点参数:{d.get('inputs')}")
def on_node_finished(_, __, d):
logger.info(f"结束执行:{d.get('title', '')}")
logger.info(f"节点输出:{d.get('outputs')}")
event_callbacks["on_node_started"] = on_node_started
event_callbacks["on_node_finished"] = on_node_finished
if timeout_sec:
ctx = _TimeoutCtx()
def on_workflow_started(client, event_name, event_data):
logger.info("开始执行dify任务")
ctx.client = client
ctx.task_id = event_data.get("task_id")
event_callbacks["on_workflow_started"] = on_workflow_started
if not material:
raise RuntimeError("缺少素材")
else:
logger.info(f"下发素材:{material}")
metric_manager = MetricManager(metric)
local_ip = _get_local_ip()
for material_index, item in enumerate(material, 1):
paramGroupUuid = item.paramGroupUuid[0]
assert paramGroupUuid, "The param Group Uuid Value must be set."
material_reporter.begin(paramGroupUuid)
dify_final_status = False
try:
# IMPORTANT: the group uuid for params
payload_data = {
**item.model_dump(),
"deviceId": device_info.device_serial,
"address": local_ip,
"caseId": case_meta_info.get("id", "Unknown"),
}
if parameters:
payload_data["parameters"] = json.dumps(parameters)
payload = DifyPayload(**payload_data)
logger.info(f"payload send to dify:\n{payload.model_dump_json(indent=2)}\n")
metric_manager.new_span(
"default", f"default-{material_index}", material_index
)
def _run_workflow():
return run_workflow(
api_key=dify_cfg.difyApiKey,
base_url=dify_cfg.difyUrl,
workflow_id=dify_cfg.difyWorkflowId,
inputs=payload.model_dump(exclude_none=True),
event_callbacks=event_callbacks,
)
if timeout_sec:
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
future = executor.submit(_run_workflow)
try:
result = future.result(timeout=timeout_sec)
except concurrent.futures.TimeoutError:
logger.error(f"Workflow timeout after {timeout_sec}s,(yaml config)")
time.sleep(0.1)
logger.info("尝试停止工作流...")
ctx.stop()
raise TimeoutError(f"Workflow timeout after {timeout_sec}s")
else:
result = _run_workflow()
logger.info(f"工作流返回结果:{result.outputs}")
logger.info(f"工作流最终状态:{result.success}")
if result.outputs:
logger.info("提交结果到执行器")
metric_manager.from_dict(result.outputs)
metric.send_all()
logger.info("提交结果到执行器完成")
else:
logger.warning("dify 工作流无返回")
if not result.success:
logger.error(f"工作流执行失败:{result.error}")
dify_final_status = result.success
except Exception as e:
logger.error(e)
dify_final_status = False
continue # do not break next round
finally:
material_reporter.end_with(paramGroupUuid, dify_final_status)
def make_dify_test(
meta: dict[str, str],
dify_settings: DifySettings | None = None,
param_model: type[BaseModel] | None = None,
timeout: int | None = None,
) -> Callable[..., None]:
if param_model is None:
param_model = create_model("EmptyParams", __base__=BaseModel)
@pytest.mark.usefixtures("cfg")
def _func_impl(
logger: Logger,
device_info: Device,
material: list[MaterialForDify],
metric,
material_reporter,
cfg: param_model,
) -> None:
param_dict = cfg.model_dump() if cfg else {}
call_dify(
meta,
logger,
device_info,
material,
dify_cfg=dify_settings,
metric=metric,
material_reporter=material_reporter,
parameters=param_dict,
timeout_sec=timeout,
)
# always use cfg fixture
# _func_impl = pytest.mark.usefixtures("cfg")(_func_impl)
return M.meta(**meta)(_func_impl)
def make_skip_test(meta: dict[str, str]) -> Callable[..., None]:
@M.skip(reason=f"{meta['id']} 未实现")
@M.meta(**meta)
def _func(
logger: Logger,
device_info: Device,
material: list[MaterialForDify],
metric,
) -> None:
logger.error(f"此用例在手机{device_info.device_serial}上暂未实现")
assert False, "not implemented"
return _func
def generate_cases_from_yaml(module_name: str, yaml_path: Path):
if not yaml_path.exists():
logger.warning(f"Test case definition file not found: {yaml_path}")
return
try:
with open(file=yaml_path, mode="r", encoding="utf-8") as f:
all_cases: list[dict[str, Any]] = yaml.safe_load( # pyright: ignore[reportAny]
f
)
except yaml.YAMLError as e:
logger.error(f"Failed to parse YAML file {yaml_path}: {e}")
pytest.fail(f"YAML解析失败: {yaml_path}")
return
if not all_cases:
return
for case_info in all_cases.get("cases", []):
if not isinstance(case_info, dict):
logger.debug(f"Skipping non-dictionary item in YAML file: {case_info}")
continue
case_id: str = case_info.get("id", "")
if not case_id:
logger.warning(f"用例 缺少 case_id 字段。{case_info=}")
pytest.fail(f"用例 缺少 case_id 字段。{case_info=}")
description: str = case_info.get("description", "")
if not description:
logger.warning(f"用例{case_id} 缺少 description 字段。")
pytest.fail(f"用例{case_id} 缺少 description 字段。")
action: str = case_info.get("action", "skipped")
meta = {"id": case_id, "description": description}
fn_name = f"test_{case_id.lower().replace('-', '_')}"
if action == "dify":
dify_settings: DifySettings | None = None
param_model: type[BaseModel] | None = None
timeout = case_info.get("timeout")
if parameters_def := case_info.get("parameters"):
model_name = f"{case_id.replace('-', '_')}_Params"
param_model = create_dynamic_model(model_name, parameters_def)
if dify_config_block := case_info.get("dify_config"):
env_key = "production" if IS_PRODUCTION else "testing"
if env_config := dify_config_block.get(env_key):
dify_settings = DifySettings(
difyUrl=env_config.get("url"),
difyWorkflowId=env_config.get("workflow_id"),
difyApiKey=env_config.get("api_key"),
)
else:
logger.warning(
f"No '{env_key}' config found for {case_id}, will use default."
)
fn = make_dify_test(meta, dify_settings, param_model, timeout)
elif action == "skipped":
fn = make_skip_test(meta)
elif action == "custom":
logger.info(f"Case {case_id} is a custom test.")
continue
else:
logger.warning(f"Unknown action '{action}' for case {case_id}. Skipping.")
continue
setattr(sys.modules[module_name], fn_name, fn)
logger.info(f"Generated {fn_name} for {case_id} with action '{action}'")
generate_cases_from_yaml(__name__, YAML_FILE)

929
scenarios/test_cases.yaml Normal file
View File

@@ -0,0 +1,929 @@
dify_templates:
tianjin_dify_config: &testing_config
url: "http://192.168.0.163:8090/v1"
workflow_id: "d4a40bf2-99cb-440f-97be-3793e2274318"
api_key: "app-cvFr7cpcHytfYIS0q2LpdS0B"
guangzhou_dify_config: &production_config
url: "http://192.168.0.140:8090/v1"
workflow_id: "0d340cfd-4957-4060-9220-058507c8d412"
api_key: "app-AJi9ezTtdKHoaP8Tei195n4m"
cases:
- id: TC-0101-audio
description: AI代接
category: AI社交.语音交流
action: dify
parameters:
- name: phoneNumber
label: 主测机电话
description: 主测机电话
defaultValue: "13302325670"
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "54c111d8-3be2-471f-b91d-dc5ddbd38689"
api_key: "app-WcDwbM2nVlkfg9gDmIQcGnd9"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0102-audio
description: 通话实时翻译
category: AI社交.语音交流
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "ec6415e8-902e-4d21-9076-b61f6be889a9"
api_key: "app-JFUq6450QLKFzwXlAPhmeK0f"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0103-audio
description: 通话摘要
category: AI社交.语音交流
action: skipped
- id: TC-0104-txt
description: 文本通话
category: AI社交.语音交流
action: skipped
- id: TC-0105-audio
description: AI通话降噪
category: AI社交.语音交流
action: skipped
- id: TC-0106-audio
description: AI隐私保护防漏音
category: AI社交.语音交流
action: skipped
- id: TC-0107-audio
description: 对话翻译
category: AI社交.语音交流
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "f564ab87-8836-4d3e-b6cf-766ba1630ce7"
api_key: "app-1Bfm6jx9qwquozsneXQzs349"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0108-audio
description: 面对面同声传译
category: AI社交.语音交流
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "f564ab87-8836-4d3e-b6cf-766ba1630ce7"
api_key: "app-1Bfm6jx9qwquozsneXQzs349"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0109-txt
description: AI短信
category: AI社交.短信
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0110-txt
description: AR虚拟表情
category: AI社交.短信
action: skipped
- id: TC-0110-img
description: AR虚拟表情
category: AI社交.短信
action: skipped
- id: TC-0111-video
description: 视频电话AI鉴伪
category: AI社交.社交应用
action: skipped
- id: TC-0112-doc
description: 语音快传
category: AI社交.语音快传
action: skipped
- id: TC-0112-img
description: 语音快传
category: AI社交.语音快传
action: skipped
- id: TC-0201-img
description: 日程管理
category: AI办公.日程管理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0201-audio
description: 日程管理
category: AI办公.日程管理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "20410cc9-93da-4e23-afed-000c4599a7b1"
api_key: "app-esPo8u1OLCR6gmcQXg6cGRRS"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0202-audio
description: 语音转写
category: AI办公.会议助手
action: skipped
- id: TC-0202-video
description: 语音转写
category: AI办公.会议助手
action: skipped
- id: TC-0203-doc
description: 智能纪要
category: AI办公.会议助手
action: skipped
- id: TC-0204-txt
description: 文稿创作
category: AI办公.工作文稿处理
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0204-img
description: 文稿创作
category: AI办公.工作文稿处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0205-txt
description: 文稿润色-文本
category: AI办公.工作文稿处理
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0205-doc
description: 文稿润色-文档
category: AI办公.工作文稿处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "fddf3829-a606-4347-b5ef-0c9c98915d52"
api_key: "app-vmy2OaQgR6tSPDrk49Kd4eIR"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "2c7809b7-baea-478f-9f19-c722a7a276c4"
api_key: "app-puoiD0ZqPRtFb7wrUimw4cSt"
- id: TC-0206-txt
description: 文稿排版
category: AI办公.工作文稿处理
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0206-doc
description: 文稿排版
category: AI办公.工作文稿处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "fddf3829-a606-4347-b5ef-0c9c98915d52"
api_key: "app-vmy2OaQgR6tSPDrk49Kd4eIR"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "2c7809b7-baea-478f-9f19-c722a7a276c4"
api_key: "app-puoiD0ZqPRtFb7wrUimw4cSt"
- id: TC-0207-txt
description: 长文本摘要
category: AI办公.工作文稿处理
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0208-doc
description: 文档摘要
category: AI办公.工作文稿处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "fddf3829-a606-4347-b5ef-0c9c98915d52"
api_key: "app-vmy2OaQgR6tSPDrk49Kd4eIR"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "2c7809b7-baea-478f-9f19-c722a7a276c4"
api_key: "app-puoiD0ZqPRtFb7wrUimw4cSt"
- id: TC-0209-doc
description: 多语言摘要
category: AI办公.工作文稿处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "fddf3829-a606-4347-b5ef-0c9c98915d52"
api_key: "app-vmy2OaQgR6tSPDrk49Kd4eIR"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "2c7809b7-baea-478f-9f19-c722a7a276c4"
api_key: "app-puoiD0ZqPRtFb7wrUimw4cSt"
- id: TC-0210-img
description: 图片转表格
category: AI办公.表格处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0211-img
description: 表格提取
category: AI办公.表格处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0212-txt
description: 文件搜索
category: AI办公.AI全局搜索
action: skipped
- id: TC-0213-txt
description: 图片搜索
category: AI办公.AI全局搜索
action: skipped
- id: TC-0214-txt
description: PPT生成
category: AI办公.PPT生成
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0214-doc
description: PPT生成
category: AI办公.PPT生成
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "fddf3829-a606-4347-b5ef-0c9c98915d52"
api_key: "app-vmy2OaQgR6tSPDrk49Kd4eIR"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "2c7809b7-baea-478f-9f19-c722a7a276c4"
api_key: "app-puoiD0ZqPRtFb7wrUimw4cSt"
- id: TC-0215-doc
description: 思维导图
category: AI办公.思维导图生成
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "fddf3829-a606-4347-b5ef-0c9c98915d52"
api_key: "app-vmy2OaQgR6tSPDrk49Kd4eIR"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "2c7809b7-baea-478f-9f19-c722a7a276c4"
api_key: "app-puoiD0ZqPRtFb7wrUimw4cSt"
- id: TC-0216-txt
description: 代码
category: AI办公.代码生成
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0301-txt
description: 用机问答
category: AI学习.学习问答
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0302-doc
description: 文档问答
category: AI学习.学习问答
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "fddf3829-a606-4347-b5ef-0c9c98915d52"
api_key: "app-vmy2OaQgR6tSPDrk49Kd4eIR"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "2c7809b7-baea-478f-9f19-c722a7a276c4"
api_key: "app-puoiD0ZqPRtFb7wrUimw4cSt"
- id: TC-0303-txt
description: 对话问答
category: AI学习.学习问答
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0304-txt
description: 网页问答
category: AI学习.学习问答
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0305-img
description: 多模态问答
category: AI学习.学习问答
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0305-audio
description: 多模态问答
category: AI学习.学习问答
action: skipped
- id: TC-0305-video
description: 多模态问答
category: AI学习.学习问答
action: skipped
- id: TC-0306-txt
description: 深度推理
category: AI学习.学习问答
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0307-txt
description: 文本翻译
category: AI学习.翻译
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0308-doc
description: 文档翻译
category: AI学习.翻译
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "fddf3829-a606-4347-b5ef-0c9c98915d52"
api_key: "app-vmy2OaQgR6tSPDrk49Kd4eIR"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "2c7809b7-baea-478f-9f19-c722a7a276c4"
api_key: "app-puoiD0ZqPRtFb7wrUimw4cSt"
- id: TC-0309-txt
description: 网页翻译
category: AI学习.翻译
action: skipped
- id: TC-0310-audio
description: 口语陪练
category: AI学习.AI教学
action: skipped
- id: TC-0311-img
description: 图片解题
category: AI学习.AI教学
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0312-img
description: 拍摄解题
category: AI学习.AI教学
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0313-img
description: 试卷还原
category: AI学习.AI教学
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0314-img
description: 作业批改
category: AI学习.AI教学
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0315-img
description: 作业讲解
category: AI学习.AI教学
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0316-doc
description: 屏幕问答
category: AI学习.AI学习
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "09a73902-b780-4062-a23e-234760161c12"
api_key: "app-yhbHr1ACuzPv3aW4tjzYJFQL"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0316-img
description: 屏幕问答
category: AI学习.AI学习
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "09a73902-b780-4062-a23e-234760161c12"
api_key: "app-yhbHr1ACuzPv3aW4tjzYJFQL"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0401-txt
description: 智能体唤醒拍照
category: AI影像.AI拍摄
action: skipped
- id: TC-0401-audio
description: 智能体唤醒拍照
category: AI影像.AI拍摄
action: skipped
- id: TC-0402-img
description: 笑脸抓拍
category: AI影像.AI拍摄
action: skipped
- id: TC-0403-video
description: 录制视频(美颜/美化)
category: AI影像.AI拍摄
action: skipped
- id: TC-0404-video
description: 识文
category: AI影像.AI拍摄
action: skipped
- id: TC-0405-img
description: 识物
category: AI影像.AI拍摄
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0406-img
description: AR翻译
category: AI影像.AI拍摄
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0407-txt
description: 文生图
category: AI影像.图片生成
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "4bfd4e67-e4eb-467b-8de5-5784e0d0e2b9"
api_key: "app-kY9HRbAsWTHw8sMPkBqQS0yb"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "6962c5d6-9d85-487c-844b-82f81fbfe246"
api_key: "app-QfWiJwbzSiGcakxHmFouPund"
- id: TC-0408-img
description: AI路人消除
category: AI影像.图片生成
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "efb1cd32-65e2-4119-875c-2eb06d8ddc56"
api_key: "app-Uwhou6v8t01Ieri22FQYk3bP"
- id: TC-0409-img
description: AI物体消除
category: AI影像.图片生成
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "efb1cd32-65e2-4119-875c-2eb06d8ddc56"
api_key: "app-Uwhou6v8t01Ieri22FQYk3bP"
- id: TC-0410-img
description: AI扩图
category: AI影像.图片生成
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "efb1cd32-65e2-4119-875c-2eb06d8ddc56"
api_key: "app-Uwhou6v8t01Ieri22FQYk3bP"
- id: TC-0411-img
description: 图片风格转化
category: AI影像.图片生成
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "efb1cd32-65e2-4119-875c-2eb06d8ddc56"
api_key: "app-Uwhou6v8t01Ieri22FQYk3bP"
- id: TC-0412-img
description: 涂鸦生图
category: AI影像.图片生成
action: skipped
- id: TC-0413-img
description: 图片翻译
category: AI影像.图片处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0414-img
description: AI搜图
category: AI影像.图片处理
action: skipped
- id: TC-0415-img
description: AI美颜
category: AI影像.图片处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "efb1cd32-65e2-4119-875c-2eb06d8ddc56"
api_key: "app-Uwhou6v8t01Ieri22FQYk3bP"
- id: TC-0416-img
description: AI美化
category: AI影像.图片处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "efb1cd32-65e2-4119-875c-2eb06d8ddc56"
api_key: "app-Uwhou6v8t01Ieri22FQYk3bP"
- id: TC-0417-img
description: 智能抠图
category: AI影像.图片处理
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "efb1cd32-65e2-4119-875c-2eb06d8ddc56"
api_key: "app-Uwhou6v8t01Ieri22FQYk3bP"
- id: TC-0418-img
description: 闭眼修复
category: AI影像.图片处理
action: skipped
- id: TC-0419-img
description: 一键成片
category: AI影像.视频生成
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "60aff4ac-56a9-43ae-88ea-a153572f9865"
api_key: "app-ZhPQqAyBaK6Ph2JvYmxrUyrx"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0420-img
description: 视频字幕生成
category: AI影像.视频处理
action: skipped
- id: TC-0421-img
description: 视频翻译
category: AI影像.视频处理
action: skipped
- id: TC-0501-txt
description: 公共服务查询(天气/交通路线/节假日等)
category: AI生活.生活类问答
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0502-txt
description: 通信业务查询(话费/流量/短信等)
category: AI生活.生活类问答
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0503-txt
description: 生活费用查询(水/电/煤/物业等)
category: AI生活.生活类问答
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0504-txt
description: 生活建议(美食推荐/穿搭建议等)
category: AI生活.生活类问答
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0505-txt
description: 系统控制(开关机/音量/字体等)
category: AI生活.系统操作
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0506-txt
description: 应用管理
category: AI生活.系统操作
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0507-img
description: AI圈选
category: AI生活.系统操作
action: skipped
- id: TC-0508-audio
description: 智能打开乘车码(地铁/公交等)
category: AI生活.购物/支付
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "375edfd9-bf28-4792-8f03-399b9201f6cf"
api_key: "app-dHfCMjyNgVwvny9oODgZNKui"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0509-txt
description: 商品比价
category: AI生活.购物/支付
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0509-img
description: 商品比价
category: AI生活.购物/支付
action: dify
dify_config:
production:
url: "http://192.168.0.140:8090/v1"
workflow_id: "e3f7239a-5145-4fbb-8e09-c52d65372c39"
api_key: "app-kSt3HFS7JIi6l7C3AtfIM0Hr"
testing:
url: "http://192.168.0.163:8090/v1"
workflow_id: "30ecb958-b56d-4b65-8713-f23945a8db91"
api_key: "app-w2NVHlHZzlIGnmxmkRUO4FPJ"
- id: TC-0510-txt
description: AI导航
category: AI生活.出行
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0510-img
description: AI导航
category: AI生活.出行
action: skipped
- id: TC-0511-img
description: 网约车
category: AI生活.出行
action: skipped
- id: TC-0511-txt
description: 网约车
category: AI生活.出行
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0512-txt
description: 行程规划
category: AI生活.出行
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0513-txt
description: 健康问答
category: AI生活.运动健康
action: dify
dify_config:
production: *production_config
testing: *testing_config
- id: TC-0514-txt
description: AI读屏
category: AI生活.无障碍辅助
action: skipped
- id: TC-0515-txt
description: AI看见
category: AI生活.无障碍辅助
action: skipped
- id: TC-0516-txt
description: AI播客生成
category: AI生活.咨询传播
action: skipped
- id: TC-0516-audio
description: AI播客生成
category: AI生活.咨询传播
action: skipped
- id: TC-0601-audio
description: 语音唤醒
category: 智能体基础测试.语音唤醒
action: skipped

1251
uv.lock generated Normal file

File diff suppressed because it is too large Load Diff