导出-每次考试/多考试对比: - 合格次数阈值等标记项抽为常显区块,三类成绩表共用 - 附缺考名单扩展到多考试导出(取所选考试全都没交的人) - 块表每场固定2列(成绩+合并空位),修复漏推空串导致的整行左移/串列 - 列宽按实际内容估算,合并区空位只给最小宽度 - 合格次数始终显示实际次数(含0),仅 ≥ 阈值标绿底 - 打印标题改为「成绩明细」,缺考名单分页单独成页 - 打印样式加 print-color-adjust:exact,绿底/红字可正常印出 数据大屏: - ?class= 班级大屏免登录公开访问,接口侧放行并按班级裁剪后回传 - 单班大屏移除退出按钮,仅首页保留 - 修复红绿判定真bug:membersTable 误用 window.DASH(DASH为let声明取不到) 改为 scoreGrade() 直接读自由变量,按后台合格率正确判红/黄/绿 测试/样例/文档同步更新,全量回归通过。
6.5 KiB
测试
回归测试分两类: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 需要两个进程:
- mock 卷王服务(必须在
tools/目录下启动,内部用__dirname解析相对路径):
cd tools
node mock-server.js # 默认监听 19911
- 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/为空 - 工具栏「导出」只一个按钮 → 弹窗里四种内容都能出表,学号不是科学计数法
- 成绩明细「每人成绩」切 最高 / 最新 → 成绩列跟着变,文件名带
_最高成绩/_最新成绩 - 每次考试导出 → 最高分红字、合格次数达标绿底、未达标留白、整场未考合并成「未考」;每场考试占 2 列,成绩不串列
- 多考试打印 → 版式与导出的 Excel 一致,「合格次数」标签没被合并吞掉
- 打印预览 → 默认成绩降序,没有教师签字栏、没有站点域名页脚;绿底 / 红字真的印出来了
(打印样式带
print-color-adjust: exact,不需要在对话框里勾「背景图形」) - 导出弹窗「附加内容 · 附缺考名单」→ 每次考试 / 多考试对比也出「缺考名单」工作表
- 在每卷配置里改满分成数 / 合格率 → 数据大屏成员榜的红绿跟着变
- 数据大屏首页 → 选试卷后列出班级卡片,点击进入单班大屏
- 单班大屏 → 顶栏只有试卷 / 自动刷新 / 全屏,没有班级选择与退出;按浏览器后退键退不回去
- 复制单班大屏链接在无痕窗口打开 → 直接看到该班数据(免登录),顶栏有「公开 · 无需登录」角标; 看不到其它班级的成绩;大屏首页仍要求登录
- 数据大屏全屏进入 / 退出都正常
- 随机抽取 → 名额守恒