人机交互实验报告与可用性测试:指标、埋点到两轮迭代
简介面向高校人机交互课程学习者这套资料包尤其适合正在完成课程实验、撰写实验报告和期末综合项目的本科生。内容围绕用户需求分析、界面设计原则、交互模式、无障碍设计与可用性评估展开涵盖二维交互式画图板、语音交互程序、订单管理、BBS与订票查询系统界面设计、VRML虚拟现实交互等实验场景并给出期末大实验从需求分析、线框图与原型制作到用户测试的完整实践线索便于对照理解实验组织方式与报告写作结构。压缩包共86个文件、约24.97MB以ppt课件、doc实验报告与设计文档、cpp与h源码、bmp与wrl素材以及exe、obj等编译文件为主兼具理论参考、可运行示例和界面素材。已有2487人学习适合用来梳理实验流程、复用界面设计思路、补充评估方法也可为课程项目选题、原型迭代和答辩整理提供参考。1. 从一份被打回的实验报告说起这套方案要解决什么A同学把十二页的人机交互实验报告交上去被打回的理由只有一句通篇在写自己点了哪里没有一句在说这个界面为什么好用、好用多少。这是这门课最容易踩的坑——实验报告不是操作记录它得用指标说话。这套材料就是围绕这句话搭起来的前半段是若干基础实验每个实验只练一种能力走查、任务分析、纸面原型、交互方式对比、行为日志、量表评估后半段是一次大实验把这些能力串成完整链路——选题收敛、任务拆解、低保真到高保真、可用性测试、两轮迭代、评估结论。它适合要交人机交互课程设计、实验报告或者毕设开题做交互原型的人也适合需要出一份可用性测试方案的产品与设计同学照着改参数就能直接跑。2. 实验体系设计六个基础实验与一次大实验的能力链路基础实验最容易散六个实验各写各的工具换三套数据格式互不相认到了大实验又得从头搭一遍。合理的做法是把它们设计成一条流水线前一个实验的产出物正好是后一个实验的输入。我一般会先把整门课的实验矩阵画出来确认每个实验只承担一种能力训练再决定用什么工具、采什么数据这样大实验阶段就不需要返工。2.1 实验矩阵每个实验只练一种能力矩阵的价值在于防止两件事一是每个实验都在做设计一个界面这种大而全的活二是六个实验其实在重复同一件事。把能力和指标对齐之后报告里该出现什么数据就变得很明确。实验练的能力主要产出落到哪个指标实验一 界面走查用启发式规则挑问题按严重度排序的问题清单问题数、严重度分布实验二 任务分析把用户目标拆成步骤层级任务图、步骤表步骤数、必经点击数实验三 纸面原型测试低保真阶段拿反馈走查记录、改版草图首步成功率、卡点位置实验四 交互方式对比控制变量做对照两组任务数据时长、错误次数实验五 行为日志分析从日志里读路径路径频次表、点击分布路径偏离率、求助次数实验六 量表评估把主观感受量化SUS 分值、认知负荷评分主观评分、短板题项从表里能看出一条依赖关系实验二拆出来的步骤是实验三纸面测试的任务脚本实验四的对照组设计决定了大实验里改版前后怎么比实验五的日志格式直接复用到大实验的高保真原型上。所以我建议在开课第二周就把这张表定下来后面每个实验只往里填数不再改结构。实验四的对照设计值得单独说一句。很多报告把交互方式对比写成两个界面各找几个人用一下然后说 A 比 B 快这种结论站不住因为人不一样、任务顺序不一样、熟练度不一样。通常的做法是同一批被试做两条任务路径顺序做拉丁方平衡一半人先 A 后 B另一半反过来这样学习效应会被摊平。样本量小的时候不要报平均值差 0.3 秒这种精度报中位数和每个人的变化方向更诚实。2.2 指标口径四个客观量加两个主观量先定死再开测指标口径必须在测试前写进方案不能等数据收完再回头解释。我见过最典型的翻车是任务完成率这一项有人把完成了但中途求助过算成功有人算失败两组数据放一起就没法比。所以每个指标都要带一句判定规则。指标判定口径采集方式任务完成率独立完成记 1提示后完成记 0.5未完成记 0主试记录表任务时长从主试读题结束到被试说好了精确到 0.1 秒计时脚本或秒表错误次数造成返工或点击无效区域的操作为一次误触不记日志 观察求助次数主动向主试提问即记一次主试主动干预另记观察记录SUS10 题五点量表按标准公式换算到 0~100问卷认知负荷六维度自评取加权均值问卷SUS 的计分规则要写在报告的方法部分不然读者不知道你的分是怎么来的奇数题第 1、3、5、7、9 题用得分减 1偶数题用 5 减得分十项求和后乘 2.5得到 0 到 100 的分数。这个分数是量表分不是百分制成绩报告里别写成可用性 82 分良好只能说高于该量表的行业参考基准并且把参考基准的来源交代清楚。认知负荷这一项容易被写虚。合理的写法是让被试在任务结束后立刻对六个维度各打一个分脑力需求、时间压力、努力程度、受挫程度、绩效感受、体力需求当场收不要事后回忆。维度分可以只报均值但报告里要说明这是自评不能等同于客观负荷。提示指标数量控制在六个以内。指标一多每个被试的测试时间会拖到四十分钟以上疲劳会直接污染后面的数据。2.3 技术选型原型要能吐数据工具要能留证据选型只看一件事——这个工具能不能产出可以贴进报告的证据。纯图片原型做出来好看但测试时所有数据都得靠人肉记一旦主试走神就丢一条。工具对比按这个标准排一遍就清楚了。方案保真度能否自动埋点报告里能贴什么纸面原型低否走查照片、卡点标注、改版草图交互原型工具中弱需手动记流程图、页面截图、跳转逻辑说明Web 前端原型高能事件日志、时长分布、路径频次桌面 GUI 原型高能同上另加窗口切换记录我一般的分工是实验三用纸面原型成本低、改起来快重点是把卡点找出来大实验用 Web 前端或桌面 GUI 做高保真因为只有能埋点的原型才拿得到时长、错误次数、路径这类客观量。前端技术栈不必复杂原生 HTML JavaScript 加 localStorage 就够别为了埋点去搭一套后端服务测试现场网络不稳的时候那是自找麻烦。还有一条经验原型里每一个可点击区域都给它一个稳定的标识别用按钮 1、按钮 2这种按顺序命名的东西。改版之后按钮顺序一变历史日志就对不上号了这个坑我在第一次做迭代对比时踩得很实。3. 基础实验报告七段式骨架与可直接跑的采集脚本基础实验报告的长度不必长六到十页足够但结构必须齐。评审看的不是文采是有没有把做了什么、看到什么、说明什么三件事分开写清楚。下面这套骨架我用了很多次改参数就能套到不同实验上。3.1 七段式骨架每段都要有证据段落写什么合格线目的与假设这次要验证什么预期方向是什么假设可被数据推翻环境与对象设备、原型版本、被试基本情况被试以编号出现注明人数与招募方式任务与流程被试要做哪几条任务主试说什么任务描述不含操作答案数据原始记录与汇总表有表有图标单位与样本量分析差异、异常、与假设的对照不只报均值解释异常点问题清单按严重度排序的界面问题每条问题有复现步骤改进建议改什么、为什么这么改与问题一一对应第二段和第四段是最容易失分的地方。被试信息写成同学若干评审没法判断样本是否有偏数据只贴一张截图没有单位、没有样本量读者没法核对。我通常会在报告开头放一张被试信息表只写编号、年龄段、相关经验年限不写姓名和身份既匿名又可追溯。分析段有个常见的写法问题只报平均时长 32 秒然后下结论说效率可以接受。这个结论没有参照物。要么给对照组要么给上一版的数据要么给任务本身的合理上限比如按步骤数估算理论最短时间。三者至少有一样结论才立得住。任务描述里不能带操作答案这条听起来简单实际特别容易违反。写成点击右上角的设置按钮进入偏好页就把答案给出去了被试只是执行指令测不出任何东西。合格的写法是把界面的字号调大只说目标不说路径。3.2 埋点采集一个能直接跑的日志脚本基础实验阶段不必上全家桶一个几十行的记录器就能把关键字段收齐。下面这段可以直接跑被试在电脑上做任务主试在关键节点按一下键。# log_session.py —— 单机交互日志记录器 # 用途被试每完成一条任务写一行记录到 CSV报告里的时长/点击/错误都从这来 import csv import time import uuid from datetime import datetime SESSION_ID uuid.uuid4().hex[:8] # 会话号报告里用它代替姓名做匿名标识 class TaskRecorder: def __init__(self, pathevents.csv): self.path path self.t0 None self.clicks 0 self.errors 0 def start(self): # perf_counter 是单调时钟不受系统时间调整影响测时长更稳 self.t0 time.perf_counter() self.clicks 0 self.errors 0 def click(self): self.clicks 1 def error(self, note): self.errors 1 def stop(self, participant, task, note): duration time.perf_counter() - self.t0 row [ SESSION_ID, participant, task, round(duration, 2), self.clicks, self.errors, datetime.now().isoformat(timespecseconds), note, ] # 用追加模式测试中断也不丢已记录的行 with open(self.path, a, newline, encodingutf-8) as f: csv.writer(f).writerow(row) return duration if __name__ __main__: rec TaskRecorder() rec.start() input(任务进行中按回车结束...) rec.stop(participantP03, taskT2_修改字号, note中途求助一次)字段含义要说得清duration单位是秒保留两位小数报告里统一换算成秒或分钟别一半秒一半毫秒clicks是被试的点击总数用来和任务的理论最少点击数对比比值超过 2 就说明路径有问题errors只记造成返工的操作误触不记否则错误率会被手抖污染note留给主试写现场观察比如犹豫 5 秒后才发现入口这类信息事后补是补不出来的。perf_counter而不是time.time()的原因值得在报告里写一句前者是单调递增的后者可能因为系统校时出现负的时长。这种细节写进去评审会认为你真的跑过测试。3.3 量表计分SUS 与认知负荷别手算十道题手算两三个人还能忍人一多必然出错方向一反就全错。用 pandas 三行就能算完而且能把汇总表直接输出成报告要的格式。# sus_score.py —— SUS 计分与汇总 import pandas as pd def sus_score(row): row 为 10 个 1~5 的评分返回 0~100 的量表分 total 0 for i, v in enumerate(row, start1): # 奇数题正向计分减 1偶数题反向用 5 减 total (v - 1) if i % 2 1 else (5 - v) return total * 2.5 df pd.read_csv(sus.csv) # 列participant, q1 ... q10 items [fq{i} for i in range(1, 11)] # 缺失值先检查不要直接填 00 会被算成极端负向 missing df[items].isna().sum().sum() print(缺失项数量:, missing) df[sus] df[items].apply(sus_score, axis1) print(df[[participant, sus]].describe().round(2)) # 样本量小于 10 时中位数比均值更能代表典型水平 print(中位数:, round(df[sus].median(), 2))参数说明sus.csv每题一列、每人一行分数写 1 到 5不要预先做反向转换反向转换在函数里做这样原始数据永远可复查。describe()会给出均值、标准差、四分位报告里贴这张表比贴十个分数更清楚。样本量小的时候这门课的实验通常五到八人我建议报中位数和极值同时把每个人的分数列出来别用均值假装自己是统计显著。注意SUS 不是越高越好地线性增长60 出头和 80 出头在实际体验上的差别没有分数看起来那么大报告里下结论要克制。3.4 数据表结构原始数据留档报告才有复盘可能一个人做实验很容易所有数据塞进一个 Excel列越加越多最后自己都分不清哪列是最初记录的、哪列是后来算的。分三张表能解决这个问题。-- 会话表一次测试一位被试一行 CREATE TABLE sessions ( session_id TEXT PRIMARY KEY, -- 与日志脚本里的会话号一致 participant TEXT NOT NULL, -- 被试编号如 P03 prototype TEXT NOT NULL, -- 原型版本如 v1 / v2 test_date TEXT NOT NULL, moderator TEXT ); -- 事件表一条任务一行原始记录不改动 CREATE TABLE events ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT REFERENCES sessions(session_id), task_code TEXT NOT NULL, -- 如 T2_修改字号 duration_s REAL NOT NULL, clicks INTEGER DEFAULT 0, errors INTEGER DEFAULT 0, help_count INTEGER DEFAULT 0, note TEXT ); -- 评分表主观量表单独存方便按版本对比 CREATE TABLE ratings ( session_id TEXT REFERENCES sessions(session_id), instrument TEXT NOT NULL, -- sus / nasa_tlx item TEXT NOT NULL, -- q1 ... q10 或维度名 score INTEGER NOT NULL );分表的关键理由是版本对比。改版之后原型版本号变了会话表里prototype一列就能把 v1 和 v2 的数据切开事件表和评分表通过session_id关联一条 SQL 就能出对比结果。原始表只追加不修改算出来的分放视图或者新表这样报告里的任何数字都能回溯到某一行原始记录。评审如果追问这个 0.5 是怎么来的你能当场打开表指给他看这比任何解释都有用。4. 综合大实验从选题收敛到两轮迭代的完整链路大实验失败的方式高度相似题目太大做到一半发现测不了最后拿几张漂亮截图凑成一份设计说明。能顺利走完的大实验共同点是范围被压得很小——小到一个明确的用户、三到五条任务、两个版本。下面按执行顺序拆开讲。4.1 选题收敛把我想做个 App拆成三条可测任务选题阶段唯一要产出的东西是任务清单不是灵感。我一般按这个顺序推先定一个人物虚构代称即可比如每周要整理一次课程资料的学生再定一个场景晚上在宿舍用笔记本整理然后从这个场景里抽任务。任务必须是用户真要干的事不能是体验一下首页这种测试用语。任务起点终点成功标准时长上限T1 找到上周的资料首页目标文件可打开独立打开且文件正确60 秒T2 把资料归到一个新分类首页分类下出现该文件分类名与内容对应90 秒T3 把一批文件分享出去文件列表生成可复制的分享入口无需主试提示75 秒时长上限的估算方法是数一遍任务的理论最少操作步数每步按 3 到 5 秒算再乘 2.5 留出认知时间。这个上限写在报告里有两个好处一是测试时能判断什么时候该介入二是分析时能算出实际时长与理论最短时长的比值效率就有了参照物不用和空气比。选题阶段还要提前想清楚一件事这个题目有没有可比的两个版本。大实验要写迭代就必须有 v1 和 v2。如果选题本身只能做一个版本比如只有一个方案可选那就在交互细节上留出对照组比如两种信息排布、两种导航方式用实验四的方法做。4.2 信息架构与低保真先做减法再做美化低保真阶段最容易跑偏的是直接开始画界面。正确的顺序是先列页面清单再定层级最后才是画。页面清单用一张表控制数量超过八个页面五到八个被试的测试量就撑不住了。页面作用关键元素优先级首页进入三条主任务的入口最近访问、搜索、分类高文件列表浏览与多选筛选、排序、批量操作高分类管理新建与调整分类分类树、拖拽区中分享面板生成分享入口有效期、权限中设置辅助功能字号、主题低优先级这一列不是给开发看的是给测试脚本用的。低优先级页面不进第一轮测试能省下大量时间第一轮只测高优先级页面把主路径的卡点先解决。导航层级我一般压在两层以内。三层以上被试在纸面测试里几乎必然迷路而纸面原型迷路和真实产品迷路的原因往往不一样前者是线索不够后者是布局问题混在一起分析会很乱。纸面测试找五个被试足够方法是一张一张卡片给让被试用手指出下一步点哪里主试只记录不引导第一下指错的位置就是卡点。4.3 高保真原型与埋点让原型自己记录过程高保真阶段的重点不是好看是能记录。下面这段是 Web 原型里用的埋点代码把任务起止、点击、页面切换都写进浏览器本地存储测试结束一键导出 CSV不需要服务器。// tracker.js —— 高保真原型埋点数据存 localStorage测试后导出 CSV const Tracker (() { const KEY hci_logs; const sessionId Math.random().toString(36).slice(2, 10); // 匿名会话号 let currentTask null; let taskStart 0; const push (record) { const logs JSON.parse(localStorage.getItem(KEY) || []); logs.push({ session: sessionId, ...record }); localStorage.setItem(KEY, JSON.stringify(logs)); }; return { // 主试点击开始记录任务起点performance.now 精度足够且不受校时影响 startTask(taskCode) { currentTask taskCode; taskStart performance.now(); push({ type: task_start, task: taskCode, t: Date.now() }); }, click(targetId) { // targetId 用稳定标识不要用按钮序号改版后才对得上 push({ type: click, task: currentTask, target: targetId, t: Date.now() }); }, endTask(success) { const duration (performance.now() - taskStart) / 1000; push({ type: task_end, task: currentTask, duration: duration.toFixed(2), success: success ? 1 : 0, t: Date.now(), }); currentTask null; }, // 测试结束后调用把 JSON 转成 CSV 触发下载 exportCsv() { const logs JSON.parse(localStorage.getItem(KEY) || []); const header session,type,task,target,duration,success,t\n; const rows logs.map((l) [l.session, l.type, l.task || , l.target || , l.duration ?? , l.success ?? , l.t].join(,) ).join(\n); const url URL.createObjectURL(new Blob([header rows], { type: text/csv })); const a document.createElement(a); a.href url; a.download logs_${sessionId}.csv; a.click(); }, }; })();几个参数的用意sessionId每次页面加载生成一次报告里用它对上被试编号不出现姓名performance.now()得到的是毫秒级单调时间算时长比Date.now()稳targetId必须是业务含义的稳定标识如btn_share不能是自动生成的序号否则改版后历史日志无法对齐success用 0/1 记录是为了后面能直接求和算完成率。导出用 Blob 加a download测试现场不依赖网络这一点在实验室最实用。提示正式测试前用自己跑三遍全流程确认每次点结束都能写进日志。埋点丢数据是最难补救的事故事后没法重测同一批被试。4.4 两轮迭代改什么要有来源改完要复测迭代记录表是大实验里最能体现工程性的东西比任何界面截图都有说服力。问题编号要能追到来源严重度要有分级标准改完必须有一列复测结果。编号来源现象严重度改动复测结果P-01纸面测试三名被试探索不到分类入口S2首页加显式分类区T2 平均时长 96→61 秒P-02日志分析分享按钮点击后无反馈重复点击S1增加生成中状态与结果提示重复点击 0 次P-03走查字号设置藏在二级页S3移入首页快捷区未复测低优先级P-04访谈批量选择后不清楚选了几个S2顶部显示已选计数SUS 单项分提升严重度分级我一般用四级S1 是阻断主任务做不下去S2 是显著增加时长或错误S3 是体验瑕疵但有替代路径S4 是纯视觉问题。第一轮只改 S1 和 S2S3 挑改动成本低的顺手做S4 留到最后一轮。理由很实在两轮迭代的窗口期通常只有两三周什么都改等于什么都没验证清楚。复测只测受影响的任务不要整套重跑。比如 P-01 改了首页入口就只重测 T2其他任务在新版本上跑一遍确认没被改坏即可。报告里对比要写成同一任务、不同版本的形式两组的中位数、完成率、错误次数并列再给一句结论改动解决了什么问题、还有没有遗留。这样的迭代记录评审一看就知道你是按流程走的不是事后编的。5. 常见问题与排查五个最容易翻车的地方下面这五条是这门课里出现频率最高的翻车点每一条都在答辩现场被追问过。我按现象—原因—解决写方便对照自查。5.1 报告写成操作流水账现象是报告从打开页面写到关闭页面每一步配一张截图读完不知道结论是什么。原因是写作者把我做了什么当成了报告主体而实验报告的主体是数据说明了什么操作步骤只是让别人能复现的方法说明。解决办法是把每段都改成证据 判断的结构贴完一组时长数据紧跟一句这组数据支持或推翻了哪个假设再跟一句由此发现的具体界面问题。截图数量砍掉一半把省下的篇幅用来写分析和问题清单。判断标准很简单——随便删掉一段如果删完结论不受影响那段就是流水账。5.2 被试全是同班同学结论站不住现象是五名被试里四个同专业、三个同宿舍测试时互相已经见过原型。原因不是懒是招募成本被低估了。同质样本会带来两个偏差一是学习效应前面的人用过后面的人提前知道入口在哪二是客气偏差熟人不好意思说难用评分普遍虚高。解决办法是定一条最低线至少一半被试不能是设计者认识的人招募时按是否有同类产品使用经验分层测试前明确告知测的是界面不是你越挑刺越有价值。如果实在只有同质样本就在报告的局限性部分写清楚并说明结论只在这个人群内成立别硬推成普适结论。5.3 改完版没复测迭代成了自说自话现象是报告里列了一堆改进第二版截图很漂亮但没有任何数据说明改完到底好了多少。原因通常是时间不够或者觉得改了肯定更好。这个判断往往不成立改动引入新问题的概率相当高尤其是加了提示和状态之后界面反而变吵。解决办法是把复测写进计划表而不是留到最后第一轮测试结束当天就定复测范围只测 S1、S2 涉及的任务复测人数可以减到三人只要能看出方向。报告里给出改前改后的同任务对比哪怕样本小也比没有数据强。5.4 指标口径中途改前后数据对不上现象是 v1 的完成率 80%v2 的完成率 60%看起来变差了实际是因为 v2 阶段把提示后完成从成功改成了失败。原因是口径没有在测试前固定改着改着就忘了。解决办法是把指标定义写进方案首页作为附录保留后续任何调整都记一条变更说明并注明该变更仅影响第几轮之后的数据。分析时宁可把两轮数据分开报也不要把不同口径的数字放同一张图里比。这条经验在真实项目里同样成立指标一旦开始漂移整份报告的可信度就没了。5.5 日志时间戳与任务编号错位数据没法用现象是导出 CSV 后发现任务编号全是空或者时长出现负数、几万秒的异常值。常见原因有三个任务开始时没有重置计时器导致上一条任务的时长被累加targetId用了会变的元素序号改版后日志对不上中途刷新页面内存里的当前任务状态丢了而日志已经写进去了。解决办法是任务开始必须显式调用一次startTask把当前任务和起始时间同时重置标识统一用业务名而非位置序号日志在每次写入后立即落盘到 localStorage刷新后能续上。测试前用自己跑三遍全流程检查导出的 CSV 里有没有空任务、异常时长这一步花十分钟能省掉事后无法补救的麻烦。6. 验收与答辩用一页指标表把更好用讲成证据答辩时间通常只有八分钟讲界面细节讲不完也没人爱听。能拿到好反馈的讲法只有一种先给结论再给支撑结论的那张表。我一般会准备一页纸的汇总表正反两面打印讲的时候手上有东西指。指标v1v2变化说明任务完成率72%91%19 个百分点提示后完成记 0.5任务时长中位数88 秒62 秒-30%同一批任务 T1–T3平均错误次数2.41.1-54%仅记造成返工的操作求助次数合计176-65%主试主动干预不计SUS 中位数62.580.017.5六人v2 为五人复测认知负荷均值4.13.2-0.9六维度五点自评这张表的作用是把我觉得更好用了换成六项指标里五项改善一项持平。讲解顺序建议按结论—证据—代价走先说 v1 到 v2 主路径时长降了三成、完成率提了近二十个百分点再挑一到两个具体改动说明因果比如首页入口外露之后 T2 的时长从 96 秒掉到 61 秒最后主动交代代价和局限比如复测只有五人、SUS 分差不能当显著性讲、有一个 S3 问题没来得及改。主动说局限不会减分被追问才承认才减分。被问到你怎么知道不是被试变熟练了标准答法是两条任务路径做了顺序平衡且 v2 复测只重跑受影响任务前后间隔控制在一周内同时坦率说明这是课程条件下的对照不是严格实验设计。被问到这个界面为什么这么排别答因为好看答纸面测试里三名被试在这个位置找不到入口改到这里之后首步成功率达到 5/5。所有回答都落回数据答不上来的就说没测过、是下一轮要补的这比现编一个理由安全得多。还有个小技巧把原始 CSV 和问卷一起放在附录里答辩时如果有人质疑某个数字直接翻到附录指出来。我带过的一次答辩里评审随机挑了一个时长数据要求核对当场翻到日志原始行后面几个问题明显温和了很多。从那以后我每次交实验报告都强制走一遍数字能不能翻到原始记录的自查凡是翻不到出处的数字要么补出处要么删掉。希望这套结构帮到你照着改改参数就能跑起来。本文还有配套的精品资源点击获取