發表文章

讀書心得#重構JavaScript 3.1.1 測試覆蓋率 Coverage

圖片
測試的術語 3.1.1 測試覆蓋率 Coverage 測試覆蓋率以百分比表示,用來測量有多少行程式碼已經被 測試程式 執行過。 如果你的程式碼有 4 行,但只有其中 3 行被測試程式執行過,那麼測試覆蓋率就會是 75%。剩下的 25% 可能是應該要廢棄的程式碼,或者是不屬於這個類別的工作責任,應該被移動至屬於他的地方。 以下列出多種測試覆蓋率的用途: 中文名稱 英文名稱 用途 函式覆蓋率 Function Coverage 確保每一個方法至少執行一次,且沒有發生錯誤。 行數覆蓋率 Line Coverage 確保程式每一行至少執行一次,且沒有發生錯誤。 決策覆蓋率 Decision Coverage 確保每個以真偽 (true/false) 控制程式走向的分支,至少被執行一次且沒有發生錯誤。 條件覆蓋率 Condition Coverage 確保每個分支是至少執行一次,並且沒有發生錯誤。 注意:為了滿足決策覆蓋率與條件覆蓋率有多個分支,必須針對每個分支的情境撰寫一個測試案例。 對測試覆蓋率的觀點: 覆蓋率數據只能代表你測試過哪些代碼,不能代表你是否測試好這些代碼。 不要過於相信覆蓋率數據。 測試人員不能盲目追求測試覆蓋率,而應該想辦法設計更多更好的案例,哪怕多設計出來的案例,對覆蓋率一點影響也沒有。 結論: 測試人員不應該為了滿足測試覆蓋率而撰寫測試案例,應該要以「使用情境」撰寫測試案例。 ​

讀書心得#重構JavaScript 1. 什麼是重構?

圖片
什麼是重構? 重構是一系列的等量變換 系統重構,就是在的 不改變軟體外部行為基礎上,改變軟體內部的結構 ,使其更易於閱讀、易於維護、易於擴充與易於變更。 持續不斷地對系統的內部品質進行改善與改進,就是重構的價值。 1.1 如何確保行為不被改變? Ans: 單元測試、版本控制 單元測試 進行重構之前,務必先替程式碼撰寫單元測試。確保每個方法的「 輸出結果符合預期結果 」之後,才可進行重構。 接下來 每重構一小步,就立刻執行一次單元測試 ,確認被重構的方法「行為沒有因為重構而被改變」。 只有測試通過了,這次重構才算成功! 版本控制 一般會採用 小步快跑 的方式進行重構,一次只重構一小部分,重構完馬上執行測試,測試通過後立刻上傳至 版本控制 (Git 或 SVN)。 這麼做的原因是,一但某個修改測試不通過,則還原回來。小步快跑可以讓重構的過程中,以最快速度發現修改的問題,將因重構錯誤帶來的損失減到最小! 畢竟人不可能避免犯錯:-P 1.2 為什麼我們不在意實作細節? Ans: 重構時只在乎受測程式的「輸出結果」與「預期結果」是否保持一致 。 因此,對一個物件進行測試時,只需要測試其公開方法(Public Methods),並不需要測試受保護方法(Protected Methods)與私有方法(Private Methods)。正確的設計下,測試完所有公開方法後,所有的受保護方法與私有方法都會被執行完畢。若出現沒有被執行的方法,表示該方法該被遺棄,或移動至屬於這個方法的類別。 1.3 為什麼不在意不明確且未測試的行為? Ans: 還沒確定一段程式碼的行為是否符合預期之前,不可以對其進行重構! 遇到一段行為不明確的程式碼,可以對其撰寫單元測試,利用輸入的資料與輸出結果,來理解這段程式碼的用意與行為。 當這段程式碼有單元測試保護的情況下,才可對其進行重構。 1.4 為什麼不關注效能? Ans:一般來說, 不會在剛開始重構的階段就去在意效能,只在意程式碼是否有保持正確的輸出 。 但是如果一個實作在太慢,我們就有必要先修改實作了! 如何對效能進行測試?透過 Benchmarking 套件,可以將執行函式的時間點當作「輸入」,並將運作完成的時間當作「輸出」。取時時間差回

單元測試法則

圖片
單元測試法則 What should we test? Incoming & Outgoing Messages 上圖表示一個物件是如何被測試的。 測試物件的時候,你可以發現受測物件會 接收 與 發送 訊息: Incoming Messages 表示呼叫受測物件的訊息 Outgoing Messages  表示受測物件 傳遞 給其依賴物件的訊息 訊息可以被傳進物件,也會被物件傳遞出去(如上圖你可以看見有訊息進入物件,也有訊息從物件出去)。 進行測試時,你只能對物件傳遞訊息,沒有辦法看見物件的內部。這就是為什麼要 測試介面,不要測試實作。 (testing the interface, and NOT the implementation.) 測試介面讓我們可以隨意切換實作類別,並且不破壞測試程式。 Query & Command Messages 除了 Incoming & Outgoing Messages 以外,訊息還分為 Query 與 Command 兩種: Query Message: messages return data without changing anything. 只返回 Data,不做修改任何物件屬性的訊息 不會替應用程式帶來副作用。 Command Message: messages modify data without returning any data. 只修改物件屬性,但不返回任何 Data 訊息 一定會有副作用。 合併的 Command 與 Query 訊息: 這種訊息除了修改資料與回傳資料外,還可能有隱藏的副作用。 (如新增一筆 user 資料並返回新的 user ID,但是 DB 內的 ID 自動 +1) 在商業邏輯一定要使用合併訊息時,一定要確保這些訊息不能含有意料外的副作用。 Test Double 為什麼要 Test Double? 1. 隔離依賴: 單元測試目的是要測試受測物件的行為是否符合預期,如果連受測物件的依賴物件也一起進行測試,那就叫做 整合測試 了。 因此單元測試需要隔離依賴。 2. 要求快速: 單元測試的時間應該

JavaScript 前端測試覆蓋率

圖片
JavaScript 前端測試覆蓋率 如果您還沒建置好 JavaScript 前端測試環境,請移步至 建立 JavaScript 單元測試環境 Blanket.js 是一款易於安裝,易於配置且易於使用的 JavaScript 程式覆蓋率庫,可在瀏覽器中和與 Node.js一起使用。 除此之外也是唯一找到可以與 Mocha 前端測試搭配的套件。 Blanket.js 的使用非常簡單,只需要兩個步驟即可。 一、將 Blanket.js 添加到您的 HTML 測試文件: __注意__ mocha-blanket.js 是讓 blanket.js 可以在 mocha 測試之後產生覆蓋率的匹配器。 原始碼文件: blanket.js ,  mocha-blanket.js 二、在受測物件的檔案後方加上 data-cover 屬性 test_taskStorage.html 配置完成的樣子 配置完成,執行 test_taskStorage.html 就會自動產生測試涵蓋率的區塊: 參考文章: 前端 mocha + blanket 產生測試覆蓋率 : 前端覆蓋率套件  Blanket.js 已經失修 。有機會要找新的套件取代。

建立 JavaScript 單元測試環境

圖片
建立 JavaScript 單元測試環境 本案例使用 Mocha 單元測試框架 替專案進行測試。 GETTING STARTED 安裝 mocha $ cd 到專案根目錄 $ npm install mocha 建立測試目錄與測試程式 $ mkdir tests # 建立測試目錄 $ $EDITOR test/test.js # 在測試目錄下,使用你的編輯器建立測試程式 test.js 到目前為止,專案目錄結構如下: ├── index.html ├── node_modules # node 套件目錄 │ │ │ ├── mocha # mocha 目錄 │ │ ├── bin # mocha 執行檔目錄 │ │ │ ├── mocha # mocha 執行檔,我們就是透過這個 mocha 進行單元測試 ├── package-lock.json ├── package.json └── tests # 測試目錄,以後所有測試程式統一放在 tests 目錄下 └── test.js # 測試程式 test.js 確定測試環境已經建立 進行測試之前,一定要先確定測試環境已經建立完成,所以先隨便寫一個一定會 pass 的測試程式。 編輯 test.js 手動進行第一次測試 啟用 Mocha,第一個參數必須是 測試目錄的路徑 $ node_modules/mocha/bin/mocha tests 執行結果: 透過 npm 進行測試 如果覺得每次都要打這麼長的指令才能進行測試,也可以設定 package.json,使用 npm 進行測試。 在 package.json 的 scripts 欄位加入 "test": "mocha --recursive ./tests" 。 修改 package.json { "name": "todolist-libs", "version": &quo

建置 ECMAScript 6 開發環境

建置 ECMAScript 6 開發環境 安裝 Babel Babel 是一個廣泛使用的轉碼器,可以將 ES6 代碼轉為 ES5 代碼,從而在現有環境執行。 在專案目錄下,使用 npm 進行安裝: npm install babel-cli 配置文件.babelrc Babel 的配置文件是 .babelrc ,存放在項目的根目錄下。使用 Babel 的第一步,就是配置這個文件。 .babelrc 用來設置轉碼規則和插件,基本格式如下。 { "presets": [], "plugins": [] } presets 字段設定轉碼規則,官方提供以下的規則集,你可以根據需要安裝。 # ES2015 轉碼規則 npm install --save-dev babel-preset-es2015 # react 轉碼規則 npm install --save-dev babel-preset-react # ES7 不同階段語法提案的轉碼規則(共有 4 個階段),選裝一個 npm install --save-dev babel-preset-stage-0 npm install --save-dev babel-preset-stage-1 npm install --save-dev babel-preset-stage-2 npm install --save-dev babel-preset-stage-3 然後,將這些規則加入 .babelrc 。 { "presets": [ "es2015",` "react", "stage-2" ], "plugins": [] } 編譯 ECMAscript 6 編譯前: ES6 語法 print = (message) => { alert(message); } 編譯後: ES6 語法已經被編譯成瀏覽器可使用之 JavaScript 語法 print = function print(message) { ale

bind、apply、call

bind、apply、call apply、call、bind 三者都是用來改變函數的 this 的指向對象; apply、call、bind 三者第一個參數都是 this 要指向的對象,也就是想指定的上下文; apply、call、bind 三者都可以利用後續參數傳參; bind 是返回對應函數,便於稍後調用;apply 、call 則是立即調用。 bind 運算符 :: ES 7 新語法 :: 為 bind 的短語法,使用範例如下: 把函數綁定到變數上 var log = console.log.bind(console); 用法: log('one', '2', 3, [4], {5: 5}); 輸出: one 2 3 [4] Object {5: 5} 為什麼要綁定在變數上? 這能讓你在程式運作的時候動態決定要使用哪一種 function。 例如:你可以在程式運行時決定使用哪一個自定義記錄器: ​

PHP 傳值與傳址

物件傳值與傳址 by Value & by Reference 本章節將會學習傳值與傳址的概念(Call by value & Call by reference),以及透過實地演練來觀察兩者之間的差異。 傳値 Call by value

PHP 單元測試 第一次進行測試

圖片
再進行此章節之前,如果還沒安裝過 PHPUnit 的朋友,可以先前往 PHPUnit 安裝篇  學習怎麼安裝唷!

閉包 Closure

閉包 Closure 閉包可以用來解偶 function 之間的依賴。 // 用閉包的方式建立一個通用的單例模式 var getSingle = function (fn) { var result; return function () { return result || (result = fn.apply( this .arguments)); } } // 建立登入彈跳視窗 var createLoginDiv = function () { var div = document .createElement( 'div' ); div.innerHTML = '我是登入彈出視窗' ; div.style.display = 'none' ; document .body.appendChild(div); return div; } // 套用 getSingle 閉包 var createSingleLoginDiv = getSingle(createLoginDiv); // 當按下登入按鈕時建立並顯示「登入彈跳視窗」 document .getElementById( 'loginBtn' ).onclick = function () { var loginLayer = createSingleLoginDiv(); loginLayer.style.display = 'block' ; }; /** * getSingle 可以輕鬆套用其他 function */ var createScript = function () { ... } var createIframe = function () { ... } var createButton = function () { ... } var createSingleScript = getSingle(createScript); var createSingleIframe = getSingle(creat

在 Codeigniter 上進行測試

圖片
在 Codeigniter 上進行測試 如果想在 CI 上面使用 PHPUnit 進行測試,可以使用 kenjis 提供的 ci-phpunit-test 。 ci-phpunit-test 讓你在 CI 上面可以很方便就能使用 PHPUnit。 不過使用這個套件之前,有一些必要條件: PHP 版本至少高於 5.4.0 CodeIgniter 至少要有 3.0 至少先安裝 PHPUnit 4.3 以上的版本 ci-phpunit-test 的目錄結構: codeigniter/ ├── application/ │ └── tests/ │ ├── _ci_phpunit_test/ ... 不要碰!裡面是 ci-phpunit-test 使用的檔案 │ ├── Bootstrap.php ... PHPUnit 的 bootstrap 設定檔 │ ├── DbTestCase.php ... 測試 DB 專用的 class │ ├── TestCase.php ... 測試案例專用的 class │ ├── controllers/ ... 把你的 controller 測試程式放進來 │ ├── libraries/ ... 把你的 library 測試程式放進來 │ ├── mocks/ │ │ └── libraries/ ... mock 模擬資料來源專用的 libraries │ ├── models/ ... 把你的 model 測試程式放進來 │ └── phpunit.xml ... PHPUnit 的設定檔 └── vendor/ 透過 Composer 進行安裝 到你的專案目錄下使用 composer 進行下載 ci-phpunit-test $ cd /path/to/codeigniter/ $ composer require kenjis/ci-phpunit-test --dev 下載完成後需要執行一次 install.php 你必須要在專案的根目錄執