Files
ny-exam-platform/docs/dev/testing.md
T
nxxy335 d05fd4a9b5 feat(export/dashboard): 导出增强与大屏公开化
导出-每次考试/多考试对比:
- 合格次数阈值等标记项抽为常显区块,三类成绩表共用
- 附缺考名单扩展到多考试导出(取所选考试全都没交的人)
- 块表每场固定2列(成绩+合并空位),修复漏推空串导致的整行左移/串列
- 列宽按实际内容估算,合并区空位只给最小宽度
- 合格次数始终显示实际次数(含0),仅 ≥ 阈值标绿底
- 打印标题改为「成绩明细」,缺考名单分页单独成页
- 打印样式加 print-color-adjust:exact,绿底/红字可正常印出

数据大屏:
- ?class= 班级大屏免登录公开访问,接口侧放行并按班级裁剪后回传
- 单班大屏移除退出按钮,仅首页保留
- 修复红绿判定真bug:membersTable 误用 window.DASH(DASH为let声明取不到)
  改为 scoreGrade() 直接读自由变量,按后台合格率正确判红/黄/绿

测试/样例/文档同步更新,全量回归通过。
2026-09-27 22:04:17 +08:00

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

相关