布解讀:更智能的默認(rèn)值、統(tǒng)一字符串 API 與更精確的調(diào)度器)
開發(fā)工具測(cè)試【免費(fèi)下載鏈接】fast-checkProperty based testing framework for JavaScript (like QuickCheck) written in TypeScript項(xiàng)目地址https://gitcode.com/gh_mirrors/fa/fast-check點(diǎn)擊查看免費(fèi)下載fast-check 4.0.0 標(biāo)志著 3.x 系列的終結(jié)也是該屬性測(cè)試Property Based Testing框架在 API 精簡(jiǎn)、現(xiàn)代標(biāo)準(zhǔn)擁抱與去 polyfill 化上的關(guān)鍵里程碑。本文基于倉(cāng)庫(kù)中的官方發(fā)布說明Whats new in fast-check 4.0.0?與遷移指南From 3.x to 4.x并結(jié)合源碼實(shí)現(xiàn)逐項(xiàng)展開幫助你在升級(jí)到 v4 時(shí)準(zhǔn)確理解每一項(xiàng)破壞性變更的動(dòng)機(jī)、替代寫法與底層原理。版本背景基于 3.23.2 的 4.0.0v4.0.0 直接基于 v3.23.2 構(gòu)建見 CHANGELOG.md 中的 4.0.0 小節(jié)官方將本次發(fā)布定位為縮減 API 表面積讓 fast-check 的上手更簡(jiǎn)單Reducing the API surface to ease ramp-up on fast-check。官方建議的遷移路徑是先升級(jí)到最新的 3.x 小版本處理其中已有的 deprecation 提示再切換到 4.x——因?yàn)榇蟛糠制茐男宰兏鼜U棄 API 的移除、新默認(rèn)值在 3.x 的后期小版本中就已以非破壞方式鋪墊完畢。官方給出的最小環(huán)境要求變化如下名稱新要求舊要求Node≥12.17.0≥8ECMAScript 規(guī)范ES2020ES2017TypeScript可選≥5.0≥4.1這一點(diǎn)在當(dāng)前倉(cāng)庫(kù)中可以得到印證packages/fast-check/package.json 中聲明了engines: { node: 12.17.0 }即構(gòu)建與運(yùn)行都強(qiáng)制 Node 不低于 12.17.0。三大核心變化Key Takeaways發(fā)布說明將 4.0.0 概括為三項(xiàng)核心變化更智能的默認(rèn)值Smarter defaults、統(tǒng)一的字符串構(gòu)建器Unified string builder、更精細(xì)的調(diào)度器Finer scheduler。下面逐項(xiàng)展開。1. 更智能的默認(rèn)值Invalid Date 與無(wú)原型對(duì)象4.0.0 延續(xù)提供更具挑戰(zhàn)性的默認(rèn)行為的思路date默認(rèn)開始生成 Invalid Daterecord/dictionary/object默認(rèn)可能生成null原型對(duì)象。官方目標(biāo)是在用戶替他們預(yù)判邊界場(chǎng)景讓測(cè)試者專注于規(guī)格定義本身。date 默認(rèn)包含 Invalid Date。從 date.ts 的實(shí)現(xiàn)可以看到其機(jī)制約束接口中noInvalidDate的默認(rèn)值為false源碼注釋明確defaultValue false當(dāng)未禁用時(shí)實(shí)現(xiàn)把生成區(qū)間從[intMin, intMax]擴(kuò)展為[intMin, intMax 1]用額外的一個(gè)整數(shù)值valueForNaN intMax 1映射出 Invalid Date并配有可逆的 unmapper 用于 shrink。若你的被測(cè)代碼無(wú)法處理 Invalid Date顯式加回約束即可-fc.date(); fc.date({ noInvalidDate: true });record / dictionary 默認(rèn)包含 null 原型。v3 時(shí)代這兩個(gè) arbitrary 生成的對(duì)象總繼承自常規(guī)Object原型v4 起默認(rèn)行為改為可能是 null 原型對(duì)象。如果代碼要求對(duì)象必須有常規(guī)原型可將noNullPrototype置為true該選項(xiàng)自 3.13.0 引入v3 中默認(rèn)是truev4 中反轉(zhuǎn)為 falsefc.dictionary(fc.string(), fc.string(), { noNullPrototype: true, // 其他約束如有... }); fc.record(recordModel, { noNullPrototype: true, });與之配套的是字符串化輸出的精簡(jiǎn)見下文高級(jí)用戶變化中的 serializer 一節(jié)null 原型對(duì)象現(xiàn)在序列化得更短。2. 統(tǒng)一的字符串構(gòu)建器4.0.0 將歷史上按字符集拆分的多個(gè)字符串 arbitrary 合并為單一的string通過unit約束指定字符來(lái)源。從 string.ts 的源碼可以確認(rèn)unit的完整取值范圍graphemeUnicode 標(biāo)準(zhǔn)定義的可打印字位grapheme可跨多個(gè)碼點(diǎn)依賴 Unicode 15 規(guī)范grapheme-composite限定為單個(gè)碼點(diǎn)的可打印字位grapheme-ascii可打印 ASCII 字符這也是unit的默認(rèn)值defaultValue grapheme-asciibinaryUnicode 全范圍內(nèi)0000-10FFFF的任意碼點(diǎn)不含半代理對(duì)binary-ascii0000-00FF 范圍內(nèi)任意 ASCII 碼點(diǎn)含控制字符或者傳入一個(gè)自定義的Arbitrarystring作為單元。值得注意發(fā)布說明明確提到團(tuán)隊(duì)把給字符串也強(qiáng)制更智能默認(rèn)值的計(jì)劃推遲到了 v5在 v4 中字符串默認(rèn)行為保持兼容后續(xù)會(huì)提供更多在 arbitrary 級(jí)別覆蓋默認(rèn)值的手段。3. 更精細(xì)的調(diào)度器fast-check 自 1.20.0 起提供檢測(cè)競(jìng)態(tài)條件的調(diào)度器原語(yǔ)。v3 的實(shí)現(xiàn)存在兩個(gè)問題比預(yù)期更慢且允許在兩個(gè)已調(diào)度任務(wù)之間插入并執(zhí)行中間任務(wù)導(dǎo)致出現(xiàn)測(cè)試通過但新增微任務(wù)后失敗的不一致場(chǎng)景。v4 對(duì)調(diào)度器做了重寫Refactor: Rewrite ofscheduleSequence使任務(wù)只有在預(yù)期時(shí)刻確實(shí)存在時(shí)才會(huì)被調(diào)度行為更可預(yù)測(cè)。遷移指南中的示例清楚地展示了行為差異。設(shè)s為一個(gè) scheduler 實(shí)例s.schedule(Promise.resolve(1)).then(async () { await something already resolved; s.schedule(Promise.resolve(2)); }); await s.waitAll();在 v3 中waitAll()結(jié)束時(shí)所有已調(diào)度任務(wù)包括Promise.resolve(2)都會(huì)被執(zhí)行而在 v4 中Promise.resolve(2)仍處于 pending 狀態(tài)——因?yàn)閣aitAll循環(huán)處理到await處就恢復(fù)了等待序列而第二個(gè)任務(wù)此時(shí)尚未被調(diào)度、對(duì)調(diào)度器而言仍是未知的。遷移指南還給出了對(duì)照如果示例中在調(diào)度第二個(gè)任務(wù)前多寫幾次awaitv3 的行為又會(huì)變回與 v4 一致即 v3 的行為取決于await數(shù)量本身就不一致v4 消除了這類邊緣場(chǎng)景下的意外。從當(dāng)前源碼看這一更精細(xì)的方向在 4.0.0 之后繼續(xù)演進(jìn)Scheduler.ts 接口 中waitOne/waitAll已被標(biāo)記deprecated分別推薦改用waitNext(1)與waitIdle()二者自 4.2.0 引入并保留waitFor(promise)用于等待某個(gè)特定任務(wù)。官方建議按場(chǎng)景選擇任務(wù)數(shù)已知用waitNext(n)等待所有已調(diào)度及可達(dá)任務(wù)全部落定用waitIdle()等待某個(gè)具體 Promise即使尚未調(diào)度用waitFor(promise)。破壞性變更全清單與遷移方法發(fā)布說明列出了自 3.23.2 以來(lái)的全部 20 項(xiàng) Breaking Changes這里按主題歸類并給出源碼可驗(yàn)證的替代方案。移除的字符串類 arbitraryascii*、hexa*、base64、stringOf、char16bits/string16bits、fullUnicode*、unicode*、char單字符 arbitrary 就是長(zhǎng)度為 1 的字符串這是官方移除它們的核心理由。遷移指南from-3.x-to-4.x.md為每個(gè)被移除的 API 提供了可直接復(fù)用的重寫函數(shù)// ascii / asciiString function ascii(): fc.Arbitrarystring { return fc.string({ unit: binary-ascii, minLength: 1, maxLength: 1 }); } function asciiString(constraints: Omitfc.StringConstraints, unit {}): fc.Arbitrarystring { return fc.string({ ...constraints, unit: binary-ascii }); } // char function char(): fc.Arbitrarystring { return fc.string({ unit: grapheme-ascii, minLength: 1, maxLength: 1 }); } // hexa / hexaString function hexa(): fc.Arbitrarystring { const items 0123456789abcdef; return fc.integer({ min: 0, max: 15 }).map((n) items[n]); } function hexaString(constraints: Omitfc.StringConstraints, unit {}): fc.Arbitrarystring { return fc.string({ ...constraints, unit: hexa() }); } // fullUnicode / fullUnicodeString function fullUnicode(): fc.Arbitrarystring { return fc.string({ unit: binary, minLength: 1, maxLength: 1 }); } function fullUnicodeString(constraints: Omitfc.StringConstraints, unit {}): fc.Arbitrarystring { return fc.string({ ...constraints, unit: binary }); } // char16bits / string16bits function char16bits(): fc.Arbitrarystring { return fc.nat({ max: 0xffff }).map((n) String.fromCharCode(n)); } function string16bits(constraints: Omitfc.StringConstraints, unit {}): fc.Arbitrarystring { return fc.string({ ...constraints, unit: char16bits() }); }對(duì)于unicode/unicodeString僅限 BMP 的字符集遷移指南還特別提醒如果你當(dāng)初選unicode只是為了支持 Unicode很可能你真正需要的是fullUnicode全 Unicode 范圍。base64的替代是字符集枚舉fc.constantFrom展開 64 個(gè)字符帶可逆 unmapper 的進(jìn)階寫法見遷移指南的 Advanced rewriting 折疊塊。注意fc.base64String()被保留了——因?yàn)樗磉_(dá)的語(yǔ)義合法的 base64 編碼串超出了base64 字符的字符串。stringOf則直接改為fc.string({ unit: ... })-fc.stringOf(fc.constantFrom(Hello, World)); fc.string({ unit: fc.constantFrom(Hello, World) });uuid版本范圍擴(kuò)展到 v1–v8uuidV 被移除v3 的uuid只生成 v1–v5v4 擴(kuò)展默認(rèn)值到 v1–v8。從 uuid.ts 源碼確認(rèn)version缺省時(shí)取[1, 2, 3, 4, 5, 6, 7, 8]而約束類型允許 1–15 的單個(gè)版本或版本數(shù)組依據(jù) RFC 9562 的 version 字段定義。如果你的代碼只依賴 v1–v5可以顯式寫回-fc.uuid(); fc.uuid({ version: [1, 2, 3, 4, 5] });uuidV(n)自 3.21.0 起由uuid的version約束替代現(xiàn)已移除-fc.uuidV(4); fc.uuid({ version: 4 });.noBias / .noShrink 方法移除改用獨(dú)立 arbitrary這兩個(gè)方法自 3.20.0 起棄用v4 移除方法形式只保留同名獨(dú)立 arbitrary。從 noBias.ts 與 noShrink.ts 的實(shí)現(xiàn)可以看到兩者均為包裝器NoBiasArbitrary在generate時(shí)把 biasFactor 恒置為undefined禁用偏向NoShrinkArbitrary的shrink恒返回空迭代器且兩者都帶冪等檢查——重復(fù)包裹同一實(shí)例會(huì)直接返回原對(duì)象。-myArbitrary.noBias(); fc.noBias(myArbitrary); -myArbitrary.noShrink(); fc.noShrink(myArbitrary);big{U|}int{N|} 移除統(tǒng)一收斂到 fc.bigIntfc.bigIntN、fc.bigUintN、fc.bigUint被移除統(tǒng)一替換為fc.bigInt。需要時(shí)可自行重寫遷移指南給出的實(shí)現(xiàn)function bigIntN(n: number): fc.Arbitrarybigint { return fc.bigInt({ min: 1n BigInt(n - 1), max: (1n BigInt(n - 1)) - 1n }); } function bigUintN(n: number): fc.Arbitrarybigint { return fc.bigInt({ min: 0n, max: (1n BigInt(n)) - 1n }); } function bigUint(max: bigint (1n 256n) - 1n): fc.Arbitrarybigint { return fc.bigInt({ min: 0n, max }); }unicodeJson* 移除收斂到 json / jsonValueunicodeJson與unicodeJsonValue被json/jsonValue的stringUnit約束取代不再按字符集維護(hù)多套 API-fc.unicodeJson(); fc.json({ stringUnit: binary }); // 或 grapheme -fc.unicodeJsonValue(); fc.jsonValue({ stringUnit: binary }); // 或 graphemerecord 的 withDeletedKeys 徹底移除withDeletedKeys自 2.11.0 起被requiredKeys取代并標(biāo)記棄用v4 徹底移除fc.record(recordModel, { - withDeletedKeys: true, requiredKeys: [], }); fc.record(recordModel, { - withDeletedKeys: false, });Random.nextArrayInt 移除此項(xiàng)只影響手工實(shí)現(xiàn)Arbitrary接口的高級(jí)用戶。官方建議改用nextBigInt獲取大數(shù)值隨機(jī)量。Node ≥12.17.0 強(qiáng)制化對(duì)應(yīng) PR#5821構(gòu)建產(chǎn)物目標(biāo)從 ES2017 提升到 ES2020見下文工程化小節(jié)engines 聲明隨之收緊。新特性更好的類型推斷與類型簡(jiǎn)化4.0.0 的 Features 部分包含四項(xiàng)類型層改進(jìn)最直觀的是constant/constantFrom的推斷方向反轉(zhuǎn)// v3 fc.constant(a); // Arbitrarystring fc.constanta(a); // Arbitrarya // v4 fc.constant(a); // Arbitrarya字面量自動(dòng)推斷 fc.constantstring(a); // Arbitrarystring顯式指定才放寬constantFrom同理fc.constantFrom(a, b)現(xiàn)在直接推斷為Arbitrarya | b。另外兩項(xiàng)是ArbitraryXxxArray類型統(tǒng)一為ArbitraryXxxArrayArrayBuffer以及fc.record類型的簡(jiǎn)化。錯(cuò)誤報(bào)告新機(jī)制默認(rèn)使用 Error causev4 改用了標(biāo)準(zhǔn) Error Cause 機(jī)制當(dāng)謂詞拋出Error時(shí)fast-check 不再把失敗詳情拼進(jìn)新 Error 的 message而是把你的原始 Error 作為cause掛載上去便于測(cè)試運(yùn)行器解析消息與堆棧。想恢復(fù)舊行為在 v4 中打開includeErrorInReport參數(shù)即可v3 中該開關(guān)叫errorWithCausev4 更名。這一點(diǎn)在源碼中可確認(rèn)Parameters.ts 定義了includeErrorInReport?: booleanRunDetailsFormatter.ts 根據(jù)該標(biāo)志決定 message 是否拼接原始錯(cuò)誤Runner.spec.ts 中有對(duì)應(yīng)的行為測(cè)試。工程化與性能改進(jìn)發(fā)布說明的 Fixes 部分包含大量工程項(xiàng)可歸納為幾條主線構(gòu)建鏈遷移到 ESM產(chǎn)物目標(biāo) ES2020。當(dāng)前倉(cāng)庫(kù)中構(gòu)建統(tǒng)一走 rolldownrolldown.common.config.js主產(chǎn)物為format: esm且配置了treeshake: { moduleSideEffects: false }package.json 中同樣聲明sideEffects: false。這正是 changelog 中 Mark all arbitraries as side-effect free 兩項(xiàng)落地的形態(tài)使打包器可以對(duì) fast-check 做更徹底的 tree-shaking。依賴管理從 yarn 切換到 pnpm倉(cāng)庫(kù)根目錄可見pnpm-workspace.yaml與pnpm-lock.yamlCI 命令切換到node --run、CI 作業(yè)遷移到 Node 22。一系列生成路徑上的性能優(yōu)化property::run采用嚴(yán)格相等判斷加速、無(wú) cause 時(shí)延遲計(jì)算 Error stack、scheduleSequence調(diào)度加速、競(jìng)態(tài)調(diào)度器提速、double重寫提速、ipV6使用緩存字符串構(gòu)建器、runner 參數(shù)與object約束讀取提速等。關(guān)鍵 bug 修復(fù)scheduleSequence的拒絕rejection處理更完善json對(duì)外部原型污染poisoning具備抵抗力倉(cāng)庫(kù)中還有配套的 packages/poisoning 檢測(cè)包與mixedCase中冗余 BigInt 檢查的移除。面向高級(jí)用戶的破壞性變更遷移指南的 Advanced usages 一節(jié)面向自定義 reporter、自定義Arbitrary/runner 的實(shí)現(xiàn)者包含四項(xiàng)需要留意的變化RunDetails 移除error字段fc.check返回結(jié)果中不再提供error字符串字段請(qǐng)改用 v3.0.0 引入的errorInstance。這與上文 Error cause 機(jī)制配套延遲計(jì)算 Error stack 也帶來(lái)相應(yīng)收益。IRawProperty執(zhí)行器必須顯式調(diào)用runBeforeEach/runAfterEach自定義屬性 runner自實(shí)現(xiàn)的fc.assert/fc.check替代物需要顯式驅(qū)動(dòng)這兩個(gè)鉤子v3 中可以通過 run 方法的第二個(gè)參數(shù)傳true提前適配。序列化器輸出變更null 原型對(duì)象的 stringify 結(jié)果從Object.create(null)/Object.assign(Object.create(null),{a:1})改為更短的{__proto__:null}/{__proto__:null,a:1}。從 stringify.ts 可見其實(shí)現(xiàn)Object.getPrototypeOf(value) null時(shí)插入__proto__:null鍵且 stringify.spec.ts 中固化了這些快照斷言。依賴自定義上報(bào)/序列化格式的用戶需要留意。CommandWrapper / CommandsIterable 的 Symbol 方法不再出現(xiàn)在類型聲明中toStringMethod、asyncToStringMethod、cloneMethod這些符號(hào)方法在運(yùn)行時(shí)依然存在但 TypeScript 類型中不再暴露對(duì)應(yīng) CI 層面的isolatedDeclarations啟用。升級(jí)行動(dòng)清單結(jié)合發(fā)布說明與遷移指南從 v3 到 v4 的實(shí)操步驟可以濃縮為先升級(jí)至最新 3.x逐項(xiàng)搜索代碼中的棄用項(xiàng)ascii/asciiString、hexa/hexaString、base64、stringOf、char16bits/string16bits、fullUnicode/fullUnicodeString、unicode/unicodeString、char、uuidV、unicodeJson/unicodeJsonValue、bigIntN/bigUintN/bigUint、.noBias()、.noShrink()、withDeletedKeys按遷移指南給出的重寫函數(shù)逐一替換評(píng)估默認(rèn)行為反轉(zhuǎn)確認(rèn)fc.date()Invalid Date、fc.record/fc.dictionary/fc.objectnull 原型、fc.uuid()v6–v8的新默認(rèn)值是否可接受不能接受的地方顯式加回noInvalidDate: true、noNullPrototype: true、version: [1, 2, 3, 4, 5]切換錯(cuò)誤上報(bào)習(xí)慣默認(rèn)改為 Error cause 掛載需要舊式拼接消息時(shí)打開includeErrorInReport檢查環(huán)境基線Node ≥12.17.0、ES2020、TypeScript ≥5.0自定義實(shí)現(xiàn)者自查RunDetails.error字段、IRawProperty鉤子調(diào)用、Command 相關(guān)的 Symbol 類型引用。完成以上步驟后遷移指南的結(jié)論是切換到 v4 應(yīng)當(dāng)是直接的should be straightforward因?yàn)槭S嗟淖兏词欠瞧茐牡脑鰪?qiáng)類型推斷、性能要么是面向高級(jí)使用場(chǎng)景的行為收緊調(diào)度器更精確、序列化更短。贊分享開發(fā)工具測(cè)試【免費(fèi)下載鏈接】fast-checkProperty based testing framework for JavaScript (like QuickCheck) written in TypeScript項(xiàng)目地址https://gitcode.com/gh_mirrors/fa/fast-check點(diǎn)擊查看免費(fèi)下載相關(guān)推薦CoffeeScript 0.5.5 發(fā)布解析字符串插值語(yǔ)法與命令行默認(rèn)行為變更指南CoffeeScript 0.5.5 發(fā)布解析字符串插值語(yǔ)法與命令行默認(rèn)行為變更指南 本篇文章圍繞 CoffeeScript 0.5.5發(fā)布于 2010 0編程語(yǔ)言編譯器抖音去水印批量下載免費(fèi)工具博主200條作品20分鐘下完抖音去水印批量下載免費(fèi)工具博主200條作品20分鐘下完 上周三做競(jìng)品復(fù)盤老板甩給我一個(gè)博主主頁(yè)鏈接讓我把他發(fā)的都存下來(lái)。換以前我得一整下午對(duì)著網(wǎng)頁(yè)復(fù)制網(wǎng)頁(yè)爬蟲CLIfast-check 3.9.0 發(fā)布解讀細(xì)粒度 act 讓競(jìng)態(tài)條件檢測(cè)更精準(zhǔn)fast check 3.9.0 發(fā)布解讀細(xì)粒度 act 讓競(jìng)態(tài)條件檢測(cè)更精準(zhǔn) 本篇技術(shù)指南圍繞 fast check 3.9.0 版本的核心更新展開它把調(diào)開發(fā)工具測(cè)試上一篇預(yù)約發(fā)送不遲到Simple SMS Messenger 定時(shí)消息功能使用教程下一篇終極指南如何用F_Record插件一鍵錄制Photoshop繪畫全過程創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考