Files
nxxy335 e87986fcc6 多考试块表:每场考试改为单列并修正第几次列合并
- ny_assemble_block_sheet() 中每场考试由 2 列改为 1 列,删除历史遗留的
  「是否最佳」空白列,消除每场右侧多余空白窄列
- 删除「第几次」列的纵向合并,改为逐行显示 1/2/3…,不再被吞成 1
- 合格次数行同步改为每场 1 列;未考合并加 $end > $start 跨行守卫,
  规避单行学生产生的非法 1x1 合并(Excel 修复提示)
- 列宽按考试名估算(CJK 记 2 半角宽),clamp 8~18
- 同步更新 test-multi-export.php(95 项含 4 条防回归断言)、
  make-samples.php(李四数学改为真正整场未考)、导出/接口/测试文档
  及样例预览文件;全量回归 404 项 0 失败
2026-10-06 12:22:16 +08:00

6.5 KiB
Raw Permalink Blame History

测试

回归测试分两类:PHP 自测(纯逻辑断言)与 Node e2e(起 mock 服务 + PHP 内置服务器,走真实 HTTP)。

一键运行

bash tests/run-all.sh

脚本会依次执行:

文件 类型 覆盖
tests/test-aggregate.php PHP 聚合、去重、考试次数、排序
tests/test-new-features.php PHP 再次提交置顶排序、XLSX 多表、名单导入列识别
tests/test-config-persist.php PHP 配置双写兜底(DB / config.json)
tools/test-xlsxwriter.php PHP XLSX 写入与 ZIP 打包、合并单元格、单元格级红字 / 绿底
tests/test-multi-export.php PHP 多考试块表与单场宽表的装配(合并区间、合格线、标红标绿、班级 / 组别列)
tools/test-config-save.js Node e2e 配置保存、连接变化检测、每卷配置隔离、CSRF
tools/test-upload-guard.js Node e2e 导入文件后缀白名单
tools/test-whitelist.js Node e2e 白名单导入 / 名单识别
tools/test-login-loop.js Node e2e 未配置账号 → 登录 → 已登录状态回流
tools/test-dashboard-nav.js Node e2e 数据大屏两种形态:dash-home / dash-class 骨架、顶栏控件收敛、后退锁定、班级卡片渲染
tools/test-draw-alloc.js Node e2e 随机抽取名额分配(加权 / 自定义 / 守恒 fuzz)
tools/test-block-print.js Node(不需要服务) 从 assets/app.js 抽取 sheetToHtml 校验合并区间换算与红 / 绿标记

tools/test-block-print.js、tools/make-samples.js、tools/test-dashboard-nav.js、tools/make-dash-sample.js 都会直接从生产源码里抽取函数在真数据上执行,而不是另抄一份渲染逻辑——改了这些函数,这几处会立刻暴露漂移。

::: warning 端口占用会让 e2e「假通过 / 假失败」 每个 e2e 段用固定端口(test-config-save.js 18081、test-whitelist.js 18082、test-upload-guard.js 18083 等)。 若上一次跑测试时中断,PHP 子进程可能变成孤儿服务继续占着端口:新一次运行时它的 waitPort 会照常通过 (打到的是旧服务),于是登录直接失败、报错信息指向错误的连接地址。遇到"服务已就绪但登录失败",先查端口:

netstat -ano | grep LISTENING | grep -E ":180[0-9][0-9]|:199[0-9][0-9]"
taskkill //PID <pid> //F

:::

生成导出版式样例

想直观看新版式(以及验证打印与导出一致),可生成可打开的样例:

php tools/make-samples.php            # 出两版 xlsx + sheet-data.json
node tools/make-samples.js            # 用生产 sheetToHtml 渲染打印预览 HTML

node tools/make-dash-sample.js        # 渲染数据大屏首页预览(含班级入口卡片)

产物在 docs/samples/:打印预览 preview-multi-block.html / preview-single-wide.html (+ 对应 .xlsx),大屏首页预览 dash-home-preview.html。两者都自起 mock 服务与临时数据目录, 不会读写项目 data/。

可通过环境变量覆盖运行时路径:

PHP_BIN=/usr/bin/php NODE_BIN=$(which node) bash tests/run-all.sh

单独运行 PHP 自测

php -d extension_dir="C:/php/ext" -d extension=pdo_sqlite tests/test-aggregate.php
php tests/test-new-features.php

输出为逐条 ✓ / ✗ 断言,结尾给出通过数 / 总数,失败时非零退出。

单独运行 Node e2e

e2e 需要两个进程:

  1. mock 卷王服务(必须在 tools/ 目录下启动,内部用 __dirname 解析相对路径):
cd tools
node mock-server.js        # 默认监听 19911
  1. PHP 内置服务器(端口 18081):
php -S 127.0.0.1:18081

然后:

node tools/test-config-save.js
node tools/test-draw-alloc.js

::: warning 测试会污染 data/ e2e 会备份并修改 data/ny.db、data/config.json、data/roster.json, 并在结束后恢复。若中途异常中断,请手动检查并还原:

git status data/          # data/ 已被 gitignore,需手工核对

:::

写新测试时注意

陷阱 说明
CSRF 写接口必须带 _csrf,e2e 里先从 config_get 取全局 token
DB 优先 配置读的是 DB 优先,只备份 config.json 不够,必须一起备份 data/ny.db
/tmp 路径 Node 在 Windows 下会把 /tmp/x.js 解析成 C:\tmp\x.js,脚本请写在项目目录内
json_decode 必须传 true 得到关联数组,否则 is_array(stdClass) 为 false 会静默跳过
mock 账号 mock-server 接受账号 mock

手工冒烟清单

改完代码建议至少过一遍:

  • 登录 → 主页面三张卡片有数字
  • 切换班级 → 卡片与表格联动
  • 点某一行 → 能看到该学生的每次提交
  • 导入含 .php 后缀的文件 → 被拒绝
  • 导入正常 .xlsx → 成功,且 data/uploads/ 为空
  • 工具栏「导出」只一个按钮 → 弹窗里四种内容都能出表,学号不是科学计数法
  • 成绩明细「每人成绩」切 最高 / 最新 → 成绩列跟着变,文件名带 _最高成绩 / _最新成绩
  • 每次考试导出 → 最高分红字、合格次数达标绿底、未达标留白、整场未考合并成「未考」;每场考试只占 1 列,「第几次」逐行 1/2/3 不被合并
  • 多考试打印 → 版式与导出的 Excel 一致,「合格次数」标签没被合并吞掉
  • 打印预览 → 默认成绩降序,没有教师签字栏、没有站点域名页脚;绿底 / 红字真的印出来了 (打印样式带 print-color-adjust: exact,不需要在对话框里勾「背景图形」)
  • 导出弹窗「附加内容 · 附缺考名单」→ 每次考试 / 多考试对比也出「缺考名单」工作表
  • 在每卷配置里改满分成数 / 合格率 → 数据大屏成员榜的红绿跟着变
  • 数据大屏首页 → 选试卷后列出班级卡片,点击进入单班大屏
  • 单班大屏 → 顶栏只有试卷 / 自动刷新 / 全屏,没有班级选择与退出;按浏览器后退键退不回去
  • 复制单班大屏链接在无痕窗口打开 → 直接看到该班数据(免登录),顶栏有「公开 · 无需登录」角标; 看不到其它班级的成绩;大屏首页仍要求登录
  • 数据大屏全屏进入 / 退出都正常
  • 随机抽取 → 名额守恒

相关