ในบทความที่ผ่านมา เราได้เรียนรู้วิธีการติดตั้งเครื่องมือที่จำเป็นในการเขียน unit test และคำสั่ง JavaScript unit test แบบง่ายๆ โดยใช้ Jasmine และ Karma
ในตอนนี้เราจะได้มาเริ่มเขียน unit test จริงๆ กับ AngularJS project กันแล้ว
ขั้นตอนต่างๆ เป็นดังนี้
เข้าไปที่ root ของ project แล้วสร้าง folder ใหม่ชื่อว่า lib
จากนั้นให้เรา download AngularJS จาก https://angularjs.org/ unzip แล้ว copy folder angular-1.x.x เข้าไปวางใน folder lib จะได้โครงสร้างของ project เป็นดังนี้
แก้ไข karma.conf.js เพิ่ม JavaScript file ที่จำเป็นเพื่อใช้สำหรับ AngularJS project
karma.conf.js
// Karma configuration
// Generated on Sat Feb 13 2016 11:28:56 GMT+0700 (SE Asia Standard Time)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'lib/angular-1.5.0/angular.min.js',
'lib/angular-1.5.0/angular-mocks.js',
'src/**/*.js',
'spec/**/*.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
บรรทัดที่ 18 และ 19 เราได้เพิ่ม 'lib/angular-1.5.0/angular.min.js', 'lib/angular-1.5.0/angular-mocks.js' ตามลำดับ
ให้เราสร้าง JavaScript file ใหม่ขึ้นมาใน folder src ตั้งชื่อว่า weatherApp.js แก้ไข file เป็นดังนี้
src/weatherApp.js
var app = angular.module('weatherApp', []);
app.factory('weatherService', function () {
var service = {};
service.getWeathers = function () {
var cities = [
{'name': 'Bangkok', 'temp': 32},
{'name': 'San Francisco', 'temp': 13},
{'name': 'Los Angeles', 'temp': 14},
{'name': 'Taipei', 'temp': 21}
];
return cities;
};
return service;
});
ให้เราสร้าง JavaScript file ใน folder spec ตั้งชื่อว่า weatherServiceSpec.js แล้วแก้ไข file เป็นดังนี้
spec/weatherServiceSpec.js
describe('weatherService', function () {
it('getWeathers should return 4 cities', function () {
var service = '???';
expect(service.getWeathers().length).toBe(4);
});
});
จะเห็นได้ว่าตอนนี้ ใน unit test เราต้องการกำหนดค่า weatherService object ให้กับตัวแปร service เพื่อมาใช้ทดสอบว่า เมื่อเรียกใช้ function getWeathers แล้วจะ return Array ที่มีจำนวนสมาชิก 4 ตัว
แต่คำถามคือ เราจะได้ object weatherService มาได้อย่างไร
คำตอบคือ Angular มี mock module ที่ช่วยสร้าง weatherService ให้เรานำไปใช้งานต่อได้เลย
ขึ้นตอนของการสร้าง weatherService object ขึ้นมาใช้งานใน unit test เป็นดังนี้
จากความรู้ตรงนี้ เราสามารถแก้ไข file weatherServiceSpec.js เป็นดังนี้
spec/weatherServiceSpec.js
describe('weatherService', function () {
it('getWeathers should return 4 cities', function () {
//load module
angular.mock.module('weatherApp');
//get service
var service = null;
angular.mock.inject(function (weatherService) { //match argument to existing service in module
service = weatherService;
});
expect(service.getWeathers().length).toBe(4);
});
});
เปิด Windows command line หรือ Mac Linux terminal แล้วใช้คำสั่งต่อไปนี้
run npm test
ผลลัพธ์การทำงานที่หน้าจอ
ผลลัพธ์การทำงาน แสดงให้เห็นว่า test weatherService getWeathers ทำงานได้ถูกต้อง return array ที่มีสมาชิก 4 ตัวกลับมา
สังเกตว่า เรามี test ที่ผ่านสอง test cases เนื่องจาก เรามี code เดิมจากบทความที่แล้ว ที่เราได้ทดสอบ add function รวมเข้าไปด้วย
ในบทความนี้ ผมได้ยกตัวอย่างการใช้งาน unit test กับ AngularJS โดยเริ่มจาก AngularJS service ก่อน แทนที่จะกระโดดไป controller เลย เนื่องจากการเขียน unit test ตัว service จะเข้าใจได้ง่ายกว่า controller
โดยอาศัยความเข้าในส่วนนี้ เราก็สามารถนำไปประยุกต์กับ controller ได้โดยจะยกตัวอย่างในบทความต่อไป
มีคำถาม หรือข้อสงสัยใดๆ เขียน comment กันมาได้เลยครับ
ขอบคุณครับ
เมื่อโหลดไปแล้วใช้คำสั่ง npm install package ต่างๆ ก็จะโหลดให้โดยอัตโนมัติครับ