เริ่มต้นเขียน unit test กับ JavaScript AngularJS ตอนที่ 1 set up tool

ตอนเริ่มเขียน unit test ใหม่ๆ ผมมักได้ยินเสมอว่า เราไม่เขียน unit test UI กัน เพราะ test ได้ยาก พอนึกถึงภาพการเขียน unit test ก็จะมีแต่งานด้าน back-end หรือ server side

แต่พอได้มาจับ AngularJS JavaScript UI framework ที่รองรับการเขียน unit test ทำให้ผมเริ่มคิดกับเรื่อง unit test กับ UI แต่ยังไม่ได้มีโอกาสเริ่มสักที เพราะเรื่องนี้ค่อนข้างใหม่สำหรับผมมาก

แต่เชื่อไหมครับ พอเราเขียน JavaScript มากขึ้น พอแก้ตรงนั้นที ตรงนี้ที แล้วไม่มี unit test เวลาจะ deploy ก็ต้องมานั่ง manual test ดูว่า code ที่เพิ่ม ที่แก้ กระทบอะไรบ้าง กลายเป็นเรื่องที่น่าเบื่อมาก

มันคงเป็นเรื่องที่ดีไม่น้อย ถ้าเราสามารถลดปริมาณ manual test ลงให้น้อยที่สุด แต่เพิ่มปริมาณ unit test ให้มากขึ้น

ดังนั้น วันนี้ครับ เราจะมาดูกันว่า เราสามารถเขียน unit test ให้กับ JavaScript AngularJS ได้อย่างไร โดยในตอนนี้เราจะเริ่มจากการติดตั้งเครื่องมือ framework ที่จำเป็น และเขียน JavaScript unit test ง่ายๆ กันก่อน

ขั้นตอนต่างๆ เป็นดังนี้

  • ติดตั้ง NodeJS
  • สร้าง package.json file
  • ติดตั้ง karma
  • ติดตั้ง library อื่นๆ เพิ่มเติม
  • ทดสอบใช้งาน Karma
  • ทดลองเขียน unit test ง่ายๆ
  • ทดสอบผลลัพธ์การทำงาน

ติดตั้ง NodeJS

ให้ไปที่ https://nodejs.org/en/ download version ที่ตรงกับเครื่องของเรา แล้วทำการติดตั้งให้เรียบร้อย หากติดตั้งได้ถูกต้องเราจะก็มีคำสั่ง npm มาให้ด้วย npm ย่อมากจาก node package manager เป็นตัวจัดการ library ต่างๆ และเครื่องมือตัวช่วยอื่นๆ สำหรับ node js project

ทดลองเปิด command line tool ใน Windows ก็ cmd หรือ terminal ใน mac แล้วทดลองใช้คำสั่งต่อไปนี้

>npm -version
3.6.0

หากผลลัพธ์แสดงตัวเลข version ของ npm ออกมา แสดงว่าเราได้ทำการติดตั้ง npm เรียบร้อยแล้วครับ

สร้าง package.json file

package.json file จะเอาไว้เก็บ config ต่างๆ ที่เกี่ยวกับ project และ library ต่างๆ ที่ต้องใช้ใน project เราจะใช้คำสั่ง npm init เพื่อสร้าง package.json ใน folder ที่เราเป็น root ของ project ยกตัวอย่างผมทำการเก็บ project ไว้ที่ D:\projects\beginning-angularjs-unit-test

เราก็ใช้ cmd เปิดที่ folder ของ project เราเลย พร้อมใช้คำสั่ง npm init ดังนี้

$ npm init

หลังจากที่เราได้ใช้งานคำสั่งนี้ด้วยการ enter จะมีข้อความต่างๆ แสดงขึ้นมาเพื่อถามเราเกี่ยวกับค่า setting ต่างๆ ใน project เราสามารถ enter ไปเรื่อยๆ เพื่อใช้ค่าที่ถูกตั้งมาให้ หรือพิมพ์เปลี่ยนได้ตามที่เราต้องการ สำหรับผมเองเปลี่ยนเพียง author ชื่อผู้สร้าง project นี้ครับ

  • ติดตั้ง Karma Karma ที่เป็น unit test runner เอาไว้ run test ที่เราเขียนขึ้น ผ่าน command line ถูกพัฒนาโดยทีมผู้สร้าง AngularJS ครับ ติดตั้ง Karma โดยคำสั่งต่อไปนี้
$ npm install karma --save-dev

note

--save-dev ใช้สำหรับบันทึกชื่อตัว package เข้าไปที่ package.json ในส่วนของ devDependencies เพื่อแยกส่วนกันชัดเจนว่า package ตัวนี้ เราใช้เพื่อการ dev หรือ test เท่านั้นครับ

ส่วน --save จะเก็บชื่อ package ไว้ใน dependencies เป็น package ที่มีความจำเป็นในการ run application

package ทั้งหมดที่ถูกติดตั้งด้วยกรณีนี้ จะถูกเก็บใน folder node_modules

ติดตั้ง library อื่นๆ เพิ่มเติมด้วยคำสั่งต่อไปนี้

 D:\projects\beginning-angularjs-unit-test> npm install karma-jasmine karma-phantomjs-launcher phantomjs-prebuilt jasmine-core --save-dev

จากคำสั่งที่ใช้ สังเกตได้ว่า เราติดตั้ง package ดังต่อไปนี้

  • karma-jasmine ทำให้ Kara ใช้งานร่วมกับ Jasmine ซึ่งเป็น JavaScript unit test framework
  • karma-phantomjs-launcher ให้ Karma เรียกใช้งาน PlantomJS ซึ่งเป็น headless browser เป็น browser ที่ไม่ UI สามารถใช้งานแบบ command line เหมาะกับการ automate test
  • phantomjs-prebuilt ตัว browser PlantomJS
  • jasmine-core ตัว Jasmine unit test framework

ทดสอบใช้งาน Karma

เพื่อความสะดวกในการใช้งาน กล่าวคือให้ เราสามารถใช้งานคำสั่ง Karma ตรงๆ เข้าไปที่ cmd หรือ terminal เราต้องติดตั้ง Karma command line interface ก่อน ด้วยคำสั่งต่อไปนี้

$ npm install -g karma-cli

ก่อนเริ่มใช้งาน Karam เราต้องสร้าง config file ของ Karma ขึ้นมาก่อนโดยใชคำสั่งต่อไปนี้

D:\projects\beginning-angularjs-unit-test>karma init

เลือกตัวเลือกต่างๆ ดังต่อไปนี้

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> jasmine

Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no

Do you want to capture any browsers automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> PhantomJS
>

What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> src/**/*.js
> spec/**/*.js
>

Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
>

Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes

เราก็ได้ Karma cofig file ที่ชื่อว่า karma.config.js ไว้ใช้งาน ทดลอง run Karma ด้วยคำสั่งนี้เลย

$ karma start karma.conf.js

ผลลัพธ์การทำงาน

13 02 2016 11:32:29.775:WARN [watcher]: Pattern "D:/projects/beginning-angularjs-unit-test/src/**/*.js" does not match any file.
13 02 2016 11:32:29.780:WARN [watcher]: Pattern "D:/projects/beginning-angularjs-unit-test/spec/**/*.js" does not match any file.
13 02 2016 11:32:29.788:WARN [karma]: No captured browser, open http://localhost:9876/
13 02 2016 11:32:29.802:INFO [karma]: Karma v0.13.19 server started at http://localhost:9876/
13 02 2016 11:32:29.812:INFO [launcher]: Starting browser PhantomJS
13 02 2016 11:32:31.686:INFO [PhantomJS 2.1.1 (Windows 7 0.0.0)]: Connected on socket /#c-gaRtZ3Mlkk7WIYAAAA with id 98899492
PhantomJS 2.1.1 (Windows 7 0.0.0): Executed 0 of 0 ERROR (0.002 secs / 0 secs)

สังเกตที่ error บรรทัดที่ 1 และ 2 เนื่องจากเรายังไม่มี unit test ที่จะ test เลย ตรง out put จึงมี warning แสดงว่าไม่เจอ folder src และ spec ที่เราได้กำหนดไว้ตอน config Karma init

  • src folder เราจะไว้เก็บ source code ของ JavaScript เป็น code ของตัว production
  • spec folder เอาไว้สำหรับเขียน unit test

ทดลองเขียน unit test ง่ายๆ กันครับ สร้าง JavaScript file ชื่อว่า calculator.js ใน folder src และเพิ่มคำสั่งต่อไปนี้

src/calculator.js

function add (x, y) {
	return x + y;
}

ต่อไปเราต้องการที่จะทดสอบว่า function add นี่ทำงานได้ถูกต้องหรือไป ให้เราสร้าง file ชื่อว่า calculatorSpec.js ใน folder spec และเพิ่มคำสั่งต่อไปนี้

spec/calculatorSpec.js

describe('calculator', function() {

	it('should add two numbers', function() {
		expect(add(1,2)).toBe(3);
	});

});

  • describe เป็น function สำหรับจัดกลุ่ม test ของเราเข้าด้วยกัน ใน describe จะประกอบด้วย test ที่อยู่ในกลุ่มเดียวกัน เพื่อทดสอบ function add ของ calculator
  • it function สำหรับเขียนชุดคำสั่งเพื่อทดสอบการทำงานของ method ใน it
  • expect เป็น function เพื่อทดสอบว่า ผลลัพธ์ของ method เป็นไปตามที่เราต้องการไหม โดยจะ return ค่า true หรือ false ออกมา

ทดสอบผลลัพธ์การทำงาน

เพื่อความสะดวกขึ้นไปอีกนิด แทนที่จะใช้คำสั่ง karma start karma.conf.js เราสามารถใช้คำสั่งผ่าน npm ได้แบบนี้เลย npm test

แต่เราต้องเข้าไปแก้ไข package.json section test ให้เป็นดังนี้

{
  "name": "beginning-angularjs-unit-test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "karma start karma.conf.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/codesanook/beginning-angularjs-unit-test.git"
  },
  "author": "aaron",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/codesanook/beginning-angularjs-unit-test/issues"
  },
  "homepage": "https://github.com/codesanook/beginning-angularjs-unit-test#readme",
  "devDependencies": {
    "jasmine-core": "^2.4.1",
    "karma": "^0.13.19",
    "karma-jasmine": "^0.3.7",
    "karma-phantomjs-launcher": "^1.0.0",
    "phantomjs-prebuilt": "^2.1.4"
  },
  "dependencies": {},
  "description": ""
}

บรรทัดที่ 6 เราแก้ไขค่าให้ test script มีค่าเป็น "test": "karma start karma.conf.js"

ทดลอง run Karma อีกครั้งด้วยคำสั่งต่อไปนี้

$ npm test

ผลลัพธ์ที่ได้

13 02 2016 12:00:10.105:WARN [karma]: No captured browser, open http://localhost:9876/
13 02 2016 12:00:10.121:INFO [karma]: Karma v0.13.19 server started at http://localhost:9876/
13 02 2016 12:00:10.130:INFO [launcher]: Starting browser PhantomJS
13 02 2016 12:00:12.030:INFO [PhantomJS 2.1.1 (Windows 7 0.0.0)]: Connected on socket /#ViZub4yBgWkuicGLAAAA with id 89275194
PhantomJS 2.1.1 (Windows 7 0.0.0): Executed 1 of 1 SUCCESS (0.004 secs / 0.002 secs)

ที่บรรทัดที่ 5 บอกว่า Executed 1 of 1 SUCCESS บอกว่า function add ทำงานถูกต้องตามที่เราต้องการ

ลองแก้ calculatorSpec.js เป็นแบบนี้บ้าง

describe('calculator', function() {
	it('should add two numbers', function() {
		expect(add(1,2)).toBe(4);
	});
});

กลับไปดูที่หน้าต่าง command line Karma ถูก run โดยอัตโนมัตครับ

13 02 2016 12:03:10.092:INFO [watcher]: Changed file "D:/projects/beginning-angularjs-unit-test/spec/calculatorSpec.js".
PhantomJS 2.1.1 (Windows 7 0.0.0) calculator should add two numbers FAILED
Expected 3 to be 4. D:/projects/beginning-angularjs-unit-test/spec/calculatorSpec.js:3:24

ในบทความนี้ เราได้เรียนรู้การติตตั้งเครื่องมือต่างๆ ที่จำเป็น และทดลองเขียน JavaScript unit test แบบง่ายๆ ในบทความต่อๆ ไป เราจะลองดูกันว่าเราจะเขียน unit test ให้กับ Angular Controller Service กันได้อย่างไรครับ

download source code

เมื่อโหลดไปแล้วใช้คำสั่ง npm install package ต่างๆ ก็จะโหลดให้โดยอัตโนมัติครับ