首页
/ Serverless Dashboard CI/CD 测试执行机制详解:npm test 如何成为部署的强制门禁

Serverless Dashboard CI/CD 测试执行机制详解:npm test 如何成为部署的强制门禁

2026-09-07 17:17:44作者:劳婵绚Shirley

本文基于 Serverless Framework 官方文档 docs/sf/guides/dashboard/cicd/running-tests.md 展开,系统讲解 Serverless Dashboard CI/CD 中自动化测试的触发条件、判定规则与失败拦截行为,并覆盖 Node.js 与 Python 两类运行时的完整测试配置方案;读完本文,你可以直接照配 package.json 让每一次 GitHub 部署前的测试自动运行,并能结合仓库内源码与测试夹具验证这些行为的真实实现。

核心机制:每次部署自动执行 npm test

Serverless Framework 的 CI/CD 流程(配合 GitHub/BitBucket 仓库使用,参见 CI/CD 总览)会在每次部署前自动执行 npm test,其判定规则只有一条硬边界:

  • 测试必须通过(进程返回码为 0),服务才会继续部署
  • 测试一旦失败,本次部署直接被阻断,任何变更都不会推送到 AWS。

这条"测试不通过、绝不上线"的规则是整个 CI/CD 管道的安全闸口。文档中描述的 CI/CD 三步流程(安装依赖、运行测试、sls deploy 部署)在 自定义脚本文档 中有完整对应:"Serverless Framework runs three primary operations on your repository when you have CI/CD configured: (1) install NPM packages via npm install, (2) run tests, if present, with npm test, and (3) deploy your service using sls deploy."

这意味着测试环节位于 npm install 之后、sls deploy 之前,依赖安装完成后测试才能拿到所需的第三方库。

触发条件:test 脚本存在才运行

测试并非无条件执行。文档明确指出:只有当项目 package.json 中存在 test 脚本时,测试才会运行。文档给出的最小示例如下:

{
  "name": "my-serverless-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

"no test specified" 的跳过逻辑

这里有一个容易踩坑的细节:上面示例中的 test 脚本看起来"存在",但它的值是 echo "Error: no test specified" && exit 1——这正是 npm init 初始化新 package.json 时写入的默认占位值

文档对此给出的规则是:如果 npm test 的输出为 Error: no test specified,测试将被直接跳过(skip),部署照常继续。 换句话说,CI/CD 系统识别的不只是"有没有 test 脚本",还会识别这个特定的 npm 默认报错串,从而区分"用户真的配置了测试"与"项目只是带着 npm 自动生成的占位脚本"。

这一行为在仓库自己的测试夹具中可以得到印证。sf-core 的 Python 集成测试为各类打包场景(pipenv、poetry、uv 等)准备了大量 fixture,其中的基础 fixture 就使用了完全一致的 npm 默认脚本,例如 packages/sf-core/tests/python/tests/base/package.json

{
  "name": "example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": ""
}

同类 fixture 还有 individually_mixed_runtimelayer_onlypoetry 等,全部沿用同一占位脚本——说明"默认 npm init 脚本 = 无测试 = 跳过"是这套工具链统一遵循的约定。

实操结论:如果你希望 CI/CD 真正执行测试,必须把 test 脚本替换为真实的测试命令;如果保留 npm 默认值,测试环节会被静默跳过,部署不会有任何测试日志可供审查。

运行 Node.js 测试

对于 Node 运行时项目,CI/CD 会在运行测试之前自动执行 npm install 安装全部依赖,因此测试脚本可以直接引用 devDependencies 中的测试框架。文档给出的要求只有一条:

test 脚本更新为你的 Node 测试套件命令(例如 mocha)。

例如使用 mocha 时:

{
  "name": "my-serverless-project",
  "version": "1.0.0",
  "scripts": {
    "test": "mocha test/**/*.spec.js"
  },
  "devDependencies": {
    "mocha": "*"
  }
}

或者使用 Jest:

{
  "scripts": {
    "test": "jest"
  }
}

测试通过(退出码 0)后管道继续执行 sls deploy;任何失败都会中止部署。

运行 Python 测试

Python 项目的关键在于:Lambda 的 Python 依赖(requirements.txt)必须先在测试环境里安装好,测试才有意义。文档给出两条路径。

方案一(推荐):使用 serverless-python-requirements 插件

文档推荐使用 serverless-python-requirements 插件从 requirements.txt 安装依赖。

值得注意的是,当前仓库自身已内置了更强的 Python 依赖打包能力:packages/serverless/lib/plugins/python 目录下实现了 pip、pipenv、poetry、uv、slim 等多种依赖收集模式(对应 pip.jspoetry.jsuv.jsslim.js 等模块),其配套集成测试覆盖了 requirements.txt、Pipfile、poetry、uv.lock 等场景(见 packages/sf-core/tests/python/test.js)。从源码结构看,本地 sls package/sls deploy 与 CI/CD 管道共享同一套依赖解析逻辑,但在 Dashboard CI/CD 中,文档明确推荐的路径仍是 serverless-python-requirements 插件

方案二:用 postinstall 脚本安装依赖

如果不想引入插件,可以在 package.json 中加一个 postinstall 脚本,让 CI/CD 自动执行的 npm install 阶段顺带把 Python 依赖装进测试环境。文档给出的完整示例:

{
  "name": "demo-python",
  "version": "1.0.0",
  "scripts": {
    "postinstall": "pip3 install -r requirements.txt",
    "test": "pytest"
  },
  "devDependencies": {
    "serverless-python-requirements": "^5.0.1"
  }
}

这里两个脚本各司其职:

脚本 执行时机 作用
postinstall CI/CD 的 npm install 阶段末尾自动触发 pip3 install -r requirements.txt 安装 Python 依赖
test npm install 完成后自动触发 运行 pytest 执行 Python 测试套件

必须把 test 脚本更新为实际的 Python 测试命令(例如 pytest),否则测试依然会被跳过。

与 CI/CD 生命周期的衔接:自定义钩子

自定义脚本文档 说明,围绕测试环节还有一组 npm 原生生命周期钩子可用来扩展管道,且它们不需要任何 Dashboard 配置,直接写在 package.json 中即可:

  • pretest:在 npm test 之前执行,适合做测试数据准备、环境变量注入;
  • posttest:在 npm test 之后执行;
  • preinstall / postinstall:分别用于依赖安装前后(Python 项目的依赖安装正是借用了 postinstall);
  • 部署前后的自定义逻辑则通过 serverless-plugin-scripts 插件挂到 serverless deploybefore:deploy:deploydeploy:finalize 等钩子上。

例如,在测试前打印被部署的分支信息:

{
  "scripts": {
    "pretest": "echo \"Deploying branch: ${GITHUB_REF_NAME}\"",
    "test": "pytest"
  }
}

部署前配置自检清单

把上述文档要点浓缩为一份可直接执行的检查单:

  1. package.jsontest 脚本是否为真实测试命令?若仍是 npm init 的默认值 echo "Error: no test specified" && exit 1,测试会被跳过而非执行。
  2. 测试命令的退出码是否正确传播?只有非 0 退出码才能触发部署阻断;测试框架(mocha/jest/pytest)默认都会正确返回失败退出码,但自定义脚本中 set -e 缺失或管道吞掉退出码(如 pytest | tee log.txt)都会让门禁失效。
  3. Node 项目:确认测试框架已列入 dependenciesdevDependencies,CI/CD 的 npm install 会自动安装。
  4. Python 项目:确认依赖安装路径已配置(serverless-python-requirements 插件,或 postinstall 中的 pip3 install -r requirements.txt),且 test 指向真实测试套件(如 pytest)。
  5. 前置条件核对:按 CI/CD 总览 的要求,项目需已推送到 GitHub/BitBucket、部署目标为 AWS、运行时为 Node 或 Python,测试环节才会随部署流水线自动生效。

相关资源

登录后查看全文
热门项目推荐
相关项目推荐