
สวัสดีครับ ช่วงเริ่มต้นบทความเนี่ยลำบากใจทุกทีไม่รู้จะเขียนทักทายยังไง …
โอเค เข้าเรื่องดีกว่า เชื่อว่าพวก unit test อะไรคงมีสอนกันเยอะมากในเน็ต แต่ละคนก็เขียนกันคนละแบบเลยก็สูตรใครสูตรมันละกันครับ แนะนำว่าให้อ่านศึกษาดูตัวอย่างเยอะๆนะครับ พอดีมีแววว่าจะต้องได้เขียน test angularjs ก็เลยมาดูๆเพื่อไว้ก่อน สำหรับบทความนี้พยายามตั้งค่าอะไรให้น้อยที่สุด เพื่อให้ง่ายต่อความเข้าใจไม่ยุ่งยาก (*บทความนี้มีไว้ให้เจ้าของกันลืม 555)
โอเคครับก่อนอื่นเนี่ย เราต้องรู้จักกับ unit-test ก่อน … โอเค เอาเป็นว่าน่าจะรู้จักกันอยู่แล้วแหละนะ ถ้าไม่รู้จักนี่แนะนำให้หาอ่านก่อนนะครับ โดย จะเขียน test เนี่ยแต่ละภาษาก็จะมีวิธีมีเครื่องมือที่แตกต่างกันไปครับ ซึ่งในบทความนี้จะเขียน test angularjs โดยใช้ karma jasmine ครับ นั่นๆงงๆ โอเคมาทำความรู้จักกันก่อน
- Karma เป็นเหมือนเครื่องมือช่วยจัดการกับสภาพแวดล้อมให้เราสามารถรัน test ได้ (เอาจริงๆบอกแค่นี้คง งงๆเดียวดูตัวอย่างว่ามันมีประโยชน์อะไรก็น่าจะ อ๋อ) ซึ่งสามารถติดตั้งปลั้กอินต่างๆเพิ่มเข้าไปได้อีกด้วย รายชื่อปลั้กอิน
- Jasmine เป็น framework สำหรับทำ testing โดยเฉพาะ ซึ่งจริงๆมีหลายเจ้ามากถ้าเราไม่ใช้ jasmine ก็ยังมีทางเลือกอื่นๆอีกมาก
โดยจริงๆถ้าเราจะ test javascriptใช้แค่ jasmine ก็ได้ครับไม่พึ่ง Karma เลยแต่เชื่อเถอะครับไม่เวิค เราควรใช้งานมันเริ่มกันแหละ โอเคหลักๆที่ควรจะรู้ก็มีสองอย่างนี้แหละครับทีนี้เรามาติดตั้ง เครื่องมือเรากันดีกว่าครับ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "name": "testing-angular", "version": "1.0.0", "description": "example angularjs testing project", "main": "index.js", "scripts": { "test": "karma start karma.config.js" }, "author": "xier", "license": "ISC", "devDependencies": { "angular": "^1.3.16", "angular-mocks": "^1.3.16", "jasmine-core": "^2.3.4", "karma": "^0.12.36", "karma-chrome-launcher": "^0.1.12", "karma-jasmine": "^0.3.5" } } |
อันนี้ไฟล์ package.json จริงๆสามารถ copy อันนี้ไปใช้ได้เลยนะครับ หรือใครอยาก init เองก็ก็อบแค่ส่วน devDependencies ไปแค่นั้นก็ได้ครับแล้วก็ npm install กันโล้ดดดด
โอเคเมื่อติดตั้งเครื่องมืออะไรกันเรียบร้อยก็มาเริ่มกันเลยครับก่อนอื่นเนี่ยเราต้องเริ่มจากตั้งค่า karma ก่อนเพื่อให้รู้ว่าเราจะรันไฟล์เทสเราที่ไหน หรือจะมีการตั้งค่าติดตั้งปลั้กอินอะไรเพิ่ม โดยเริ่มต้นให้เราพิมคำสั่ง (ในกรณีมีปัญหาการใช้งานคำสั่ง karma ให้พิม npm install karma -g เพิ่มเข้าไปนะครับ)
1 |
karma init karma.conf.js |
หลังจากนั้นก็จะมีคำถามเกี่ยวกับการตั้งค่าพื้นฐานให้เราเลือกซึ่งถ้าเรา ไม่พิมอะไรแล้ว enter ก็จะถือเป็นก็ข้ามไป ซึ่งให้เราเลือก jasmine เรานะครับ อะไรที่ไม่รู้เว้นว่างไว้ก็ได้ครับ หลังจากนั้นเราก็จะได้ไฟล์ karma.conf.js ทีนี้เรามาแก้ไขไฟล์นี้กัน (ข้างล่างคือที่แก้ไขแล้วนะครับ)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
// Karma configuration // Generated on Sat Jun 13 2015 20:58:05 GMT+0700 (ICT) 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: [ 'node_modules/angular/angular.js', 'node_modules/angular-mocks/angular-mocks.js', 'src/myapp.js', 'test/*_test.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: ['Chrome'], // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits singleRun: false }); }; |
โดยหลักที่ควรจะต้องรู้คือ
- framework: อันนี้คือ framework ที่ใช้ในการ test ควรเป็น jasmine
- files: อันนี้เป็นการ include files ก่อนที่เราจะเข้าสู่การเทสซึ่ง karma ก็รู้ว่าต้องใช้ไฟล์อะไรบ้างในที่นี้ก็จะมีพวก angular หรือไฟล์ต่างๆในโปรเจค (แล้วก็อย่าไปทะลึ่ง include ไฟล์ angular.min.js นะครับ มันจะพัง 555+ )
- browsers: อาจจะดูเหมือนไม่สำคัญใส่อะไรก็ได้ แต่บางคำสั่งก็ไม่รองรับบนบาง browser นะอันนี้สำคัญ
*_test.js หมายถึงไฟล์ไหนก็ตามที่มีชื่อลงท้ายด้วย _test.js เช่น user_test.js , test_test.js , app_test.js
หลักๆที่น่าจะต้องรู้แต่จริงๆค่าอื่นๆก็สำคัญนะครับ แต่แนะนำให้อ่านเพิ่มเติมนะครัชชชช โอเคเรามาเริ่มเขียน angular กับไฟล์ test ของเรากันเถอะครับ
เริ่มจาก src/myapp.js จะเป็นว่ามี controller SimpleCtrl กับโค้ดนิดๆหน่อยๆ ^,^ (ตัวอย่างนะครับ)
1 2 3 4 5 6 7 8 9 10 11 |
var app = angular.module("myapp", []); app.controller("SimpleCtrl", function($scope){ $scope.message = "Hello World"; $scope.add = function(a,b) { return a + b } }); |
ต่อไปเราอยากจะทดสอบว่าเจ้า SimpleCtrl เนี่ย message มีค่าเท่ากับ “Hello World” ไหมหรือว่า function add เราทำงานได้ถูกต้องรึเปล่าก็จะเริ่มกันเลย เวลาเขียน test ก็จะประมาณนี้ครับ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
describe("unit testing myapp", function(){ beforeEach(angular.mock.module('myapp')); var controller, scope; beforeEach(inject(function ($rootScope, $controller) { scope = $rootScope.$new(); controller = $controller('SimpleCtrl', { $scope: scope }); })); describe("Test SimpleCtrl", function(){ it("message should be Hello World", function(){ expect(scope.message).toEqual("Hello World"); }); it("1 + 1 should be 2", function(){ expect(scope.add(1,1)).toEqual(2); }) }); }); |
(เดียวๆใจเย็นๆก่อนอย่าพึ่งตกใจ!!)
โอเคมาเริ่มอธิบายกันเถอะครัช คือว่าอาจจะเริ่มงงๆนิดนึง มาถึงอะไรเยอะแยะฟะ จริงๆแล้วสำคัญๆคือ เรื่องของเรื่องเนี่ยคือ
1 |
beforeEach(angular.mock.module('myapp')); |
เป็นการบอกให้ ว่ามีการจำลอง module myapp (อ่านเพิ่มเติม mock.module) ของขึ้นมาก่อนที่จะทำการเริ่ม test (beforeEach และก็มี AfterEach ด้วยคือหลังจากทดสอบเสร็จ) ต่อมาเนี่ยเพื่อที่เราจะเริ่มจะบอกว่าการเทสนี้จะเทส SimpleCtrl ก็ต้องเรียกเข้ามาด้วยโดยใช้ $controller เป็นคำสั่งที่ใช้ในการสร้าง controller พร้อมกับ inject ค่า และจะเห็นว่ามีการเรียกใช้ inject() มันคือ 1 ในความสามารถของ ngMock module ที่ช่วยให้เรา inject dependencies
1 |
expect(scope.add(1,1)).toEqual(2); |
ส่วน expect บรรทัดนี้หมายถึงคาดหวังว่า function scope.add เนี่ยจะทำงานได้ถูกต้องคือ มีค่าเท่ากับ 2 ซึ่งถ้าผลลัพธ์ที่ได้ไม่เท่ากับ 2 จะถือว่าการทำงานผิดไม่ตรงกับเป้าหมายที่หวังไว้จะ test failed นะครับ
describe กับ it เข้าใจว่ามันเหมือนพวกคำอธิบายละกันครัชช
ทีนี้ไฟล์ต่างๆจะอยู่ในในโฟลเดอร์เราก็จะหน้าตาประมาณนี้นะครับ path ต่างๆก็จะตรงตั้งกับค่าที่เราตั้งใน karma
โอเคมารันกันได้ละ เหนื่อยๆวิธีการรัน karma เนี่ยคือเราต้องไปอยู่ที่โฟลเดอร์เดียวกับไฟล์ karma.config.js จากนั้นให้เราพิมคำสั่ง
1 |
karma start karma.config.js |
หรือ
1 |
npm test |
เพราะว่าผมไปตั้งค่าไว้ใน package.json ว่าถ้าพิม npm test เนี่ยจะรันคำสั่ง karma start มันสั้นดีนะครับแต่นำให้ลองตั้งดูหรือดูจากตัวอย่างก็ได้ครับ
เอาละทีนี้ได้ผลลัพธ์ดังภาพ และก็จะมี browser เด้งขึ้นมาตามที่เราตั้งว่าจะเทสกับ browser อะไรปล่อยมันยังงั้นละครับ
ทีนี้ karma จะบอกเราว่า test เราสำเร็จหรือไม่ อะไรยังไง 🙂 โหทำตั้งนานเพื่อดูสองบรรทัด Y.Y ทีนี้ถ้าใครได้ Failed นี่ก็ตามแก้เอานะครับ 555+ (karma จะรันใหม่ทุกครั้งที่มีการแก้ไขไฟล์ใน path ที่เรากำหนดนะครับ)
ส่วนอันนี้คือโค้ดที่เราทำกันมาทั้งหมดนะครับใครขี้เกียจก็โหลดไปรันเล่นกันได้นะครับ https://github.com/zier/beginner-angular-testing
โอเค หวังว่าจะช่วยให้ใครที่อยากจะ test angular ให้เข้าใจได้เร็วขึ้นหรืออย่างน้อยๆก็รู้ว่าต้องเริ่มจากไหนนะครับ