4.6 KiB
4.6 KiB
适配器标准:真实/仿真 × API/RPA 四档模式
凡是"连接三方系统"(ERP、CRM、SaaS、银行等)的 skill,都应采用本文的 adapter 四档模式。这样同一套业务逻辑可以在不同档位间切换:开发用仿真、CI 用 mock、上线用真实,互不影响。
为什么要分档
对接一个外部系统,工程上无非四种方式的组合:
| API(有接口) | RPA(操作界面) | |
|---|---|---|
| 真实系统 | real_api 真实 API |
real_rpa 真实界面 |
| 仿真系统 | mock 离线仿真 |
sim_rpa 仿真平台界面 |
- mock:纯离线、不联网,给单测 / CI / 开发自测,保证可重复。
- sim_rpa:操作仿真平台(如
sandbox.jc2009.com),跑真实端到端流程但不碰生产,默认开发档位。 - real_api:有官方接口时首选(最稳、最快、最易维护)。
- real_rpa:没有 API 只能操作生产界面,风险最高、放最后。
推荐优先级:real_api > sim_rpa > real_rpa,mock 永远保留做 CI。
目录骨架
业务逻辑只依赖 base 里定义的接口与数据契约,具体档位实现各自一个文件:
scripts/service/<domain>_adapter/
__init__.py # dispatch:按档位返回对应 adapter 实例
base.py # 数据契约(dataclass)+ AdapterBase 接口(NotImplementedError)
mock.py # 离线仿真,给 CI/单测
real_api.py # 真实系统 API
sim_rpa.py # 仿真平台 RPA(Playwright/pywinauto/uiautomator2)
real_rpa.py # 真实系统 RPA(占位,谨慎实现)
参考实现:
disburse-payroll-icbc/scripts/service/disburse_adapter/(已有base.py/mock.py/icbc_simulator_rpa.py)。 模板示例:scripts/service/example_adapter/(复制改名即用)。
引用方式
from service.example_adapter import get_adapter
from service.example_adapter.base import ExampleItem
adapter = get_adapter() # 由 OPENCLAW_TEST_TARGET 决定档位
result = adapter.do_batch(
target="https://sandbox.jc2009.com",
items=[ExampleItem(id="1", label="demo")],
)
mock 档位纯离线验证:
set OPENCLAW_TEST_TARGET=mock
python -c "import sys; sys.path.insert(0,'scripts'); from service.example_adapter import get_adapter; from service.example_adapter.base import ExampleItem; r=get_adapter().do_batch('x',[ExampleItem('1','a')]); print(r.ok, r.serial_no)"
base.py 写法(要点)
- 数据契约用
@dataclass:输入项(如PayrollItem)、批量结果(如BatchResult{ok, serial_no, error_msg, artifacts})。 - 接口方法抛
NotImplementedError:所有档位实现同一签名。 - 以"批"为单位返回:真实 RPA 往往是整批提交,结果按批次返回,不要假设逐条。
- 结果里带
artifacts:截图/录屏/日志路径,便于排查。
@dataclass
class XxxResult:
ok: bool
serial_no: Optional[str]
error_msg: Optional[str]
artifacts: Dict[str, Any] = field(default_factory=dict)
class AdapterBase:
name = "base"
def do_batch(self, target: str, items: list) -> XxxResult:
raise NotImplementedError
档位 dispatch
由 OPENCLAW_TEST_TARGET 统一决定用哪个 adapter(与现有测试体系一致):
OPENCLAW_TEST_TARGET |
adapter | 用途 |
|---|---|---|
unit / mock |
MockAdapter |
单测 / CI,离线 |
simulator_rpa(默认) |
SimRpaAdapter |
开发/演示,操作仿真平台 |
real_api |
RealApiAdapter |
生产,走官方接口 |
real_rpa |
RealRpaAdapter |
生产,操作真实界面(最后手段) |
# __init__.py
def get_adapter():
target = (os.environ.get("OPENCLAW_TEST_TARGET") or "simulator_rpa").lower()
if target in ("unit", "mock"):
return MockAdapter()
if target == "real_api":
return RealApiAdapter()
if target == "real_rpa":
return RealRpaAdapter()
return SimRpaAdapter() # 默认
实际可改为读
.env里的运行模式(见CONFIG.md),OPENCLAW_TEST_TARGET作为进程级覆盖优先。
测试要求
- mock 档必须能纯离线跑通,进 CI。
- 每个 adapter 单测同一组用例(契约测试),保证档位间行为一致。
- RPA 档的真实联网测试单独标记,不进默认 CI(参考
tests/desktop/)。
相关文档
RPA.md— 三端 RPA 技术选型与拟人/反反爬范式CONFIG.md—.env里如何配置运行模式与目标地址TESTING.md— 测试 target 与隔离体系