影刀RPA店群自动化:脚本CI/CD流水线与自动化测试体系实战

影刀RPA店群自动化:脚本CI/CD流水线与自动化测试体系实战

店群自动化项目做到后期,脚本数量会爆炸式增长。

我们统计过:50个店铺、8个平台、20多种任务类型,对应的影刀脚本和Python辅助脚本加起来超过200个。

问题来了:改一个通用函数,怎么知道会影响哪些脚本?上架流程改了,怎么验证所有店铺的上架脚本都正常?新加一个原子操作,怎么确保不会破坏现有的编排流程?

早期我们的做法是:改完脚本,手动跑几个店铺看看。没报错就上线。结果经常出现“开发环境没问题,生产环境挂了”的尴尬。

后来我们花了两个月,搭建了一套脚本CI/CD流水线与自动化测试体系

这篇文章不讲调度,也不讲运维。专门聊聊如何让店群脚本的开发和发布变得可测试、可回溯、可回滚。

适用场景:店群自动化脚本数量多、迭代频繁的团队。

picture.image

技术栈:Git + Jenkins/GitLab CI + Docker + 影刀RPA + Pytest。


一、脚本开发的痛点

先说说我们遇到的问题。

picture.image

痛点一:改动影响面不可知

一个公共的登录函数,被80个上架脚本调用。改了一行代码,不知道哪些脚本会受影响,只能全量回归测试。全量跑一遍需要4小时。

痛点二:环境差异导致“在我这能跑”

开发环境是Windows 10 + 影刀版本6.3,生产环境是Windows Server 2019 + 影刀版本6.5。同一个脚本表现不一样。

picture.image

痛点三:回滚困难

上线一个新版上架脚本,跑了2小时后发现有个bug,但已经改了几百个商品。想回滚到旧版,但旧版脚本没保留,或者数据库状态已经变了。

痛点四:缺乏回归测试

每次发布都是“信任开发”。没有自动化测试,只能靠人工点几个商品验证。

picture.image

解决这些问题的核心思路:把脚本当代码管


二、整体架构:从代码提交到生产发布

我们搭建了一条完整的CI/CD流水线:

picture.image

picture.image 阶段一:代码提交

所有影刀脚本(.xaml)和Python辅助脚本(.py)都存储在Git仓库中。每个原子操作独立一个文件,每个店铺的配置也独立。

阶段二:静态检查

  • 检查脚本是否符合命名规范
  • 检查是否有硬编码的店铺ID或密码
  • 检查Python代码的语法和lint问题

阶段三:单元测试(Python)

对Python辅助函数进行单元测试,不依赖浏览器。

阶段四:集成测试(影刀脚本)

在测试环境中,用模拟数据执行影刀脚本,验证关键路径。

阶段五:灰度发布

先在新版脚本上打canary标签,只在1个店铺运行4小时。观察健康度指标。

阶段六:全量发布

灰度通过后,更新stable标签,所有店铺逐步切换。

阶段七:回滚

如果发现严重问题,一键将stable指向上一个版本。

下面详细说每个阶段的工程实现。


三、脚本的版本管理与依赖追踪

我们使用Git管理所有脚本,分支策略:

  • main:生产环境当前版本
  • develop:集成分支
  • feature/xxx:新功能开发
  • hotfix/xxx:紧急修复

每个脚本文件的头部必须包含元数据注释:

# script: pdd_upload_product_v2.xaml
# version: 2.3.1
# dependencies: login_common, image_processor
# author: linyan
# changelog: 修复了图片上传失败的重试逻辑

CI流程会解析这些元数据,构建依赖图。当login_common脚本变更时,系统自动找出所有依赖它的脚本,并触发这些脚本的回归测试。

依赖图存储在Neo4j或简单的JSON中:

# dependency_graph.py
{
    "pdd_upload_product": ["login_common", "image_processor", "price_calculator"],
    "temu_upload_product": ["login_common", "image_processor", "translator"],
    "batch_price_update": ["login_common", "price_calculator"]
}

这样,改了一个公共模块,CI就知道要跑哪些测试。


四、测试环境隔离:影刀脚本的沙箱

测试环境必须和生产环境隔离,但又要足够真实。

我们搭建了一套测试店铺体系:每个平台都有专用的测试店铺账号,这些店铺不对真实用户开放,可以随意测试。

测试店铺的数据是生产的脱敏子集:商品数量固定、订单数量可控。

测试环境的关键配置:

  • 单独的代理IP池(测试专用)
  • 单独的Redis和数据库实例
  • 影刀RPA使用相同的版本,但配置文件中标记为env=test
  • 所有写操作(上架、改价、发货)在测试环境中只写入测试数据,不调用真实支付接口

测试脚本中,我们可以通过环境变量控制行为:

import os

def upload_product(product_data):
    env = os.getenv("AUTOMATION_ENV", "production")
    if env == "test":
        # 测试模式:只验证参数,不实际调用API
        return {"success": True, "test_mode": True}
    else:
        return real_api_call(product_data)

影刀RPA脚本中也可以通过读取外部配置文件来判断环境,比如“如果当前店铺ID以test_开头,则不执行真实发货”。


五、自动化测试框架设计

我们基于Pytest构建了一套测试框架,可以驱动影刀RPA脚本执行并验证结果。

# test_automation.py
import pytest
import subprocess
import json

class YingdaoScriptRunner:
    def __init__(self, script_path, shop_id, env="test"):
        self.script_path = script_path
        self.shop_id = shop_id
        self.env = env
        
    def run(self, inputs: dict) -> dict:
        """执行影刀脚本,返回输出结果"""
        # 将输入参数写入临时文件
        input_file = f"/tmp/input_{self.shop_id}.json"
        with open(input_file, 'w') as f:
            json.dump(inputs, f)
        # 调用影刀命令行执行脚本,传入店铺ID、环境、输入文件路径
        cmd = [
            "YDBot.exe", "run",
            "--script", self.script_path,
            "--param", f"shop_id={self.shop_id}",
            "--param", f"env={self.env}",
            "--param", f"input_file={input_file}",
            "--timeout", "120"
        ]
        result = subprocess.run(cmd, capture_output=True, text=True)
        # 解析脚本输出的JSON结果
        output = json.loads(result.stdout)
        return output

def test_pdd_upload_product_success():
    runner = YingdaoScriptRunner("scripts/pdd_upload_product.xaml", "test_shop_001")
    inputs = {
        "product_title": "测试商品-自动化测试",
        "price": 99.99,
        "image_url": "https://test.com/img.jpg"
    }
    output = runner.run(inputs)
    assert output["code"] == 0
    assert output["data"]["product_id"] is not None
    
def test_pdd_upload_product_duplicate():
    # 测试重复上架相同商品应返回错误
    runner = YingdaoScriptRunner("scripts/pdd_upload_product.xaml", "test_shop_001")
    inputs = {...}
    first = runner.run(inputs)
    assert first["code"] == 0
    second = runner.run(inputs)
    assert second["code"] != 0
    assert "duplicate" in second["msg"].lower()

对于编排引擎生成的复杂流程,我们测试的是最终业务结果,而非中间步骤。

def test_intelligent_on_off_shelve():
    # 执行编排流程
    engine = OrchestrationEngine(dsl, {"shop_id": "test_shop_001"})
    result = engine.run()
    # 验证结果:低库存商品被下架,备选池商品被上架
    low_stock_products = get_low_stock_products("test_shop_001", threshold=10)
    assert all(p.status == "off_shelf" for p in low_stock_products)
    backup_products = get_backup_pool("test_shop_001")
    assert len(backup_products) == len(low_stock_products)

测试套件在CI中自动运行,每次提交都会触发。整个测试套件(约200个用例)运行时间控制在15分钟内(并行执行)。


六、灰度发布与流量切换

测试通过后,脚本不是直接全量上线。我们使用标签机制控制哪个店铺用哪个版本的脚本。

配置中心(etcd)存储版本映射:

/scripts/pdd/upload_product/stable -> v2.3.1
/scripts/pdd/upload_product/canary -> v2.4.0-beta
/scripts/temu/upload_product/stable -> v1.8.2

节点管理器在拉取脚本时,根据店铺是否在灰度名单中决定取canary还是stable

灰度名单动态配置:

# 灰度规则:先跑1个店铺4小时
canary_shops = ["pdd_shop_888"]

灰度期间自动监控对比:

  • 灰度店铺 vs 稳定店铺的任务成功率
  • 灰度店铺 vs 稳定店铺的平均执行耗时
  • 灰度店铺的错误类型分布

如果灰度店铺的指标明显差于稳定店铺,自动回滚(将灰度版本指向稳定版本)。如果没有异常,逐步扩大灰度范围:10%店铺 → 30% → 100%。

整个过程完全自动化,不需要人工干预。


七、一键回滚机制

即使经过了测试和灰度,也可能出现问题。

我们要求每个脚本的发布记录中,必须保留至少最近3个版本的可执行文件。回滚操作只是改变配置中心的stable指针。

但有些脚本修改了数据格式,回滚后新旧数据不兼容怎么办?

解决方案:向前兼容的脚本设计

所有脚本对输入数据采用宽松读取策略:遇到未知字段忽略,遇到缺失字段使用默认值。这样新版本写的数据,旧版本也能读取(虽然可能处理得不完美,但不会崩溃)。

对于无法兼容的变更(比如数据库表结构调整),我们采用双写+迁移策略:新版本同时写新旧两种格式,运行一周后再废弃旧格式。


八、真实踩坑记录

坑1:影刀脚本无法用命令行传递复杂参数

影刀的命令行参数只支持基础类型。我们通过临时文件传递JSON解决了。

坑2:测试环境与生产环境指纹不同

测试环境的指纹比较简单,导致测试通过的脚本在生产环境因为指纹问题失败。

解决:测试环境也使用和生产环境相同的指纹生成器和代理池,只是店铺账号不同。

坑3:CI运行时间过长

全量回归测试需要4小时,严重拖慢发布节奏。

解决:只运行受影响的脚本测试。通过依赖图,只测试变更脚本及其依赖链上的脚本。平均耗时降到20分钟。

坑4:测试数据污染

多个测试并行运行时,共用了同一个测试店铺,导致状态互相干扰。

解决:每个测试用例运行前,重置测试店铺的环境(清理购物车、删除测试商品、恢复默认配置)。同时支持并行测试时自动分配独立的测试子账号。


九、度量与改进

引入CI/CD体系后,我们跟踪了几个关键指标:

  • 脚本发布频率:从每周2次提升到每天5次
  • 生产环境故障率:降低了80%(因为大部分问题在测试和灰度阶段发现)
  • 回滚平均时间:从30分钟(手动找旧版本)降到1分钟(改配置)
  • 新人加入成本:从2周降到3天(因为有了完善的测试用例作为参考)

我们还做了一个“脚本健康度”仪表盘,展示每个脚本的最近发布版本、测试覆盖率、最近一次测试结果、灰度状态。


十、总结:脚本也是软件

很多做RPA的人,把脚本当成一次性工具,写完能跑就行。

但在店群规模下,脚本的生命周期维护成本远大于开发成本。没有CI/CD,没有自动化测试,没有灰度发布,迟早会被脚本管理压垮。

影刀RPA本身不提供这些能力,但我们可以用外部的工程实践来补全。

投入产出比很高:花两周搭好框架,后续每个月的维护时间节省80%以上。

如果你有10个以上活跃脚本,建议开始考虑引入版本管理、自动化测试和灰度发布。这不是过度工程,而是规模化运营的必经之路。


作者:林焱

0
0
0
0
评论
未登录
暂无评论