mcpField
Q
qa-testing

qa-testing

github.com/rampstackco测试与质量1.0k284 次安装1 周前更新
代码仓库

关于 qa-testing

面向网站团队的通用 QA 指南,用于发布前后检查页面、功能和站点。它通过浏览器控制台代码片段执行检查,并按冒烟、标准和完整三档覆盖。

主要功能

  1. 01三级 QA 检查
  2. 02浏览器控制台审查代码
  3. 03检查元数据与页面结构
  4. 04基础无障碍与响应式检查
  5. 05跨浏览器及发布检查
  6. 06Markdown 审查报告模板

适用场景

  1. 01对部署进行冒烟测试
  2. 02检查新上线的页面或功能
  3. 03在重大版本发布前验证站点
  4. 04调查页面异常反馈

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rampstackco/claude-skills --skill qa-testing

安装后在 Claude Code 中输入/qa-testing确认已加载。

附带文件README.mdreferences/qa-report-template.md

详细介绍

QA 测试

在宣布页面、功能或网站已交付前,验证其是否正常运行。不依赖特定技术栈。通过控制台代码片段快速检查。

此技能比 accessibility-audit(更深入地检查 WCAG)和 performance-optimization(更深入地检查 Core Web Vitals)更快。一般 QA 请使用此技能;深入审计请使用专用技能。


何时使用

  • 每次部署后(冒烟测试)
  • 发布新页面或功能后(标准审计)
  • 重要版本发布前(完整发布检查矩阵)
  • 调查“看起来不太对劲”的报告
  • 网站或版块上线前验证

何时不使用

  • 深入的无障碍合规工作(使用 accessibility-audit)
  • 深入的性能调查(使用 performance-optimization)
  • 代码审查或调试(使用 code-review-web)
  • 初始网站设置或技术 SEO 基线检查(使用 seo-technical)

必需输入

  • 待测试页面的 URL 或网站
  • 所需的 QA 级别(冒烟、标准或完整)
  • 浏览器开发者工具访问权限
  • 标准级别之外需要检查的具体问题

框架:3 个级别

QA 检查范围应与风险相匹配。根据实际情况选择相应级别。

级别运行时机时间覆盖范围
冒烟每次部署后2 分钟仅检查关键信号
标准新页面或功能10 分钟页面基础项、无障碍和结构
完整重要版本发布、上线前30 分钟以上全面检查所有维度
级别 1:冒烟测试

用 2 分钟检查“这次部署有没有明显弄坏什么?”。每次部署后运行。

控制台代码片段(粘贴到浏览器开发者工具中):

const smoke = {
  title: document.title,
  titleLen: document.title.length,
  canonical: document.querySelector('link[rel="canonical"]')?.href,
  h1Count: document.querySelectorAll('h1').length,
  missingAlts: [...document.querySelectorAll('img')].filter(i => !i.hasAttribute('alt')).length,
  schema: [...document.querySelectorAll('script[type="application/ld+json"]')]
    .map(s => { try { return JSON.parse(s.innerText)['@type'] } catch(e) { return 'invalid' } }),
  brokenImages: [...document.querySelectorAll('img')].filter(i => !i.complete || i.naturalWidth === 0).length,
};
console.log(JSON.stringify(smoke, null, 2));

通过标准:

  • 标题存在,且长度为 30 至 60 个字符
  • Canonical 指向生产域名(绝不能指向 staging 或预览 URL)
  • 恰好有一个 H1
  • 没有缺少 alt 属性的图片。装饰性图片使用空 alt="" 是正确的标记,可通过检查;只有缺少该属性才算未通过。
  • 没有损坏的图片
  • 每个 schema 区块都能解析(代码片段输出中没有 invalid 条目)。页面类型是否正确属于完整级别的检查,需使用 Rich Results Test。

如果其中任何一项未通过,请先修复冒烟测试发现的问题,再继续深入测试。

级别 2:标准页面审计

用 10 分钟检查新页面或功能。涵盖页面基础项,以及无障碍和结构。

控制台代码片段:

const audit = {
  title: document.title,
  titleLen: document.title.length,
  canonical: document.querySelector('link[rel="canonical"]')?.href,
  metaDesc: document.querySelector('meta[name="description"]')?.content,
  metaDescLen: document.querySelector('meta[name="description"]')?.content?.length,
  ogImage: document.querySelector('meta[property="og:image"]')?.content,
  ogTitle: document.querySelector('meta[property="og:title"]')?.content,
  twitterCard: document.querySelector('meta[name="twitter:card"]')?.content,
  h1Count: document.querySelectorAll('h1').length,
  h1Text: document.querySelector('h1')?.innerText,
  h2Count: document.querySelectorAll('h2').length,
  h2s: [...document.querySelectorAll('h2')].map(h => h.innerText.trim().slice(0, 60)),
  totalImages: document.querySelectorAll('img').length,
  missingAlts: [...document.querySelectorAll('img')].filter(i => !i.hasAttribute('alt')).length,
  brokenImages: [...document.querySelectorAll('img')].filter(i => !i.complete || i.naturalWidth === 0).length,
  externalLinksWithoutNoopener: [...document.querySelectorAll('a[target="_blank"]')]
    .filter(a => !a.rel?.includes('noopener')).length,
  schema: [...document.querySelectorAll('script[type="application/ld+json"]')]
    .map(s => {
      try {
        const d = JSON.parse(s.innerText);
        return d['@graph'] ? d['@graph'].map(x => x['@type']) : d['@type'];
      } catch(e) { return 'invalid' }
    }),
  hasSkipLink: [...document.querySelectorAll('a[href^="#"]')].slice(0, 3)
    .some(a => /skip/i.test(a.textContent) && !!document.getElementById(a.getAttribute('href').slice(1))),
  pageLanguage: document.documentElement.lang || 'NOT SET',
  hasFavicon: !!document.querySelector('link[rel*="icon"]'),
};
console.log(JSON.stringify(audit, null, 2));

通过标准(除冒烟测试标准外,还需满足):

  • Meta description:120 至 160 个字符
  • 存在 og:image、og:title、twitter:card
  • 存在描述明确的 H2
  • 所有带有 target="_blank" 的外部链接都设置了 rel="noopener"
  • 已声明页面语言(<html> 上的 lang 属性)
  • 存在 favicon
第 3 级:完整发布检查矩阵

发布前 30 分钟检查。覆盖所有维度。

维度通过标准
冒烟测试和标准检查全部通过
无障碍(基础)运行浏览器审计工具(例如 Lighthouse),得分高于 90
性能(基础)报告模板中「性能」检查清单的每项阈值均达标,包括 INP
移动端响应式报告模板中「响应式」检查清单的每个视口均通过
跨浏览器已在 Chrome、Safari、Firefox 中测试(如果受众相关,也要测试 Edge)
表单所有表单均可成功提交并正确验证
内部链接没有失效的内部链接(随机抽查 20 个)
外部链接全部返回 200(抽查 10 个)
Sitemap返回 200,且仅列出规范 URL
robots.txt允许生产环境爬虫抓取;如适用,则阻止抓取暂存环境
安全标头存在 HSTS、X-Frame-Options、X-Content-Type-Options
HTTPS所有资源均通过 HTTPS 加载,没有混合内容
404 处理404 页面返回 HTTP 404(而不是软 200)
Schema 验证所有 Schema 均通过 Rich Results Test 验证
分析关键用户操作会按预期触发事件
缓存行为缓存标头适用于相应页面类型

对于标头,运行:

fetch(window.location.origin, { method: 'HEAD' })
  .then(r => {
    const headers = {};
    for (const [k, v] of r.headers.entries()) headers[k] = v;
    console.log(JSON.stringify(headers, null, 2));
  });

检查:strict-transport-security、x-frame-options、x-content-type-options。


特定 QA 代码片段

图片审计
const imgs = [...document.querySelectorAll('img')].map(i => ({
  src: i.src.split('/').pop().split('?')[0].slice(0, 60),
  alt: i.hasAttribute('alt') ? (i.alt === '' ? 'DECORATIVE (empty alt)' : i.alt) : 'MISSING',
  width: i.naturalWidth,
  height: i.naturalHeight,
  loaded: i.complete && i.naturalWidth > 0,
}));
console.table(imgs);
console.log({
  total: imgs.length,
  broken: imgs.filter(i => !i.loaded).length,
  noAlt: imgs.filter(i => i.alt === 'MISSING').length,
  decorative: imgs.filter(i => i.alt.startsWith('DECORATIVE')).length,
});
标题层级检查
const headings = [...document.querySelectorAll('h1, h2, h3, h4, h5, h6')].map(h => ({
  level: parseInt(h.tagName[1]),
  text: h.innerText.trim().slice(0, 80),
}));
console.table(headings);

// Check for skipped levels
const levels = headings.map(h => h.level);
let skipped = false;
for (let i = 1; i < levels.length; i++) {
  if (levels[i] > levels[i-1] + 1) {
    console.warn(`Skipped from H${levels[i-1]} to H${levels[i]}: "${headings[i].text}"`);
    skipped = true;
  }
}
if (!skipped) console.log('No skipped heading levels');
对比度抽查
function contrast(bg, fg) {
  function lum(hex) {
    return [hex.slice(1,3), hex.slice(3,5), hex.slice(5,7)]
      .map(h => parseInt(h, 16) / 255)
      .map(v => v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4))
      .reduce((a, v, i) => a + v * [0.2126, 0.7152, 0.0722][i], 0);
  }
  const [l1, l2] = [lum(bg), lum(fg)];
  const r = ((Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05)).toFixed(2);
  return r + ':1 ' + (parseFloat(r) >= 4.5 ? 'PASS body' : parseFloat(r) >= 3 ? 'PASS large only' : 'FAIL');
}

// Examples
contrast('#FFFFFF', '#4B5563'); // body color check
contrast('#FFFFFF', '#9CA3AF'); // verify gray choices
表单审计(每个表单)
[...document.querySelectorAll('form')].forEach((form, i) => {
  const fields = [...form.querySelectorAll('input, select, textarea')].map(field => ({
    type: field.type || field.tagName.toLowerCase(),
    name: field.name,
    hasLabel: !!form.querySelector(`label[for="${field.id}"]`) || !!field.closest('label'),
    required: field.required,
  }));
  console.log(`Form ${i + 1}:`);
  console.table(fields);
});
外部链接审计
const externalLinks = [...document.querySelectorAll('a[href^="http"]')]
  .filter(a => !a.href.includes(window.location.host));
const issues = externalLinks.filter(a =>
  a.target === '_blank' && (!a.rel?.includes('noopener') || !a.rel?.includes('noreferrer'))
);
if (issues.length) {
  console.warn(`${issues.length} external links missing noopener/noreferrer:`);
  issues.forEach(a => console.warn(a.href));
} else {
  console.log(`All ${externalLinks.length} external links properly attributed`);
}

工作流

  1. 选择级别。 常规部署做冒烟测试,新工作做标准检查,发布做完整检查。
  2. 运行代码片段。 粘贴相应的控制台代码片段,并检查输出。
  3. 记录失败项。 每项失败都必须在发布前修复,或登记为已知问题。
  4. 对于标准级别,增加以下检查:在 375px、768px 和 1440px 视口进行视觉检查。标准级别有意跳过 1024px;完整级别会根据模板中的其余响应式检查清单检查该视口。测试主要用户流程。
  5. 对于完整级别,增加以下检查:跨浏览器测试、Lighthouse 审计、Schema 验证、安全标头和 404 处理。
  6. 记录文档。 完整审计请使用 references/qa-report-template.md 中的模板。

常见失败模式

  • 在「小型」部署中跳过冒烟测试。 一半的生产环境故障都始于看起来「安全」的部署。
  • 运行代码片段却不查看输出。 控制台代码片段只是工具,关键在于解读其返回结果。
  • 只做视觉 QA。 只靠目测会漏掉缺失的替代文本、失效的 Schema、缺失的规范链接。务必运行代码片段。
  • 只在一种浏览器中测试。 移动版 Safari 和 Chrome 的差异足以让人措手不及。至少测试 Chrome 和 Safari。
  • 不做移动端 QA。 大多数用户都在 375px 视口下浏览。务必在该视口测试,否则日后会付出代价。
  • 只判定通过或失败,不做补救。 QA 失败必须促成修复或生成已知问题工单。未修复就发布的失败 QA,只是在走流程。

输出格式

冒烟测试:以控制台输出作为报告。

标准和完整审计:生成 Markdown 报告,文件名为 qa-report-[date].md。使用 references/qa-report-template.md 中的模板。


如果所需数据不可用

此技能的输出依赖于它无法自行生成的数据、测量结果或工具结果。当所需输入、工具或数据源不可用或无法验证时,合规的输出方式是交付成果并说明差距:需要什么、实际获取或验证了什么,以及输出的哪些部分受到影响。严禁为完成交付成果而捏造、估算或插值所需数值。明确说明差距,即为完整答复。


参考文件

评论

支持 Markdown