ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Snapshot report for `test/snapshot-workflow/try-skip.js`

Snapshot report for `test/snapshot-workflow/try-skip.js` Snapshot report fortest/snapshot-workflow/try-skip.js【免费下载链接】avaNode.js test runner that lets you develop with confidence 项目地址: https://gitcode.com/gh_mirrors/ava/avaThe actual snapshot is saved intry-skip.js.snap.Generated by AVA.其中 The actual snapshot is saved in ... 说明真正的快照数据存放在同名 .snap 文件中.md 只是可视化报告。这份报告的核心价值在于正文部分——它记录了一次快照报告 diff即测试运行前后报告内容的变化用于断言特定的行为差异。 ## 核心场景t.snapshot.skip() 嵌套在 t.try() 中 该快照报告对应的测试用例定义在 [try-skip.js](https://link.gitcode.com/i/cbcc368d4bc314fe0387bdaada79f9fd) 中包含两个 test.serial 用例分别针对 discard 与 commit 两种路径 js import test from ava/test; import {cwd} from ../helpers/exec.js; import {beforeAndAfter} from ./helpers/macros.js; test.serial( t.snapshot.skip() in discarded t.try() doesn\t copy over old value, beforeAndAfter, { cwd: cwd(discard-skip), cli: [--update-snapshots], expectChanged: true, }, ); test.serial( t.snapshot.skip() in committed t.try() does copy over old value, beforeAndAfter, { cwd: cwd(commit-skip), cli: [--update-snapshots], expectChanged: false, }, );两个用例使用了同一个测试宏beforeAndAfter但指向不同的 fixture 目录并且对结果有着截然相反的预期用例fixture 目录预期结果t.snapshot.skip()位于被丢弃的t.try()中discard-skip不复制旧值.snap与.md均发生变化expectChanged: truet.snapshot.skip()位于被提交的t.try()中commit-skip复制旧值.snap与.md均保持不变expectChanged: falsecwd与cli参数表示测试会在临时目录中复制对应 fixture并以--update-snapshots标志运行 AVA。用 fixture 复现行为差异场景一被丢弃的 t.try() 中的 skipdiscard-skipfixture 的测试代码见 discard-skip/test.jsconst {default: test} await import(process.env.TEST_AVA_IMPORT_FROM); // This fixture is copied to a temporary directory, so import AVA through its configured path. test(discard a skipped snapshot, async t { t.snapshot(1); const firstTry await t.try(t { if (process.env.TEMPLATE) { t.snapshot(before (first try)); } else { t.snapshot.skip(after (first try)); } }); firstTry.discard(); const secondTry await t.try(t { t.snapshot(process.env.TEMPLATE ? before (second try) : after (second try)); }); secondTry.commit(); });当TEMPLATEtrue时这是模板运行生成基准快照两次t.try()分别记录before (first try)与before (second try)当TEMPLATE未设置时这是实际运行第一次尝试改为调用t.snapshot.skip(after (first try))且该尝试被firstTry.discard()丢弃第二次尝试记录after (second try)并commit()。模板运行产出的报告见 discard-skip/test.js.md## discard a skipped snapshot Snapshot 1 1 Snapshot 2 before (second try)而实际运行后的报告与模板相比Snapshot 2的取值发生了变化。这份变化正是快照报告 try-skip.js.md 中记录的 diff Snapshot 2 - before (second try) after (second try)也就是说第一次t.try()中的t.snapshot.skip()没有把任何值写入快照它连旧值before (first try)都没有保留第二次尝试提交的新值after (second try)直接覆盖了旧的before (second try)。这正是测试名所表达的语义——discardedt.try()中的t.snapshot.skip()不会复制旧值。场景二被提交的 t.try() 中的 skip对比commit-skipfixture见 commit-skip/test.jsconst {default: test} await import(process.env.TEST_AVA_IMPORT_FROM); test(commit a skipped snapshot, async t { t.snapshot(1); const firstTry await t.try(t { if (process.env.TEMPLATE) { t.snapshot(before); } else { t.snapshot.skip(after); } }); firstTry.commit(); });模板运行记录before实际运行改为t.snapshot.skip(after)后commit。此时行为反转skip 会从旧快照中复制旧值报告中仍然保留before见 commit-skip/test.js.md.snap与.md均不发生任何变化。因此该用例的预期是expectChanged: false。结论可以概括为两条对称的规则discard丢弃尝试内的一切快照写入包括 skip 的保留旧值行为都被回滚不产生任何副作用commit提交尝试内的快照写入被保留t.snapshot.skip()会按正常 skip 语义保留旧快照值。源码级原理skipSnapshot 的延迟记录机制上述行为并非魔法其底层实现在 lib/snapshot-manager.js 的SnapshotManager类中。关键方法skipSnapshot接受一个deferRecording标志skipSnapshot({belongsTo, index, deferRecording}) { const oldBlock this.oldBlocksByTitle.get(belongsTo); const snapshot oldBlock?.snapshots[index] ?? {}; // Retain the label from the old snapshot, so as not to assume that the // snapshot.skip() arguments are well-formed. // Defer recording if called in a try(). if (deferRecording) { return () { // Must be called in order! this.recordSerialized({belongsTo, index, ...snapshot}); }; } this.recordSerialized({belongsTo, index, ...snapshot}); }要点拆解skip 的本质是复制旧值skipSnapshot从旧快照块oldBlocksByTitle.get(belongsTo)中取出对应index的旧快照并将其原样重新记录recordSerialized。注意注释中说明会保留旧快照的 label而不是假设snapshot.skip()的参数是合法、良构的——因为 skip 的参数本身并不重要重要的是旧值。在t.try()中调用时走延迟记录分支deferRecording: true时skipSnapshot不立即写入而是返回一个闭包函数该函数被调用时才真正执行recordSerialized。discard 意味着闭包永不执行延迟记录函数只有在尝试被提交时才会被按序调用一旦尝试被discard()整个尝试产生的所有快照操作包括 skip 的复制旧值动作都会被整体放弃因此旧值不会被复制进新的快照集——这就是discard-skip场景中after (second try)得以覆盖before (second try)的原因。commit 意味着闭包按序执行尝试被提交后延迟记录函数被依次调用skip 的正常语义得以生效——旧快照值被保留报告与数据文件均保持不变。与之配套的还有deferRecord方法record的延迟版本与skipBlock(title)方法。skipBlock用于跳过整个测试块时保留旧块this.newBlocksByTitle.set(title, block)而skipSnapshot负责块内单个快照的跳过。save()方法则在hasChanges为真时将新快照集分别编码写入.snap文件并生成.md报告lib/snapshot-manager.js。测试宏如何验证变了与没变beforeAndAfter宏定义于 helpers/macros.js完整地演示了这套验证流程export async function beforeAndAfter(t, { cwd, expectChanged, env {}, cli [], }) { const updating process.argv.includes(--update-fixture-snapshots); if (updating) { // Run template await fixture([--update-snapshots], { cwd, env: { TEMPLATE: true, AVA_FORCE_CI: not-ci, }, }); } const before await readSnapshots(cwd); // Copy fixture to a temporary directory await withTemporaryFixture(cwd, async cwd { // Run fixture await fixture(cli, {cwd, env: {AVA_FORCE_CI: not-ci, ...env}}); const after await readSnapshots(cwd); if (expectChanged) { t.not(after.report, before.report, expected .md to be changed); t.notDeepEqual(after.snapshot, before.snapshot, expected .snap to be changed); t.snapshot(cleanStringDiff(before.report, after.report), snapshot report diff); } else { t.is(after.report, before.report, expected .md to be unchanged); t.deepEqual(after.snapshot, before.snapshot, expected .snap to be unchanged); } }); }【免费下载链接】avaNode.js test runner that lets you develop with confidence 项目地址: https://gitcode.com/gh_mirrors/ava/ava创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表