關於重構ch.4-建構測試程式
為了正確的進行重構,需要一套可靠的測試工具來發現難以避免的錯誤
這篇筆記一併介紹測試種類,以及利用Jest&Peppeteer實作
Building Test-建構測試程式
章節分成七個部分:
- The value of Self-Testing Code-自檢程式的價值
- Sample Code to Test-測試的範例
- A First Test-初次測試
- Add Another Test-加入其他測試
- Modifying The Fixture-修改fixture
- Probing the Boundaries-探測邊界
- Much More Than This-點到為止?(淺嘗輒止)
The Value of Self-Testing Code
修復bug很快,但找出bug的原因像惡夢 / 修好一個bug還有千千萬萬個bug,而且不知道什麼時候發作
實現頻繁的測試,讓每一次的測試只相距幾分鐘,可以知道bug來自不久前寫的code,也因為記憶猶新,容易找出bug。
開始coding時就是寫測試的好時機!
先寫測試程式才實作功能的程式開發技巧稱為測試驅動開發(Test-Driven Development),透過Test/Coding/Refactor (Red–Green–Refactor)的循環。
Red-Green-Refactor
One of the most widely used techniques for code refactoring is the red/green process used in Agile test-driven development. Applying the Red-Green-Refactor method, developers break refactoring down into three distinct steps:
-
think about what you want to develop. [RED]
-
think about how to make your tests pass. [GREEN]
-
think about how to improve your existing implentation. [REFACTOR]
Sample Code to Test
利用Academind的影片的測試範例
輸入Name&Age,點擊Add User會出現{}
點擊Add User會出現 {name} ({age} years old)
A First Test-demo
開始寫測試之前…
Testing setup
we need some tools that help us with creating these tests
typically need three kinds of tools!
- Test runners
- test runner executes your tests and summarizes the results in the terminal.
- e.g. Mocha / Jest
- Assertion library
- define testing logic, conditions
- also need to be able to define your expect actions and ckeck them.
- e.g. Chai
- Jest is test runner+assertion library combined.
- Headless browser (e2e-testing tools)
- simulation browser interaction
- e.g. Selenium/ Puppeteer
Jest
-
npm install –save-dev jest
-
利用npm套件管理工具下載Jest
-
Jest will be development dependency of our project
-
//package.json "scripts":{ "test":"jest" // "test":"jest --watch" 自動re-run }
-
-
Jest會自動執行檔名結尾為 .spec.js或 .test.js的檔案
-
初次測試generateText function
// util.js // 回傳name和age組合的字串 exports.generateText = (name, age) => { // Returns output text return `${name} (${age} years old)`; };
-
試著建立util.test.js
// import欲測試的function (ex:generateText) const { generateText } = require('./util') //定義test function //傳入兩個參數: 1.測試的描述 2.一個包含測試邏輯的匿名函式 //test('name', () => { // jest will execute to re-run //testing code //}) test('should output name and age', () => { const text = generateText('Max', 29) expect(text).toBe('Max (29 years old)') }) // 執行generateText('Max', 29) // expect function是由assertion library提供 // 檢查text是否為預想的結果-'Max (29 years old)' // ex: tobe(5)確認值是否為5 ;toBeCalled function是否有被執行 ;not.toBe(5)確認值不等於5
coding時至少都要看到每一個測試失敗一次,確保該失敗的時候失敗
Add Another Test & Modifying The Fixture & Probing the Boundaries
// util.js
exports.generateText = (name, age) => {
// Returns output text
return `${name} (${name} years old)`;
};
// util.test.js
test('should output name and age', () => {
const text = generateText('Max', 29);
expect(text).toBe('Max (29 years old)');
});
執行npm test
顯示結果-在”should output name and age”測試中,Received和Expected不同
測試當資料為空/0/負值等情形時
test('should output data-less text', () => {
const text = generateText('', null);
expect(text).toBe(' ( years old)')
})
// fail!!!
Puppeteer
-
e2e-tests需要安裝額外工具去控制browser
-
npm install –save-dev puppeteer
-
將每個步驟逐行輸入(開啟browser、開啟新頁面、導向至url、點擊輸入框、type something)
const puppeteer = require('puppeteer') // 利用puppeteer.lanch啟用browser // browser物件: newPage()開啟新頁面 ;goto()導向URL ;click()頁面點擊互動 test('should create an element with text and correct class', async () => { const browser = await puppeteer.launch({ headless: false, slowMo:80,// slow down by 80ms args:['--window-size=1920,1080'] }) // await 確保一個promise物件都resolve/reject才會繼續執行 const page = await browser.newPage(); await page.goto('localhost:4000/your-page'); await page.click('input#name'); await page.type('input#name', 'Anna'); await page.click('input#age'); await page.type('input#age', '28'); await page.click('#btnAddUser'); const finalText = await page.$eval('.user-item', el => el.textContent); expect(finalText).toBe('Anna (28 years old)'); }, 10000)
所以關於測試這件事
內容取自JavaScript Testing Introduction Tutorial - Unit Tests, Integration Tests & e2e Tests
What is Testing?
writing an app and we are creating an application and we simply test it right
we had a feature , we open the browser and we test our application
[圖片來源: Academind]
we automate the testing part , so we automate it so that we don’t have to manually test everything in our application
Why test?
- get an error if you break code
- save time
- think about possible issues & bugs
- integrate into build workflow
- break up complex dependencies
- improve your code
Different kinds of tests(自動化測試)
Fully Isolated (ex:testing one function) |
Unit Tests | write thousands of these! |
---|---|---|
With Dependencies (e.g. testing a function that calls a function) |
Integration Test | write a good couple of these! |
Full Flow (e.g. validating a the DOM after a click) |
End-to-End(E2E) Tests | write a few of these! |
-
單元測試(Unit Testing)
分為TDD(測試驅動開發)及BDD(行為驅動開發)
測試框架: mocha, jasmine,ava,tap
-
整合測試(Integration Testing)
-
端對端測試(End-to-end Testing)
[圖片來源: Academind]
Other types about Testing
圖片來源:https://www.softwaretestinghelp.com/
延伸閱讀&圖文出處
Code Refactoring Best Practices: When (and When Not) to Do It
Javascript Unit Test: Mocha, Chai, Sinon
The different types of software testing
Types Of Software Testing: Different Testing Types With Details