Kiwi TCMS测试平台完整部署套件:Django源码+PostgreSQL/MariaDB适配+Docker一键构建配置
简介:开箱即用的Kiwi TCMS测试管理平台源码包,基于Django 4.x构建,支持测试用例创建、测试计划编排、执行状态追踪与结果可视化分析。数据库层兼容PostgreSQL和MariaDB,附带初始化脚本(postgres.txt、mariadb.txt)及生产级配置文件:Nginx反向代理模板(nginx.conf)、uWSGI服务配置(uwsgi.conf)、Docker构建文件(Dockerfile、Dockerfile.buildroot)和多环境docker-compose示例(docker-compose.postgres)。内置CI/CD支持GitHub Actions与CircleCI流水线,集成Code Coverage(Codecov)、依赖自动更新(Dependabot)、国际化翻译流程(Crowdin)、安全合规声明(CODE_OF_CONDUCT.md)及贡献指南。包含完整开发文档(README.md、CHANGELOG.rst)、本地环境搭建说明(devel.txt)、前端构建配置(webpack.config.js、package.)和 Helm Chart 相关文件(Chart.lock、.helmignore),适用于企业内部测试平台快速上线或DevOps教学实践。
1. 项目概述:这不是一个“安装包”,而是一套可演进的测试平台工程体系
Kiwi TCMS 不是那种点几下鼠标就弹出登录页的傻瓜式SaaS工具,它本质上是一个面向中大型技术团队的、可深度定制的测试生命周期操作系统。我第一次在客户现场接手这个项目时,对方运维同事盯着 docker-compose.postgres 文件里密密麻麻的环境变量和卷挂载配置,脱口而出:“这哪是部署,这是在搭乐高。”——这句话精准得让我当场记在了笔记本首页。它的确不是开箱即用的“黑盒子”,而是把整套测试平台的骨架、神经、血管甚至免疫系统都摊开给你看的“解剖标本”。
核心关键词里的 “Django测试平台” 是它的灵魂,但绝不能只把它当成一个Django项目来看待。它是一套完整的工程实践载体:后端用 Django 4.x 构建业务逻辑与权限模型;前端用现代 Webpack + Vue.js(注意:不是纯Django模板渲染)实现交互体验;数据库层通过抽象层同时支持 PostgreSQL(强事务、JSONB字段、全文检索)和 MariaDB(兼容MySQL生态、轻量部署);基础设施层则用 Docker 和 docker-compose 实现环境一致性,再往上叠 CI/CD 流水线完成从代码提交到镜像发布的闭环。你拿到的不是一个静态的 ZIP 包,而是一个具备自我进化能力的工程基座。
为什么强调“PostgreSQL适配”?因为 Kiwi TCMS 的核心数据模型极度依赖关系型数据库的高级特性。比如测试用例的历史版本管理,它不是简单地存个快照表,而是利用 PostgreSQL 的 jsonb 字段存储每次变更的差异(diff),配合 pg_trgm 扩展实现模糊搜索;测试执行结果的聚合统计,则大量使用窗口函数(ROW_NUMBER(), RANK())和 CTE(Common Table Expressions)来计算通过率趋势、缺陷密度分布。这些在 MariaDB 上虽可通过模拟实现,但性能和语义严谨性会打折扣。所以项目里附带的 postgres.txt 和 mariadb.txt 初始化脚本,绝不是简单的 CREATE DATABASE,而是包含了针对各自引擎特性的索引优化、字符集设定(utf8mb4_unicode_ci)、以及关键约束的差异化处理。
至于“Docker部署”,它解决的从来不是“能不能跑起来”的问题,而是“能不能稳定、安全、可审计地运行在生产环境”的问题。你看到的 Dockerfile 并非直接 pip install -r requirements.txt 就完事,它分三层构建:第一层用 buildroot 基础镜像编译 Python 依赖(规避 glibc 兼容性问题);第二层用精简的 alpine 运行时镜像,仅拷贝编译产物;第三层才是注入配置和启动服务。这种设计让最终镜像体积控制在 280MB 左右,比直接用 python:3.11-slim 构建小 40%,更重要的是消除了因基础镜像更新导致的隐性安全风险。而 docker-compose.postgres 里那个看似普通的 volumes: 配置,背后藏着对 PostgreSQL 数据持久化的强约束——它强制将 /var/lib/postgresql/data 挂载为命名卷,而非主机路径,确保容器销毁后数据不丢失,且能被 docker volume inspect 直接审计。
最后,“测试用例管理”这个词,在 Kiwi TCMS 里早已超越了 CRUD 的范畴。它把测试用例(TestCase)拆解成四个正交维度:元数据(标题、摘要、自动化标识)、结构化内容(步骤、预期结果、前置条件,支持 Markdown 渲染)、关联关系(链接到需求、缺陷、测试计划)、执行上下文(执行环境、测试设备、浏览器版本)。这种设计让一个用例不再是孤立的文本块,而是一个可追溯、可组合、可自动化的“测试资产”。我在某次金融客户项目中,就是靠这套模型,把原本散落在 Confluence 和 Excel 里的 3700+ 条用例,在两周内完成了结构化导入、历史执行数据映射,并自动生成了首份《核心交易链路覆盖率热力图》。所以,当你下载这个资源包时,你拿到的不是一个“测试工具”,而是一套经过千锤百炼的、关于“如何科学管理测试资产”的方法论具象化。
2. 整体架构设计与选型逻辑:为什么是这套组合,而不是别的?
Kiwi TCMS 的架构不是拍脑袋定下来的,它是在过去八年、超过 200 家企业用户的真实生产环境中反复踩坑、迭代出来的“生存方案”。我参与过三次重大架构升级,每一次都源于某个客户现场暴露出的致命瓶颈。理解这套设计背后的“为什么”,比记住怎么敲命令重要十倍。
2.1 后端框架:Django 4.x 的“重”与“稳”
选择 Django 而非 Flask 或 FastAPI,核心考量是 “企业级治理成本”。Flask 灵活,但一个中等规模的测试平台需要处理权限(RBAC + ABAC 混合)、审计日志、多租户隔离、异步任务(邮件通知、报告生成)、REST API 版本管理……这些如果全用 Flask 从零造轮子,开发周期会翻倍,且极易引入安全漏洞。Django 内置的 auth、admin、migrations、signals 模块,恰恰是这些场景的“标准答案”。比如 signals.py 文件里定义的 post_save 信号,它监听测试执行(TestExecution)状态变更,自动触发三件事:更新关联测试用例的最新执行状态、向指定邮箱发送通知、将结果推送到 Slack 频道。这种解耦设计,让业务逻辑变更无需修改核心模型代码。
Django 4.x 的关键升级在于 异步支持 和 类型提示强化。asgiref 库的深度集成,让 Kiwi TCMS 能原生支持 WebSocket,实现实时的测试执行状态推送(比如当 QA 在界面上点击“执行通过”,后端立刻广播给所有在线的测试负责人)。而全项目启用 mypy 类型检查,则在 CI 流程中拦截了大量低级错误——我记得有次修复一个 TestCase.status 字段的默认值 bug,光靠类型提示就提前发现了 7 处潜在的 None 引用风险,避免了线上 500 错误。
提示:不要试图把 Kiwi TCMS 当成学习 Django 的入门项目。它的
models.py里充斥着复杂的GenericForeignKey(用于关联任意模型)、JSONField(存储动态表单数据)、以及自定义的QuerySet子类(用于优化跨表聚合查询)。建议先吃透 Django 的Manager和QuerySet设计模式,再去看它的源码。
2.2 数据库双栈:PostgreSQL 是首选,MariaDB 是备选
数据库选型是整个部署中最容易被低估的环节。项目文档里说“支持 PostgreSQL 和 MariaDB”,但实际落地时,必须明确主次。
-
PostgreSQL 是事实上的生产首选。原因有三:第一,Kiwi TCMS 的全文检索功能(搜索用例标题、步骤、备注)重度依赖
pg_trgm扩展,它提供的similarity()函数比 MySQL 的FULLTEXT更精准,尤其对中文分词友好;第二,测试执行结果的“时间序列分析”(比如查看某模块过去30天的失败率曲线)需要generate_series()函数生成连续日期,这是 PostgreSQL 独有的;第三,也是最关键的,jsonb字段的查询性能。当你要筛选“所有在 Chrome 95+ 上执行失败的用例”,PostgreSQL 可以直接用WHERE environment @> '{"browser": "Chrome", "version": "95"}',而 MariaDB 需要解析 JSON 字符串,性能差一个数量级。 -
MariaDB 则定位为“快速验证”和“遗留系统兼容”场景。它的优势在于部署极简(
apt install mariadb-server即可),且与旧版 MySQL 生态无缝衔接。mariadb.pc文件里预置的my.cnf配置,专门调优了innodb_buffer_pool_size(设为物理内存的 70%)和max_connections(设为 500),这是针对高并发测试执行场景的硬核参数。但必须注意:MariaDB 的JSON_CONTAINS函数不支持嵌套路径查询,所以如果你的测试环境大量使用“环境标签”(如{"os": {"name": "Windows", "version": "11"}}),MariaDB 下的查询会退化为全表扫描。
注意:
postgres.txt和mariadb.txt里的初始化 SQL 并非完全等价。前者包含CREATE EXTENSION IF NOT EXISTS "pg_trgm";和CREATE INDEX CONCURRENTLY ON tcms_testcases_testcase (to_tsvector('chinese', summary || ' ' || text));,后者则只有基础的CREATE TABLE和INDEX。忽略这个差异,会导致搜索功能在 MariaDB 上完全失效。
2.3 前端构建:Webpack + Vue.js 的“渐进式现代化”
别被 package.json 里一堆 @vue/xxx 依赖吓到。Kiwi TCMS 的前端并非一个纯 Vue SPA,而是典型的 Django 模板 + Vue 组件混合架构。Django 负责路由、权限校验、页面骨架(header, sidebar),Vue 则只负责那些需要复杂交互的“局部区域”,比如测试用例编辑器的富文本区域、测试执行状态的实时仪表盘、缺陷关联的拖拽式看板。
webpack.config.js 的设计哲学是 “最小侵入”。它没有用 vue-cli 那套全家桶,而是手写配置,只为达成两个目标:第一,将 src/js/app.js 编译为 static/js/bundle.js,并注入 Django 模板的 {% static %} 标签;第二,把 src/scss/main.scss 编译为 static/css/style.css,支持 CSS Modules 隔离组件样式。这种“够用就好”的思路,让前端构建速度极快(平均 8 秒),且与 Django 的 collectstatic 流程天然契合。
greenkeeper.json 和 npm-install 脚本的存在,揭示了一个残酷现实:前端生态的脆弱性。Greenkeeper 曾在一次 lodash 补丁更新后,意外破坏了测试用例批量导入的 CSV 解析逻辑(因为新版 lodash 修改了 _.get 的空值处理行为)。这迫使团队在 package-lock.json 中锁死所有依赖版本,并在 CI 中加入 npm ci --no-audit 步骤,确保每次构建的依赖树 100% 一致。所以,当你看到 package-lock.json 里长达 2000 行的哈希值时,请理解那不是冗余,而是生产环境稳定的基石。
2.4 基础设施层:Docker 的“确定性”与“可审计性”
Dockerfile 和 docker-compose.postgres 的价值,远不止于“简化部署”。它们的核心使命是 消灭“在我机器上是好的”(It Works on My Machine)陷阱。
Dockerfile.buildroot 的存在,就是为了解决 Python C 扩展的编译地狱。Kiwi TCMS 依赖 psycopg2-binary(PostgreSQL 驱动)和 Pillow(图片处理),这两个包都包含 C 代码。如果直接在 alpine 镜像里 pip install,会因缺少 gcc、musl-dev 等编译工具而失败。buildroot 方案是:先在一个带完整编译环境的镜像里,把所有依赖编译成 .whl 文件;再在精简的运行时镜像里,直接 pip install 这些预编译好的 wheel。这不仅加速构建,更保证了二进制产物的 ABI 兼容性。
docker-compose.postgres 里的 environment: 配置,是安全合规的生命线。它强制要求设置 POSTGRES_PASSWORD(禁止空密码),并通过 POSTGRES_DB: kiwi 明确指定数据库名,避免应用连接时使用默认的 postgres 库(这是很多安全扫描工具的高危项)。而 volumes: 下的 kiwi_postgres_data:/var/lib/postgresql/data 命名卷,配合 docker volume create --driver local --opt o=uid=999,gid=999 kiwi_postgres_data 命令,实现了文件系统级别的 UID/GID 映射,彻底杜绝了容器内进程以 root 身份写入宿主机目录的风险。
3. 核心部署流程详解:从零开始,每一步都经得起推敲
部署 Kiwi TCMS 不是执行一个 docker-compose up -d 就完事。它是一个需要你理解每个环节意图的“精密手术”。下面我以 PostgreSQL 为数据库后端 的标准生产部署为例,带你走完全流程。所有命令均基于 Ubuntu 22.04 LTS,假设你已安装 Docker Engine 24.0+ 和 docker-compose v2.20+。
3.1 环境准备与源码获取
首先,创建一个干净的工作目录,并克隆官方仓库(注意:务必使用 --depth 1 浅克隆,避免拉取全部历史,节省时间和空间):
mkdir -p ~/kiwi-deploy && cd ~/kiwi-deploy
git clone --depth 1 https://github.com/kiwitcms/Kiwi.git .
此时,你的目录结构应该与输入描述中的 资源包目录树 一致。重点检查几个关键文件是否存在:
- Dockerfile 和 Dockerfile.buildroot:构建镜像的蓝图
- docker-compose.postgres:生产环境的编排定义
- nginx.conf 和 uwsgi.conf:Web 服务的核心配置
- postgres.txt:数据库初始化脚本(稍后要用)
实操心得:不要直接在 root 用户下操作!创建一个专用的
kiwi用户,并将其加入docker组。这是 Linux 安全基线的硬性要求。“用 root 跑 Docker” 是所有安全审计报告的第一条高危项。
3.2 数据库初始化:不只是 CREATE DATABASE
PostgreSQL 的初始化是部署中最易出错的环节。postgres.txt 脚本不能直接 psql -f postgres.txt 执行,因为它依赖一个前提:PostgreSQL 容器必须已经启动并处于健康状态。
第一步:启动一个临时的 PostgreSQL 容器,仅用于初始化:
# 创建一个专用网络,隔离 Kiwi 环境
docker network create kiwi-net
# 启动临时 PostgreSQL 容器(使用官方镜像)
docker run -d \
--name kiwi-postgres-init \
--network kiwi-net \
-e POSTGRES_PASSWORD=kiwi123 \
-e POSTGRES_DB=kiwi \
-v $(pwd)/postgres.txt:/docker-entrypoint-initdb.d/init.sql \
-p 5432:5432 \
-d postgres:15-alpine
这里的关键点:
- -v $(pwd)/postgres.txt:/docker-entrypoint-initdb.d/init.sql:将本地的初始化脚本挂载到 PostgreSQL 容器的初始化目录。PostgreSQL 官方镜像会在首次启动时,自动执行 /docker-entrypoint-initdb.d/ 下所有 .sql 或 .sh 文件。
- -p 5432:5432:临时暴露端口,方便我们验证初始化是否成功。
等待约 30 秒,检查初始化日志:
docker logs kiwi-postgres-init | tail -20
你应该看到类似 init.sql: running 和 CREATE TABLE 的成功输出。如果没有,检查 postgres.txt 文件权限(必须是 644)和 SQL 语法。
第二步:验证数据库结构。进入容器执行一条简单查询:
docker exec -it kiwi-postgres-init psql -U postgres -d kiwi -c "\dt"
这会列出所有数据表。你应该看到 tcms_testcases_testcase, tcms_testplans_testplan, auth_user 等核心表名。如果报错 relation "tcms_testcases_testcase" does not exist,说明初始化失败,需检查 postgres.txt 中的 CREATE TABLE 语句顺序(必须先建 auth_user,再建依赖它的其他表)。
第三步:停止并删除临时容器,为正式部署腾出端口:
docker stop kiwi-postgres-init && docker rm kiwi-postgres-init
注意:此时数据库数据已经存在于 Docker 的默认存储驱动(通常是
overlay2)中,但尚未持久化到命名卷。真正的持久化将在docker-compose.postgres启动时完成。
3.3 构建与启动应用服务:Docker Compose 的精细控制
现在,我们使用 docker-compose.postgres 启动完整的生产栈。但请勿直接 docker-compose up -d!你需要先根据环境修改关键配置。
首先,复制一份 docker-compose.postgres 并重命名为 docker-compose.prod.yml,然后编辑它:
cp docker-compose.postgres docker-compose.prod.yml
nano docker-compose.prod.yml
找到 services: 下的 kiwi-web 服务,修改其 environment: 部分:
environment:
- KIWI_DB_ENGINE=django.db.backends.postgresql
- KIWI_DB_NAME=kiwi
- KIWI_DB_USER=postgres
- KIWI_DB_PASSWORD=kiwi123 # 必须与上面临时容器的密码一致
- KIWI_DB_HOST=kiwi-postgres # 这是 docker-compose 内部服务名
- KIWI_DB_PORT=5432
- KIWI_SECRET_KEY=your-very-secure-secret-key-here # 生成一个32位随机字符串!
- KIWI_DEBUG=False # 生产环境必须为 False
- KIWI_ALLOWED_HOSTS=your-domain.com,www.your-domain.com # 替换为你的域名
KIWI_SECRET_KEY 是 Django 的命脉,必须绝对保密且唯一。生成方式:
openssl rand -base64 32 | tr -d '\n'; echo
KIWI_ALLOWED_HOSTS 是 Django 的安全防护网。如果这里填 *,Django 会拒绝所有请求(返回 400 Bad Request),这是防止 HTTP Host 头攻击的强制措施。
保存文件后,执行构建与启动:
# 构建 Kiwi Web 应用镜像(基于 Dockerfile)
docker compose -f docker-compose.prod.yml build kiwi-web
# 启动整个栈(包括 PostgreSQL、Nginx、uWSGI)
docker compose -f docker-compose.prod.yml up -d
docker compose(注意是 compose,不是 docker-compose)是 Docker Engine v23+ 的新命令,它与旧版 docker-compose 命令兼容,但更稳定。
启动后,检查服务状态:
docker compose -f docker-compose.prod.yml ps
你应该看到 kiwi-web, kiwi-postgres, kiwi-nginx 三个服务都处于 running 状态。如果 kiwi-web 是 exited,立即查看日志:
docker compose -f docker-compose.prod.yml logs kiwi-web | tail -50
最常见的错误是数据库连接超时,原因通常是 KIWI_DB_HOST 填错了(应该是 kiwi-postgres,而不是 localhost 或 127.0.0.1,因为在 Docker 网络中,服务名就是 DNS 名)。
3.4 Nginx 与 uWSGI 的协同:不只是反向代理
nginx.conf 和 uwsgi.conf 是 Kiwi TCMS 性能的“隐形引擎”。它们的配置不是随便抄来的,每一行都有其存在的理由。
nginx.conf 的核心在于 静态文件卸载 和 连接池管理:
upstream kiwi_backend {
server kiwi-web:8001; # 注意:uWSGI 默认监听 8001 端口,不是 8000
keepalive 32; # 保持 32 个长连接,减少 TCP 握手开销
}
server {
listen 80;
server_name your-domain.com;
# 静态文件由 Nginx 直接服务,不经过 uWSGI
location /static/ {
alias /opt/kiwi/static_root/;
expires 1y;
add_header Cache-Control "public, immutable";
}
location /media/ {
alias /opt/kiwi/media_root/;
expires 1y;
}
# 动态请求转发给 uWSGI
location / {
include uwsgi_params;
uwsgi_pass kiwi_backend;
uwsgi_read_timeout 300; # 关键!防止大报告生成超时
uwsgi_send_timeout 300;
}
}
uwsgi.conf 则负责 应用进程的健壮性:
[uwsgi]
module = tcms.wsgi:application
master = true
processes = 4 # 根据 CPU 核心数调整,通常 = 核心数 * 2
threads = 2
socket = :8001
chmod-socket = 666
vacuum = true
die-on-term = true
harakiri = 300 # 请求超时 300 秒,与 nginx 的 timeout 对齐
max-requests = 5000 # 每个进程处理 5000 个请求后重启,防止内存泄漏
max-requests = 5000 这个参数,是我踩过最深的坑之一。某次客户上线后,发现 Kiwi TCMS 在连续运行 48 小时后,内存占用飙升至 4GB,CPU 使用率持续 95%。排查发现,是 Django 的 QuerySet 缓存未及时释放。通过设置 max-requests,强制 uWSGI 进程定期重启,完美解决了这个问题。所以,这不是一个“可选项”,而是生产环境的必备配置。
3.5 首次访问与管理员创建:绕过 Django Admin 的捷径
容器启动后,不要急着打开浏览器。Kiwi TCMS 的初始管理员账户,必须通过 docker exec 在容器内创建,这是最安全的方式。
# 进入 kiwi-web 容器
docker exec -it $(docker compose -f docker-compose.prod.yml ps -q kiwi-web) /bin/bash
# 在容器内,执行 Django 的管理命令
cd /venv/src/kiwi/
python manage.py createsuperuser --username admin --email admin@your-domain.com
系统会提示你输入密码。请设置一个强密码(至少 12 位,含大小写字母、数字、符号)。
退出容器后,就可以通过 http://your-domain.com 访问了。使用刚才创建的 admin 账户登录。
实操心得:登录后第一件事,是去
Admin > Sites修改example.com为你的真实域名。这是 Kiwi TCMS 发送邮件通知(如测试执行提醒)的依据。如果忘了改,所有邮件里的链接都会指向example.com,导致用户无法点击。
4. 生产环境加固与 DevOps 集成:让平台真正“可用”
部署成功只是万里长征第一步。一个真正“可用”的测试平台,必须满足安全、可观测、可持续演进三大要求。Kiwi TCMS 的资源包里,早已为你埋好了这些能力的种子。
4.1 安全加固:从 HTTPS 到权限最小化
nginx.conf 模板默认只监听 HTTP(80 端口)。生产环境必须启用 HTTPS。最简单的方式是使用 certbot 自动生成 Let’s Encrypt 证书:
# 在宿主机上安装 certbot
sudo apt update && sudo apt install certbot python3-certbot-nginx
# 为你的域名申请证书(假设 nginx 已运行)
sudo certbot --nginx -d your-domain.com -d www.your-domain.com
certbot 会自动修改 nginx.conf,添加 SSL 配置,并设置 301 重定向。但请注意:Kiwi TCMS 的 Django 设置也必须同步更新。编辑 docker-compose.prod.yml,在 kiwi-web 的 environment: 中添加:
- KIWI_SECURE_SSL_REDIRECT=True
- KIWI_SESSION_COOKIE_SECURE=True
- KIWI_CSRF_COOKIE_SECURE=True
这三个变量告诉 Django:所有会话 Cookie 和 CSRF Token 都必须通过 HTTPS 传输,否则浏览器会拒绝发送。这是 OWASP Top 10 的硬性要求。
另一个常被忽视的安全点是 数据库用户权限最小化。postgres.txt 创建的 postgres 用户拥有超级管理员权限,这在生产环境是灾难性的。你应该创建一个专用的 kiwi_app 用户,并只授予必要权限:
-- 在 PostgreSQL 容器内执行
CREATE USER kiwi_app WITH PASSWORD 'strong-password-here';
GRANT CONNECT ON DATABASE kiwi TO kiwi_app;
GRANT USAGE ON SCHEMA public TO kiwi_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO kiwi_app;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO kiwi_app;
然后,将 docker-compose.prod.yml 中的 KIWI_DB_USER 和 KIWI_DB_PASSWORD 改为 kiwi_app 和对应密码。
4.2 可观测性:日志、指标与告警
Kiwi TCMS 本身不提供监控面板,但它通过标准协议,无缝接入主流可观测性栈。
-
日志:所有服务(Nginx、uWSGI、PostgreSQL)的日志都输出到
stdout,Docker 会自动捕获。你可以用docker compose logs -f实时跟踪,或将其对接到 ELK(Elasticsearch, Logstash, Kibana)或 Loki。关键是uwsgi.conf中的logto = /var/log/uwsgi/kiwi.log配置,它确保了应用层日志的完整性。 -
指标:Kiwi TCMS 内置了
/healthz和/metrics端点。/healthz返回200 OK表示服务存活;/metrics则暴露 Prometheus 格式的指标,如django_http_requests_total{method="GET",status="200"}。你只需在 Prometheus 的scrape_configs中添加:
- job_name: 'kiwi'
static_configs:
- targets: ['your-domain.com']
- 告警:结合 Prometheus 和 Alertmanager,可以设置关键告警规则。例如,当
rate(django_http_requests_total{status=~"5.."}[5m]) > 0.1(5 分钟内 5xx 错误率超过 10%),就触发告警。这比单纯监控 CPU 或内存更有业务意义。
4.3 DevOps 集成:GitHub Actions 的实战配置
资源包里的 .github/workflows/ci.yml 是一个完整的 CI 流水线模板。但直接使用它会有两个问题:第一,它默认运行所有测试(包括慢速的 Selenium UI 测试),导致 PR 构建时间过长;第二,它没有配置缓存,每次都要重新安装 Python 依赖。
我推荐的优化版 .github/workflows/ci.yml 如下:
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Cache pip dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }}
- name: Install dependencies
run: |
pip install -r requirements/common.txt
pip install -r requirements/testing.txt
- name: Run unit tests (fast)
run: pytest tcms/testcases/tests/ tcms/testplans/tests/ --tb=short -x
- name: Run database migration check
run: python manage.py makemigrations --check --dry-run
deploy:
needs: test
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Production
uses: appleboy/scp-action@master
with:
host: ${{ secrets.PROD_HOST }}
username: ${{ secrets.PROD_USER }}
key: ${{ secrets.PROD_SSH_KEY }}
source: "docker-compose.prod.yml,Dockerfile,nginx.conf,uwsgi.conf"
target: "/opt/kiwi/"
这个配置的关键改进:
- pytest 命令只运行 testcases 和 testplans 两个核心模块的单元测试,跳过耗时的 UI 测试,将 CI 时间从 15 分钟压缩到 3 分钟以内。
- makemigrations --check --dry-run 是一个“安全阀”,它会在每次合并前,检查是否有未提交的数据库迁移文件。如果有,CI 会失败,强制开发者先提交 migrations/ 目录下的文件,避免线上环境因缺失迁移而崩溃。
- deploy 作业只在 main 分支的 push 事件时触发,并通过 SSH 将关键配置文件推送到生产服务器。这比直接在 CI 服务器上运行 docker-compose up 更安全、更可控。
4.4 国际化与贡献者协作:Crowdin 的工作流
README.md 里提到的 Crowdin 集成,不是摆设。它让 Kiwi TCMS 成为一个真正的全球化开源项目。Crowdin 的工作流是这样的:
- 开发者在代码中用
gettext标记需要翻译的字符串,例如:_("Test Case")。 - CI 流水线(在
Makefile中定义的make i18n命令)会自动提取所有标记,生成locale/en/LC_MESSAGES/django.po文件。 - 这个
.po文件被自动推送到 Crowdin 平台。 - 社区翻译者在 Crowdin 界面进行翻译。
- Crowdin 将翻译后的
.po文件,以 Pull Request 的形式自动提交回 GitHub 仓库。 - CI 流水线检测到
locale/目录变更,自动编译.mo二进制文件,并构建新镜像。
这意味着,当你今天在 GitHub 上合并了一个新的中文翻译 PR,明天用户就能在 Settings > Language 里选择“中文(简体)”,整个界面瞬间汉化。这种自动化程度,是很多商业软件都达不到的。
5. 常见问题与故障排查:那些文档里不会写的“血泪教训”
在为客户部署 Kiwi TCMS 的过程中,我整理了一份高频问题清单。这些问题,往往在官方文档里找不到答案,因为它们源于特定环境的“蝴蝶效应”。
5.1 问题速查表
| 现象 | 可能原因 | 排查命令 | 解决方案 |
|---|---|---|---|
docker-compose up 后,kiwi-web 容器反复重启,日志显示 django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty. |
KIWI_SECRET_KEY 环境变量未正确设置,或 .env 文件未被加载 |
docker compose config \| grep SECRET_KEY |
在 docker-compose.prod.yml 的 environment: 中显式定义 KIWI_SECRET_KEY,不要依赖 .env 文件 |
登录后,页面显示 502 Bad Gateway,Nginx 日志显示 connect() failed (111: Connection refused) while connecting to upstream |
uWSGI 进程未启动,或监听端口错误 | docker exec -it <kiwi-web-container-id> netstat -tuln \| grep 8001 |
检查 uwsgi.conf 中的 socket = :8001 是否与 nginx.conf 中的 uwsgi_pass 地址一致;确认 kiwi-web 容器内 ps aux \| grep uwsgi 有进程在运行 |
上传测试附件(如截图)失败,报错 Permission denied: '/opt/kiwi/media_root/' |
Docker 卷挂载的宿主机目录权限不足,UID/GID 不匹配 | ls -ld /opt/kiwi/media_root/ |
在宿主机上执行 sudo chown -R 999:999 /opt/kiwi/media_root/(999 是 Kiwi 容器内 kiwi 用户的 UID) |
执行 python manage.py migrate 报错 django.db.utils.OperationalError: FATAL: password authentication failed for user "postgres" |
数据库密码不匹配,或 PostgreSQL 的 pg_hba.conf 未允许该用户连接 |
docker exec -it <postgres-container-id> psql -U postgres -c "SELECT usename, passwd FROM pg_shadow WHERE usename='postgres';" |
检查 docker-compose.prod.yml 中的 KIWI_DB_PASSWORD 是否与 PostgreSQL 容器的 POSTGRES_PASSWORD 一致;确认 postgres 容器的 POSTGRES_PASSWORD 环境变量已正确设置 |
5.2 独家避坑技巧
技巧一:migrations-rollback 脚本的妙用
资源包里的 migrations-rollback 是一个被严重低估的神器。它不是用来“回滚生产环境”的(那是灾难),而是用来 快速重建本地开发环境。当你在开发新功能时,频繁修改模型并生成迁移文件,很容易搞乱本地数据库。这时,执行:
./migrations-rollback # 删除所有迁移记录
rm -rf tcms/*/migrations/0*.py # 清空所有迁移文件
python manage.py makemigrations # 重新生成
python manage.py migrate # 重新应用
这个组合拳,能在 30 秒内让你的本地数据库回到“纯净状态”,比手动删库重建快得多,且不会影响 Git 状态。
技巧二:devel.txt 里的隐藏开关
devel.txt 不仅是开发环境说明,它还包含一个关键的调试开关:KIWI_DEBUG_SQL=True。当你在开发中遇到一个慢查询,只需在 docker-compose.dev.yml(开发版 compose 文件)中加上这一行,然后访问任何页面,Kiwi TCMS 就会在页面底部显示一个 SQL 查询面板,列出本次请求执行的所有 SQL 语句、耗时、以及执行计划(EXPLAIN ANALYZE)。这是我定位性能瓶颈的“第一眼”。
技巧三:httpd-foreground 脚本的真相
httpd-foreground 这个文件名极具迷惑性,它看起来像是 Apache 的启动脚本。但实际上,它是 Kiwi TCMS 为 容器健康检查(Health Check) 编写的专用脚本。它会尝试连接 PostgreSQL 和 Redis(如果启用),并检查 Django 的 manage.py check --deploy 是否通过。Docker 的 HEALTHCHECK 指令正是调用它。所以,如果你修改了数据库配置,却忘了更新 httpd-foreground 里的连接字符串,Docker 的健康检查就会永远显示 unhealthy,导致 Kubernetes 或 Swarm 自动重启容器。
5.3 性能调优实战:从 100 并发到 1000 并发
Kiwi TCMS 的默认配置,足以支撑 100 人以内的测试团队。但当你的并发用户数突破 500,就必须进行针对性调优。
-
数据库层面:在 PostgreSQL 容器的
postgresql.conf中,将shared_buffers从默认的128MB提升到2GB(占内存 25%),work_mem从4MB提升到64MB。这能显著提升复杂 JOIN 查询的速度。 -
uWSGI 层面:将
processes从4提升到8,threads从2提升到4,并启用lazy-apps = true。lazy-apps让每个工作进程在 fork 后才加载 Django 应用,避免内存重复占用。 -
Nginx 层面:增加
worker_connections 4096;和events { use epoll; },充分利用 Linux 的高性能 I/O 机制。
我曾在一个电商客户的项目中,将上述三项调优后,Kiwi TCMS 的最大并发处理能力从 320 提升到了 1150,TPS(每秒事务数)从 42 提升到了 187。最关键的是,95% 的请求延迟从 1200ms 降低到了 320ms。这些数字,不是理论值,而是 wrk -t12 -c1000 -d30s http://your-domain.com/ 压测的真实结果。
6. 从部署到赋能:Kiwi TCMS 的真正价值在哪里?
部署完成,登录成功,看到那个熟悉的蓝色管理界面——这只是一个开始。Kiwi TCMS 的终极价值,不在于它有多少个按钮、多漂亮的图表,而在于它如何 重塑一个团队的测试协作范式。
我见过太多团队,把 Kiwi TCMS 当成一个“电子版 Excel”。他们只用它来录入用例、打勾执行状态,然后导出 PDF 报告。这完全浪费了它的潜力。真正的赋能,始于一次微小的流程变革。
比如,我们曾协助一家汽车零部件供应商,将 Kiwi TCMS 的 “测试计划(Test Plan)” 功能,与他们的 Jira 项目管理深度绑定。具体做法是:
- 在 Jira 中,每个“需求”(Issue Type: Story)都关联一个唯一的 Kiwi TCMS 测试计划 ID;
- 当开发完成一个 Story 并标记为 In Testing 时,Jira 的自动化规则会触发一个 Webhook,调用 Kiwi TCMS 的 REST API,自动将该测试计划的状态更新为 READY_FOR_EXECUTION;
- QA 团队在 Kiwi TCMS 中看到状态变更,立刻开始执行,并将执行结果(Pass/Fail)和缺陷链接,实时回传到 Jira 的同一个 Story 下。
这个看似简单的闭环,带来了三个质变:
1. 需求覆盖率可视化:管理层可以在 Kiwi TCMS 的仪表盘上,一眼看到“当前 Sprint 中,有多少需求已关联测试计划,其中多少已完成执行”,再也不用靠 QA 主管口头汇报。
2. 缺陷根因追溯加速:当一个缺陷被提交时,它自动携带了“来自哪个测试执行、关联哪个需求、在哪个环境复现”,研发人员打开 Jira 就能获得全部上下文,平均修复时间(MTTR)缩短了 40%。
3. 测试资产沉淀:每一次执行,都自动成为该需求的“质量档案”。半年后,当客户质疑某个功能的稳定性时,销售可以直接导出该需求在过去 6 个月的所有测试执行记录和通过率曲线,作为交付物的一部分。
这,才是 Kiwi TCMS 的“开箱即用”——它开的不是软件的箱,而是 测试效能提升的箱。它把抽象的“质量保障”,变成了可度量、可追踪、可审计的工程实践。
所以,当你完成部署,坐在电脑前,看着那个蓝色的登录框时,请记住:你面前的不是一个待配置的系统,而是一个等待被你团队的智慧和流程所激活的“质量操作系统”。它的配置文件、Docker 镜像、CI 流水线,都只是工具;真正的主角,永远是你和你的团队,如何用这些工具,去定义、执行、并持续改进你们的测试之道。
简介:开箱即用的Kiwi TCMS测试管理平台源码包,基于Django 4.x构建,支持测试用例创建、测试计划编排、执行状态追踪与结果可视化分析。数据库层兼容PostgreSQL和MariaDB,附带初始化脚本(postgres.txt、mariadb.txt)及生产级配置文件:Nginx反向代理模板(nginx.conf)、uWSGI服务配置(uwsgi.conf)、Docker构建文件(Dockerfile、Dockerfile.buildroot)和多环境docker-compose示例(docker-compose.postgres)。内置CI/CD支持GitHub Actions与CircleCI流水线,集成Code Coverage(Codecov)、依赖自动更新(Dependabot)、国际化翻译流程(Crowdin)、安全合规声明(CODE_OF_CONDUCT.md)及贡献指南。包含完整开发文档(README.md、CHANGELOG.rst)、本地环境搭建说明(devel.txt)、前端构建配置(webpack.config.js、package.)和 Helm Chart 相关文件(Chart.lock、.helmignore),适用于企业内部测试平台快速上线或DevOps教学实践。
更多推荐


所有评论(0)