成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網
最全最豐富的資訊網站

詳解構建可運行的JavaScript規范的方法

詳解構建可運行的JavaScript規范的方法

編程不僅僅是給計算機下達如何完成一項任務的指令,它還包括以一種精確的方式與他人交流思想,甚至是與未來的自己。這樣的交流可以有多個目標,也許是為了共享信息,或者只是為了更容易地修改—如果你不理解或不記得很久以前做過什么,那么就很難修改。

當我們編寫軟件時,我們還需要確保代碼具有預期的功能。雖然有定義語義的正式方法,但是最簡單、最快速(但不那么嚴格)的方法是將該功能投入使用,并查看它是否產生預期的結果。

大多數開發人員都熟悉這些實踐:代碼文檔作為注釋來明確代碼塊的目標,以及一系列測試來確保函數給出所需的輸出。

但是通常文檔和測試是在不同的步驟中完成的。通過統一這些實踐,我們可以為參與項目開發的任何人提供更好的體驗。本文探討了一個簡單的程序實現,該程序可以運行既適用于文檔編寫又適用于測試的JavaScript規范。

我們將構建一個命令行界面,該界面將查找目錄中的所有規范文件,提取每個規范中找到的所有斷言,并計算它們的結果,最后顯示哪些斷言失敗了,哪些斷言通過了。

規范的格式

每個規范文件將從模板文本導出一個字符串。第一行可以作為規范的標題。模板文字將允許我們在字符串之間嵌入JS表達式,每個表達式將表示一個斷言。要識別每個斷言,我們可以用一個獨特的字符開始行。

在本例中,我們可以使用bar字符(|)和破折號(-)的組合,破折號類似于旋轉門符號,有時可以將其作為邏輯斷言的符號表示。

下面是一個例子,對它的用法做了一些解釋:

const dependency = require('./dependency')module.exports = `   Example of a Specification File      This project allows to test JavaScript programs using specification files.   Every *.spec.js file exports a single template literal that includes a general   explanation of the file being specified. Each file represents a logical   component of a bigger system. Each logical component is composed of several   units of functionality that can be tested for certain properties.   Each one of this units of functionality may have one or more   assertions. Each assertion is denoted by a line as the following:    |- ${dependency} The dependency has been loaded and the first assert has   been evaluated.    Multiple assertions can be made for each file:    |- ${false} This assertion will fail.    |- ${2 + 2 === 4} This assertion will succeed.    The combination of | and - will form a Turnstile ligature (|-) using the appropriate   font. Fira Code is recommended. A Turnstile symbol was used by Gottlob Frege   at the start of sentenses being asserted as true.    The intended usage is for specification-first software. Where the programmer   defines the high level structure of a program in terms of a specification,   then progressively builds the parts conforming that specification until all   the tests are passed. A desired side-effect is having a simple way to generate   up-to-date documentation outside the code for API consumers. `

現在讓我們繼續我們程序的高層結構。

我們程序的結構

我們的程序的整個結構可以在幾行代碼中定義,除了使用兩個Node.js庫來處理文件系統(fs)和目錄路徑(path)之外,沒有任何依賴關系。在本節中,我們只定義程序的結構,函數定義將在下一節中給出。

#!/usr/bin/env node const fs = require('fs') const path = require('path') const specRegExp = /.spec.js$/ const target = path.join(process.cwd(), process.argv[2]) // Get all the specification file paths // If a specification file is provided then just test that file // Otherwise find all the specification files in the target directory const paths = specRegExp.test(target)   ? [ target ]   : findSpecifications(target, specRegExp).filter(x => x) // Get the content of each specification file // Get the assertions of each specification file const assertionGroups = getAssertions(getSpecifications(paths)) // Log all the assertions logAssertions(assertionGroups)   // Check for any failed assertions and return an appropriate exit code process.exitCode = checkAssertions(assertionGroups)

因為這也是我們的CLI(命令行接口)的入口點,所以我們需要添加第一行shebang,它表示這個文件應該由節點程序執行。不需要添加特定的庫來處理命令選項,因為我們只對單個參數感興趣。但是,如果您計劃以相當大的方式擴展此程序,則可以考慮其他選項。

要獲得目標測試文件或目錄,我們必須將執行命令的路徑(使用process.cwd())與用戶提供的參數作為執行命令時的第一個參數(使用process.argv[2])連接起來。

您可以在process對象的Node.js文檔中找到對這些值的引用。通過這種方法,我們獲得了目標目錄/文件的絕對路徑。

現在,我們要做的第一件事是找到所有的JavaScript規范文件。如第12行所示,我們可以使用條件運算符來提供更大的靈活性:如果用戶提供了一個規范文件作為目標然后我們就直接使用,文件路徑。

否則,如果用戶提供了一個目錄路徑然后我們必須找到相匹配的所有文件模式specRegExp定義的常數,我們使用findSpecifications函數以后,我們將定義。這個函數將返回目標目錄中每個規范文件的路徑數組。

在第18行中,我們通過組合兩個函數getspecification()和getassertion()來定義assertionGroups常量。首先獲取每個規范文件的內容,然后從中提取斷言。

我們稍后將定義這兩個函數,現在只需要注意,我們使用第一個函數的輸出作為第二個函數的參數,從而簡化了過程,并在這兩個函數之間建立了直接的聯系。

雖然我們可以只有一個函數,通過拆分它們,我們可以更好地了解什么是實際的過程,但請記住,程序應該清晰易懂;僅僅做到這一點是不夠的。

assertionsGroup常量的結構如下:

assertionGroup[specification][assertion]

接下來,我們將所有這些斷言記錄到用戶日志中,以便使用logassertion()函數報告結果。每個斷言將包含結果(true或false)和一個小描述,我們可以使用該信息為每種類型的結果賦予特殊的顏色。

最后,我們根據斷言的結果定義退出代碼。這將向流程提供關于程序如何結束的信息:流程是成功的還是失敗了?退出碼為0表示進程成功退出,如果失敗則為1,或者在我們的示例中,當至少一個斷言失敗時為1。

查找所有規范文件

要找到所有的JavaScript規范文件,我們可以使用一個遞歸函數,該函數遍歷用戶作為CLI參數指定的目錄。在搜索時,應該使用程序開始時定義的正則表達式(/.spec.js$/)檢查每個文件,該表達式將匹配以.spec.js結尾的所有文件路徑。

function findSpecifications (dir, matchPattern) {   return fs.readdirSync(dir)     .map(filePath => path.join(dir, filePath))     .filter(filePath => matchPattern.test(filePath) && fs.statSync(filePath).isFile()) }

我們的findspecification函數接受一個目標目錄(dir)和一個正則表達式,該正則表達式標識規范文件(matchPattern)。

獲取每個規范的內容

由于我們導出的是模板文本,因此獲取內容和計算后的斷言非常簡單,因此我們必須導入每個文件,當它被導入時,所有的斷言都將自動進行計算。

function getSpecifications (paths) {   return paths.map(path => require(path)) }

使用map()函數,我們使用節點的require函數將數組的路徑替換為文件的內容。

從文本中提取斷言

此時,我們有一個數組,其中包含每個規范文件的內容,并且已經計算了它們的斷言。我們使用旋轉門指示器(|-)來查找所有這些斷言并提取它們。

function getAssertions (specifications) {   return specifications.map(specification => ({     title: specification.split('nn', 1)[0].trim(),     assertions: specification.match(/^( |t)*(|-)(.|n)*?./gm).map(assertion => {       const assertionFragments = /(?:|-) (w*) ((?:.|n)*)/.exec(assertion)         return {         value: assertionFragments[1],         description: assertionFragments[2].replace(/n /, '')       }     })   })) }

這個函數將返回一個類似的數組,但是用一個如下結構的對象替換每個規范的內容:

title: <String: Name of this particular specification>,   assertions: [     {       value: <Boolean: The result of the assertion>,       description: <String: The short description for the assertion>     }   ] }

標題是用規范字符串的第一行設置的。然后,每個斷言都作為數組存儲在斷言鍵中。該值將斷言的結果表示為布爾值。我們將使用這個值來知道斷言是否成功。

此外,描述將顯示給用戶,作為識別哪些斷言成功和哪些斷言失敗的方法。我們在每種情況下都使用正則表達式。

記錄結果

我們沿著程序構建的數組現在有一系列JavaScript規范文件,其中包含一列找到的斷言及其結果和描述,因此除了向用戶報告結果之外,沒有什么可做的。

{   function logAssertions(assertionGroups) {   // Methods to log text with colors   const ansiColor = {     blue: text => console.log(`x1b[1mx1b[34m${text}x1b[39mx1b[22m`),     green: text => console.log(`x1b[32m    ${text}x1b[39m`),     red: text => console.log(`x1b[31m    ${text}x1b[39m`)   }   // Log the results   assertionGroups.forEach(group => {     ansiColor.blue(group.title)     group.assertions.forEach(assertion => {       assertion.value === 'true'         ? ansiColor.green(assertion.description)         : ansiColor.red(assertion.description)     })   })     console.log('n') }

我們可以根據結果使用顏色來格式化輸入。為了在終端上顯示顏色,我們需要添加ANSI轉義碼。為了在下一個塊中簡化它們的用法,我們將每種顏色保存為ansiColor對象的方法。

首先,我們要顯示規范的標題,請記住,我們為每個規范使用數組的第一個維度,并將其命名為一組(斷言)。然后,我們使用它們各自的顏色根據它們的值記錄所有斷言:綠色表示計算為true的斷言,紅色表示具有其他值的斷言。

注意比較,我們檢查true是否為字符串,因為我們從每個文件接收字符串。

檢查結果

最后,最后一步是檢查所有測試是否成功。

function checkAssertions (assertionGroups) {   return assertionGroups.some(     group => group.assertions.some(assertion => assertion.value === 'false')   ) ? 1 : 0 }

我們使用數組的some()方法檢查每個斷言組(規范),看看是否至少有一個值是' ' ' false ' ' '。我們嵌套了其中的兩個因為我們有一個二維數組。

運行我們的程序

此時,我們的CLI應準備好運行一些JavaScript規范,并查看是否拾取并評估了斷言。在test目錄中,您可以從本文開頭復制規范示例,并將以下命令粘貼到您的文件中:package.json

"scripts": {   "test": "node index.js test"   }

其中test是包含示例規范文件的目錄的名稱。

當運行npm test命令時,您應該看到使用它們各自顏色的結果。

相關免費學習推薦:js視頻教程

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
浪潮AV激情高潮国产蜜臀| 天干天干夜天干天天爽| 性猛交ⅩXXX富婆video| 一本一道AV中文字幕无码| 啊宝宝的扇贝真会夹C视频 | FREEXXXPORN中国女人| 国产精品国产三级国产专I| 久久久久久亚洲AV无码专区| 日本人妻丰满大屁股a v| 亚洲加勒比少妇无码AV| 锕锕锕锕锕锕锕好疼免费视频| 国产在线乱码一区二区三区| 一区二区三区熟女少妇小牛| 成人区人妻精品一区二区网站| 狠狠色噜噜狠狠狠狠色综合网| 欧美人与动牲交片免费| 亚洲AV噜噜在线成人网站| 99久久久国产精品免费| 国精产品一区二区三区有限公司 | ASS年轻少妇PIC精品| 国产免费人成视频在线播放播| 免费人成在线观看视频无码| 无码中文字幕AV久久专区| 7777久久亚洲中文字幕蜜桃| 国精产品一区一区三区M| 人人爽人人片人人片AV| 亚洲熟妇另类AV老熟女| 公侵犯人妻一区二区三区四区 | 中文精品久久久久人妻| 国产精品自在线拍国产电影| 欧美精品成人久久AV爱乃娜美| 亚洲AV无码一区二区三区性色 | 妺妺坐在我腿上勃起弄了应用| 午夜理论片免费播放| V与子敌伦刺激对白播放| 久久精品露脸对白国产| 少妇又紧又色又爽又刺激视频| 中文在线ずっと好きだった| 国产又猛又黄又爽| 日韩系列精品无码免费不卡| 中国WINDOWS野外| 好男人在在线社区WWW在线影院| 日本一道综合久久AⅤ免费| 伊人丁香狠狠色综合久久| 国产精品无码无片在线观看3D| 欧美日韩人妻一区二区| 野花香在线观看免费观看大全动漫 | 久久99国产精品成人| 完全着衣の爆乳お姉さんが| YSL水蜜桃86| 老师你的好软水好多的时候图片| 性偷窥TUBE凸凹视频| 大帝A∨无码视频在线播放| 美女内射毛片在线看免费人动物| 亚洲AV综合色区无码4区| 国产成人精品一区二区视频 | 成人欧美一区二区三区视频| 女人被弄高潮视频免费| 野花视频免费观看| 狠狠色综合7777久夜色撩人 | 播放灌醉水嫩大学生国内精品| 麻花豆传媒MV在线播放| 亚洲精品国产成人精品| 国产乱子伦一区二区三区| 日韩国产成人无码AV毛片蜜柚| 7777精品久久久大香线蕉| 久久久综合九色合综| 亚洲国产天堂久久综合226| 国产美女精品AⅤ在线| 熟妇的滚烫的肉唇翻进翻出| 超薄丝袜足J好爽在线观看| 欧美成人精品在线观看| 中文字幕无码成人免费视频| 久久国产亚洲精品无码| 亚洲成A人片在线观看无遮挡| 国产老妇女婬片A级毛片| 熟妇啊轻点灬大JI巴太粗| 不卡无在一区二区三区四区| 漂亮人妻沦陷精油按摩| 99精品国产兔费观看久久 | 亚洲乱码一区二区三区| 国产曰的好深好爽免费视频| 无码熟熟妇丰满人妻啪啪喷水| 国产AV无码区亚洲| 十八禁啪啪污污网站免费下载| 成人免费A级毛片无码片2022| 强开小婷嫩苞又嫩又紧视频| CAOPORN最新地址| 欧美人与性囗牲恔配视频| av 成人 亚洲无码| 欧美日日日日BBBBB视频| 99久久精品无码专区| 欧美高大丰满FREESEX| 99热精国产这里只有精品| 欧美多人片高潮野外做片黑人| 97久久欧美极品少妇XXXXⅩ| 欧美 狠狠操 888| AV色欲无码人妻中文字幕| 欧美日韩久久中文字幕| 拔萝卜视频免费播放在线观看| 人妻丰满熟妇av无码区免费蜜臀| ZZIJZZIJ亚洲日本少妇| 日本无人区一线影视| 绯色AV一区二区三区在线高清| 色综合天天无码网站| 国产AV免费一区二区三区| 无码日韩人妻精品久久| 国产一区二区三区不卡在线观看| 亚洲AV无码成人网站国产网站| 国内偷窥一区二区三区视频| 亚洲国产精品尤物YW在线观看| 精品无人区麻豆乱码无限制 | 白嫩极品女粉嫩喷水视频的| 人人爽人人澡人人人妻、百度| 成年女人A级毛片免费观看| 十八款夜间禁用APP| 国产乱码精品一区二区三区四川人 | 亚洲XXX午休国产熟女屁| 久久精品国产99精品亚洲蜜桃| 又粗又大又硬又爽的少妇毛片| 免费A级毛片无码A∨奶水在线| 99国产欧美久久久精品蜜桃| 人妻中出无码一区二区三区| 高潮白浆潮喷正在播放| 亚州熟妇无码AV线播放| 久久国产精品77777| 主人地下室惩罚骚奴的法律后果| 欧美老熟妇XB水多毛多| 绯色av一区二区| 西西顶级艺术WWW日本超大胆| 好深啊太粗好烫撑满了| 曰本A级毛片无卡免费视频| 欧美中日韩免费观看网站| 丰满熟女一区二区三区蜜桃臀 | 婷婷俺也去俺也去官网| 黑人上司与人妻激烈中文字幕| 一边做一边喷17P| 欧洲精品码一区二区三区| 国产成人精品一区二区三区| 亚洲精品无码成人片久久| 免费三级现频在线观看免费| 草莓影视在线观看视频| 性欧美GAYSEⅩ| 浪潮AV激情高潮国产蜜臀| 波多野结衣AV无码久久一区| 无码专区中文字幕无码野外| 九月在线 视频 在线观看| 99久久无色码中文字幕人妻蜜柚| 四虎永久在线精品无码视频| 精品国产你懂的在线观看| 99国产精品久久久蜜芽| 天天AV天天翘天天综合网 | 亚洲AV成人一区二区三区在线观| 久久人妻少妇偷人精品综合桃色| AV色蜜桃一区二区三区| 午夜精品射精入后重之免费观看| 久久亚洲国产成人精品性色| 成 人片 黄 色 大 片| 亚洲А∨天堂久久精品PPYPP| 你日的我走不了路了| 国产高潮抽搐翻白眼在线播放| 亚洲熟女综合一区二区三区| 人妻有码ΑV中文字幕久久琪琪布| 国产偷窥熟女高潮精品视频| 中文精品无码中文字幕无码专区 | 99精品无人区乱码1区2区3区| 天天爽夜夜爽人人爽| 久青草国产97香蕉在线影院| 大黑大巴大战欧洲美女图片| 亚洲精品中文字幕久久久久| 人妻熟妇久久久久久XXX| 和丰满少妇作爱过程视频| JAPANESE娇小侵犯| 亚洲AV无码乱码国产精品FC2| 欧美成人精品午夜免费影视| 国产三级精品三级在专区| 18禁白丝JK自慰喷水无码| 无码人妻丰满熟妇区毛片18| 没带罩子让他捏了一节课 | 国产高潮刺激叫喊视频| 中国CHAIN同志GAY片国产| 无码动漫性爽XO视频在线观看不| 免费观看电视在线高清| 国产六月婷婷爱在线观看| 97精品伊人久久大香线蕉APP| 小怡的暴露耻辱系列小说| 女人18毛片A级毛片免费视频| 国产午夜精品一区二区三区极品| AV无码一区二区大桥未久| 亚洲AV无码性色AV无码网站| 人禽杂交18禁网站免费| 久久九九兔免费精品6| 国产JJIZZ女人多水| 18禁止福利午夜体验试看| 亚洲AV日韩AV永久无码电影| 日本入室强伦姧在线观看| 久久理伦片琪琪电影院| 国产精品美女被操| 爱丫爱丫影院在线观看免费| 一区二区日韩视频|