การทดสอบหน่วย (Unit Testing) ของ AngularJS ด้วย Karma และ Jasmine

⚡ สรุปอย่างชาญฉลาด

การทดสอบหน่วย (Unit Testing) ของ AngularJS ด้วย Karma และ Jasmine ตรวจสอบคอนโทรลเลอร์ ไดเร็กทีฟ และเซอร์วิสแบบแยกส่วน Karma รันข้อกำหนดภายในเบราว์เซอร์จริง Jasmine ให้ไวยากรณ์การยืนยัน และ angular-mocks ฉีดการพึ่งพาโดยไม่ต้องใช้เซิร์ฟเวอร์จริง

  • 🧱 การแบ่งส่วนเครื่องมือ: Karma คือตัวรันการทดสอบ Jasmine คือเฟรมเวิร์กสำหรับการกำหนดคุณสมบัติ และ angular-mocks เป็นตัวช่วยในการฉีดการพึ่งพา (dependency injection)
  • ⚙️ ขั้นตอนการติดตั้ง: ติดตั้ง karma, karma-chrome-launcher, karma-jasmine และ karma-cli ผ่าน npm จากนั้นสร้างไฟล์ karma.conf.js
  • 📁 กฎการกำหนดค่า: อาร์เรย์ไฟล์ต้องแสดงไฟล์ angular.js, angular-mocks.js, ซอร์สโค้ดของแอปพลิเคชัน และโฟลเดอร์ทดสอบ ตามลำดับนั้น
  • 🎛️ การทดสอบตัวควบคุม: ฉีดเซอร์วิส $controller เข้าไป ส่งอ็อบเจ็กต์ $scope จำลองเข้าไป จากนั้นตรวจสอบค่าที่คอนโทรลเลอร์กำหนดให้
  • 🧩 การทดสอบคำสั่ง: ใช้ $compile ร่วมกับ $rootScope เรียกใช้ $digest และตรวจสอบมาร์กอัปที่แสดงผลซึ่งส่งคืนโดยไดเร็กทีฟ
  • 🌐 เลเยอร์แบบครบวงจร: มือโปรtractor จะควบคุมแอปพลิเคชันที่กำลังทำงานอยู่ และนับจำนวนแถวที่ซ้ำกันซึ่งสร้างโดย ng-repeat
  • 📌 สถานะการสนับสนุน: AngularJS สิ้นสุดการสนับสนุนเมื่อวันที่ 31 ธันวาคม 2021 ดังนั้นให้ถือว่าขั้นตอนการทำงานนี้เป็นความรู้สำหรับการบำรุงรักษาแบบเดิม

การทดสอบหน่วย (Unit Testing) ของ AngularJS ด้วย Karma และ Jasmine

หนึ่งในคุณสมบัติที่ยอดเยี่ยมที่สุดของ AngularJS คือ การทดสอบ แง่มุม เมื่อนักพัฒนาที่ Google ในการพัฒนา AngularJS พวกเขาคำนึงถึงการทดสอบและทำให้แน่ใจว่าเฟรมเวิร์ก AngularJS ทั้งหมดสามารถทดสอบได้

ใน AngularJS การทดสอบมักจะทำโดยใช้ Karma (เฟรมเวิร์ก) การทดสอบ AngularJS สามารถทำได้โดยไม่ต้องใช้ Karma แต่เฟรมเวิร์ก Karma มีฟังก์ชันการทำงานที่ยอดเยี่ยมสำหรับการทดสอบโค้ด AngularJS ดังนั้นจึงสมเหตุสมผลที่จะใช้เฟรมเวิร์กนี้

⚠️ หมายเหตุเกี่ยวกับเวอร์ชัน: AngularJS (เวอร์ชัน 1.x) สิ้นสุดการสนับสนุนอย่างเป็นทางการเมื่อวันที่ 31 ธันวาคม 2021 และ Protractor ถูกยกเลิกการใช้งานในเดือนสิงหาคม 2023 เวิร์กโฟลว์ในหน้านี้ยังคงใช้ได้สำหรับการบำรุงรักษาแอปพลิเคชัน AngularJS 1.x ที่มีอยู่ โครงการใหม่ควรใช้ Angular เวอร์ชันใหม่ที่มี runner ที่รองรับในปัจจุบัน

บทนำและการติดตั้งกรอบกรรม

กรรมคือก ทดสอบเครื่องมืออัตโนมัติ สร้างโดยทีม AngularJS ที่ Googleขั้นตอนแรกในการใช้งาน Karma คือการติดตั้ง Karma โดยติดตั้งผ่าน npm (ซึ่งเป็นตัวจัดการแพ็กเกจที่ใช้สำหรับการติดตั้งโมดูลบนเครื่องโลคอลได้อย่างง่ายดาย)

การติดตั้งกรรม

การติดตั้ง Karma ผ่าน npm เสร็จสิ้นในสองขั้นตอน

ขั้นตอน 1) ดำเนินการบรรทัดด้านล่างจากภายในบรรทัดคำสั่ง

npm install karma karma-chrome-launcher karma-jasmine --save-dev

โดยที่

  1. npm คือยูทิลิตี้บรรทัดคำสั่งสำหรับตัวจัดการแพ็กเกจ Node.js ซึ่งใช้สำหรับติดตั้งโมดูลที่กำหนดเองบนเครื่องใดก็ได้ โดยจะมาพร้อมกับแพ็กเกจหลัก Node.js.
  2. พารามิเตอร์การติดตั้งจะแนะนำยูทิลิตีบรรทัดคำสั่ง npm ที่จำเป็นต้องมีการติดตั้ง
  3. มีการระบุไลบรารี 3 รายการในบรรทัดคำสั่งที่จำเป็นสำหรับการทำงานกับกรรม
    • กรรมเป็นห้องสมุดหลักที่จะใช้สำหรับการทดสอบ
    • karma-chrome-launcher เป็นไลบรารีแยกต่างหากซึ่งช่วยให้เบราว์เซอร์ Chrome จดจำคำสั่งกรรมได้
    • karma-jasmine - สิ่งนี้จะติดตั้ง jasmine ซึ่งเป็นเฟรมเวิร์กที่ต้องพึ่งพาสำหรับ Karma

ขั้นตอน 2) ขั้นตอนต่อไปคือการติดตั้งยูทิลิตีบรรทัดคำสั่งกรรม สิ่งนี้จำเป็นสำหรับการดำเนินการคำสั่งบรรทัดกรรม ยูทิลิตี้บรรทัดกรรมจะถูกใช้เพื่อเริ่มต้นสภาพแวดล้อมกรรมสำหรับการทดสอบ

ในการติดตั้งยูทิลิตี้บรรทัดคำสั่งให้รันบรรทัดด้านล่างจากภายในบรรทัดคำสั่ง

npm install -g karma-cli
  • karma-cli ใช้สำหรับติดตั้งส่วนติดต่อบรรทัดคำสั่งของ Karma ซึ่งจะใช้ในการเขียนคำสั่ง Karma ผ่านทางส่วนติดต่อบรรทัดคำสั่ง แฟล็ก -g จะติดตั้งแบบทั่วโลก ทำให้สามารถใช้คำสั่ง Karma ได้จากทุกโฟลเดอร์

การกำหนดค่ากรอบกรรม

ขั้นตอนต่อไปคือการกำหนดค่ากรรมซึ่งสามารถทำได้ผ่านคำสั่ง

karma init

หลังจากดำเนินการขั้นตอนข้างต้นแล้ว กรรมจะสร้างไฟล์ karma.conf.js ไฟล์อาจจะมีลักษณะเหมือนกับตัวอย่างที่แสดงด้านล่าง

files: [
  'node_modules/angular/angular.js',
  'node_modules/angular-mocks/angular-mocks.js',
  'lib/app.js',
  'tests/*.js'
]

ไฟล์กำหนดค่าด้านบนจะแจ้งให้กลไกรันไทม์ Karma ทราบข้อมูลต่อไปนี้

  1. เชิงมุม.js – คำสั่งนี้จะบอก Karma ว่าแอปพลิเคชันของคุณต้องพึ่งพาโมดูลหลักของ AngularJS
  2. angular-mocks.js – คำสั่งนี้บอกให้ Karma ใช้ฟังก์ชันการทดสอบหน่วย (Unit Testing) สำหรับ AngularJS จากไฟล์ angular-mocks.js
  3. แอปพลิเคชันหลักหรือไฟล์ตรรกะทางธุรกิจทั้งหมดมีอยู่ในโฟลเดอร์ lib ของแอปพลิเคชันของคุณ
  4. โฟลเดอร์การทดสอบจะมีการทดสอบหน่วยทั้งหมด

💡 เคล็ดลับ: ลำดับการโหลดไฟล์ภายในอาร์เรย์มีความสำคัญ angular.js ต้องโหลดก่อน angular-mocks.js และทั้งสองไฟล์ต้องโหลดก่อนโค้ดแอปพลิเคชันของคุณ มิเช่นนั้น ตัวฉีด (injector) จะไม่พร้อมใช้งานเมื่อทำการทดสอบ

หากต้องการตรวจสอบว่ากรรมทำงานอยู่หรือไม่ ให้สร้างไฟล์ชื่อ Sample.js ใส่โค้ดด้านล่างและวางลงในไดเร็กทอรีทดสอบ

describe('Sample test', function() {
  it('Condition is true', function() {
    expect('AngularJS').toBe('AngularJS');
  });
});

โค้ดด้านบนมีลักษณะดังต่อไปนี้

  1. ฟังก์ชั่นอธิบายใช้เพื่ออธิบายการทดสอบ ในกรณีของเรา เราจะให้คำอธิบาย 'การทดสอบตัวอย่าง' กับการทดสอบของเรา
  2. ฟังก์ชัน 'it' ใช้เพื่อตั้งชื่อให้กับการทดสอบ ในกรณีของเรา เราจะตั้งชื่อการทดสอบว่า 'Condition is true' ชื่อของการทดสอบจะต้องมีความหมาย
  3. การรวมกันของคีย์เวิร์ด 'expect' และ 'toBe' จะระบุค่าที่คาดหวังและมูลค่าที่แท้จริงของผลการทดสอบ หากค่าจริงและค่าที่คาดหวังเท่ากัน การทดสอบจะผ่าน ไม่เช่นนั้นจะล้มเหลว

เมื่อคุณดำเนินการบรรทัดต่อไปนี้ที่พรอมต์คำสั่ง ระบบจะดำเนินการไฟล์ทดสอบด้านบน

karma start

ผลลัพธ์ด้านล่างนำมาจาก IDE Webstorm ซึ่งได้ดำเนินการตามขั้นตอนข้างต้นแล้ว

การกำหนดค่ากรอบกรรม

  1. ผลลัพธ์จะมาใน Karma explorer ภายใน Webstorm- หน้าต่างนี้แสดงการดำเนินการทดสอบทั้งหมดที่กำหนดไว้ในกรอบกรรม
  2. ที่นี่คุณจะเห็นคำอธิบายของการทดสอบที่ดำเนินการซึ่งก็คือ “การทดสอบตัวอย่าง”
  3. ต่อไป คุณจะเห็นว่าการทดสอบซึ่งมีชื่อว่า "เงื่อนไขเป็นจริง" ได้ถูกดำเนินการแล้ว
  4. โปรดทราบว่าเนื่องจากการทดสอบทั้งหมดจะมีไอคอน "ตกลง" สีเขียวอยู่ข้างๆ ซึ่งเป็นสัญลักษณ์ว่าการทดสอบทั้งหมดผ่าน

Jasmine ในการทดสอบหน่วยของ AngularJS คืออะไร?

Karma เป็นตัวกำหนดว่าจะทำการทดสอบที่ใด ในขณะที่ Jasmine เป็นตัวกำหนดวิธีการเขียนการทดสอบ Jasmine เป็นเฟรมเวิร์กการกำหนดคุณสมบัติแบบขับเคลื่อนด้วยพฤติกรรม ซึ่งเป็นผู้จัดหาคำศัพท์ที่ใช้ในทุกตัวอย่างในหน้านี้ นั่นคือเหตุผลที่อะแดปเตอร์ karma-jasmine ถูกติดตั้งควบคู่ไปกับตัวรันการทดสอบ

จัสมินมีองค์ประกอบพื้นฐานสี่อย่าง:

  • อธิบาย(): จัดกลุ่มข้อกำหนดที่เกี่ยวข้องเข้าเป็นชุดเดียวกัน และยอมรับคำอธิบายที่อ่านง่ายของหน่วยที่กำลังทดสอบ
  • มัน(): ประกาศข้อกำหนดเพียงข้อเดียว ชื่อควรระบุถึงพฤติกรรมที่กำลังตรวจสอบ มากกว่าวิธีการที่ถูกเรียกใช้
  • expect() พร้อมตัวจับคู่: เปรียบเทียบค่าจริงกับค่าที่คาดหวัง ตัวเปรียบเทียบที่ใช้กันทั่วไป ได้แก่ toBe, toEqual, toContain และ toBeDefined
  • beforeEach() และ afterEach(): ดำเนินการติดตั้งและถอดอุปกรณ์ก่อนและหลังการทดสอบทุกครั้ง เพื่อให้การทดสอบแต่ละครั้งเป็นอิสระต่อกัน

Jasmine ยังมีฟังก์ชันสปาย (spy) ด้วย สปายจะแทนที่ฟังก์ชันจริงด้วยฟังก์ชันจำลองที่บันทึกไว้ ทำให้สามารถทดสอบคอนโทรลเลอร์ได้โดยไม่ต้องเรียกใช้เอนด์พอยต์ HTTP จริงๆ เนื่องจาก Jasmine ไม่ต้องการ DOM และไลบรารีการยืนยันใดๆ ของตัวเอง การใช้งาน Karma ร่วมกับ Jasmine จึงยังคงเป็นวิธีที่เบาที่สุดในการใช้งาน AngularJS Javaการทดสอบหน่วยสคริปต์.

การทดสอบคอนโทรลเลอร์ AngularJS

กรอบการทดสอบกรรมยังมีฟังก์ชันในการทดสอบตัวควบคุมตั้งแต่ต้นจนจบ ซึ่งรวมถึงการทดสอบวัตถุ $scope ที่ใช้ในคอนโทรลเลอร์

ลองดูตัวอย่างว่าเราจะบรรลุเป้าหมายนี้ได้อย่างไร

ในตัวอย่างของเรา

ก่อนอื่นเราจะต้องกำหนดตัวควบคุมก่อน ตัวควบคุมนี้จะดำเนินการตามขั้นตอนที่กล่าวถึงด้านล่าง

  1. สร้างตัวแปร ID และกำหนดค่า 5 ให้กับตัวแปรนั้น
  2. กำหนดตัวแปร ID ให้กับวัตถุ $scope

การทดสอบของเราจะทดสอบการมีอยู่ของคอนโทรลเลอร์นี้และทดสอบเพื่อดูว่าตัวแปร ID ของวัตถุ $scope ถูกตั้งค่าเป็น 5 หรือไม่

ก่อนอื่นเราต้องแน่ใจว่ามีข้อกำหนดเบื้องต้นต่อไปนี้

ติดตั้งไลบรารี angular-mocks ผ่าน npm โดยสามารถทำได้โดยการเรียกใช้บรรทัดต่อไปนี้ในพรอมต์คำสั่ง

npm install angular-mocks --save-dev

ถัดไปคือการแก้ไขไฟล์ karma.conf.js เพื่อให้แน่ใจว่ามีไฟล์ที่ถูกต้องสำหรับการทดสอบ ส่วนด้านล่างแสดงเฉพาะส่วนของไฟล์ของ karma.conf.js ที่ต้องแก้ไข

files: ['lib/angular.js', 'lib/angular-mocks.js', 'lib/index.js', 'test/*.js']
  • โดยพื้นฐานแล้วพารามิเตอร์ 'files' จะบอก Karma ถึงไฟล์ทั้งหมดที่จำเป็นในการทดสอบ
  • ไฟล์ angular.js และ angular-mocks.js จำเป็นสำหรับการรันการทดสอบหน่วยของ AngularJS
  • ไฟล์ index.js จะมีโค้ดของเราสำหรับคอนโทรลเลอร์
  • โฟลเดอร์ทดสอบจะมีการทดสอบ AngularJS ทั้งหมดของเรา

ด้านล่างนี้คือโค้ด AngularJS ของเรา ซึ่งจะถูกจัดเก็บเป็นไฟล์ชื่อ Index.js ในโฟลเดอร์ทดสอบของแอปพลิเคชันของเรา

โค้ดด้านล่างนี้ทำสิ่งต่อไปนี้

  1. สร้าง โมดูล AngularJS เรียกว่าแอพตัวอย่าง
  2. สร้างคอนโทรลเลอร์ชื่อ AngularJSController
  3. สร้างตัวแปรชื่อ ID โดยให้ค่า 5 และกำหนดให้กับอ็อบเจ็กต์ $scope
var sampleApp = angular.module('sampleApp', []);
sampleApp.controller('AngularJSController', function($scope) {
  $scope.ID = 5;
});

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

รหัสสำหรับการทดสอบของเราจะเป็นไปตามที่แสดงด้านล่าง

โค้ดจะอยู่ในไฟล์แยกต่างหากชื่อ ControllerTest.js ซึ่งจะวางไว้ในโฟลเดอร์ทดสอบ โค้ดด้านล่างนี้จะทำสิ่งสำคัญดังต่อไปนี้

  1. ฟังก์ชัน beforeEach – ฟังก์ชันนี้ใช้สำหรับโหลดโมดูล AngularJS ที่ชื่อว่า 'sampleApp' ก่อนเริ่มการทดสอบ โปรดทราบว่านี่คือชื่อของโมดูลในไฟล์ index.js
  2. อ็อบเจ็กต์ `$controller` ถูกสร้างขึ้นเพื่อเป็นอ็อบเจ็กต์จำลองสำหรับคอนโทรลเลอร์ “AngularJSController” ซึ่งถูกกำหนดไว้ในไฟล์ `index.js` ของเรา ในการทดสอบแบบ Unit Testing ทุกประเภท อ็อบเจ็กต์จำลองนี้จะแทนอ็อบเจ็กต์เสมือนที่จะถูกนำไปใช้ในการทดสอบจริง โดยอ็อบเจ็กต์จำลองนี้จะจำลองพฤติกรรมของคอนโทรลเลอร์ของเรา
  3. beforeEach(inject(function(_$controller_) – ใช้เพื่อฉีดวัตถุจำลองในการทดสอบของเราเพื่อให้ทำงานเหมือนกับคอนโทรลเลอร์จริง
  4. var $ขอบเขต = {}; นี่คือวัตถุจำลองที่ถูกสร้างขึ้นสำหรับวัตถุ $scope
  5. var controller = $controller('AngularJSController', { $scope: $scope }); – ตรงนี้เรากำลังตรวจสอบว่ามีคอนโทรลเลอร์ชื่อ 'AngularJSController' อยู่หรือไม่ และเรายังกำหนดค่าตัวแปรทั้งหมดจากอ็อบเจ็กต์ $scope ในคอนโทรลเลอร์ของเราในไฟล์ Index.js ไปยังอ็อบเจ็กต์ $scope ในไฟล์ทดสอบของเราด้วย
  6. สุดท้ายนี้ เรากำลังเปรียบเทียบ $scope.ID กับ 5
describe('AngularJSController', function() {
  beforeEach(module('sampleApp'));

  var $controller;

  beforeEach(inject(function(_$controller_){
    $controller = _$controller_;
  }));

  describe('$scope.ID', function() {
    it('Check the scope object', function() {
      var $scope = {};
      var controller = $controller('AngularJSController', { $scope: $scope });
      expect($scope.ID).toEqual(5);
    });
  });
});

การทดสอบข้างต้นจะทำงานในเบราว์เซอร์กรรมและให้ผลการผ่านเช่นเดียวกับที่แสดงในหัวข้อที่แล้ว

การทดสอบคำสั่ง AngularJS

เฟรมเวิร์กการทดสอบ Karma ยังมีฟังก์ชันการทำงานสำหรับการทดสอบไดเร็กทีฟแบบกำหนดเอง ซึ่งรวมถึงเทมเพลตด้วยURLซึ่งใช้ภายในคำสั่งที่กำหนดเอง

ลองดูตัวอย่างว่าเราจะบรรลุเป้าหมายนี้ได้อย่างไร

ในตัวอย่างของเรา เราจะกำหนดคำสั่งแบบกำหนดเองก่อน ซึ่งจะดำเนินการดังต่อไปนี้

  1. สร้างโมดูล AngularJS ชื่อ SampleApp
  2. สร้างไดเร็กทีฟแบบกำหนดเองโดยใช้ชื่อว่า – guru99
  3. สร้างฟังก์ชันที่ส่งคืนเทมเพลตพร้อมแท็กส่วนหัวซึ่งแสดงข้อความ “นี่คือการทดสอบ AngularJS”
var sampleApp = angular.module('sampleApp', []);
sampleApp.directive('guru99', function () {
  return {
    restrict: 'E',
    replace: true,
    template: '<h1>This is AngularJS Testing</h1>'
  };
});

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

โค้ดจะอยู่ในไฟล์แยกต่างหากชื่อ DirectiveTest.js ซึ่งจะวางไว้ในโฟลเดอร์ทดสอบ โค้ดด้านล่างนี้ทำหน้าที่สำคัญดังต่อไปนี้

  1. ฟังก์ชัน beforeEach – ฟังก์ชันนี้ใช้สำหรับโหลดโมดูล AngularJS ที่ชื่อว่า 'sampleApp' ก่อนที่จะเริ่มการทดสอบ
  2. บริการ `$compile` ใช้สำหรับคอมไพล์ไดเร็กทีฟ บริการนี้เป็นสิ่งที่จำเป็นและต้องประกาศไว้เพื่อให้ AngularJS สามารถนำไปใช้คอมไพล์ไดเร็กทีฟที่กำหนดเองของเราได้
  3. `$rootScope` คือขอบเขตหลักของแอปพลิเคชัน AngularJS ใดๆ เราได้เห็นอ็อบเจ็กต์ `$scope` ของคอนโทรลเลอร์ในบทก่อนหน้านี้แล้ว อ็อบเจ็กต์ `$scope` นั้นเป็นอ็อบเจ็กต์ลูกของอ็อบเจ็กต์ `$rootScope` เหตุผลที่ประกาศไว้ที่นี่ก็เพราะเรากำลังทำการเปลี่ยนแปลงแท็ก HTML จริงๆ ใน ​​DOM ผ่านทางไดเร็กทีฟที่กำหนดเองของเรา ดังนั้นเราจึงจำเป็นต้องใช้บริการ `$rootScope` ซึ่งคอยรับฟังหรือรับรู้เมื่อมีการเปลี่ยนแปลงใดๆ เกิดขึ้นภายในเอกสาร HTML
  4. var element = $compile(“ ”)($rootScope) – ใช้สำหรับตรวจสอบว่า directive ของเราถูกแทรกเข้าไปอย่างถูกต้องหรือไม่ directive นี้ถูกลงทะเบียนด้วยชื่อแบบ camel case ว่า guru99 ดังนั้น AngularJS จึงจับคู่กับองค์ประกอบที่เป็นตัวพิมพ์เล็ก ในโค้ดมาร์กอัป ดังนั้นจึงใช้คำสั่งนี้ในการตรวจสอบดังกล่าว
  5. expect(element.html()).toContain(“This is AngularJS Testing”) – คำสั่งนี้ใช้เพื่อบอกฟังก์ชัน expect ว่าควรค้นหาองค์ประกอบ (ในกรณีของเราคือแท็ก h1) ที่มีข้อความ innerHTML ว่า “This is AngularJS Testing”
describe('Unit testing directives', function() {
  var $compile,
      $rootScope;
  beforeEach(module('sampleApp'));

  beforeEach(inject(function(_$compile_, _$rootScope_){
    $compile = _$compile_;
    $rootScope = _$rootScope_;
  }));

  it('Check the directive', function() {
    // Compile a piece of HTML containing the directive
    var element = $compile("<guru99></guru99>")($rootScope);
    $rootScope.$digest();
    expect(element.html()).toContain("This is AngularJS Testing");
  });
});

การทดสอบข้างต้นจะทำงานในเบราว์เซอร์กรรมและให้ผลการผ่านเช่นเดียวกับที่แสดงในหัวข้อที่แล้ว

การทดสอบแบบครบวงจร (End-to-End Testing) สำหรับแอปพลิเคชัน AngularJS

เฟรมเวิร์กการทดสอบกรรม พร้อมกับเฟรมเวิร์กที่เรียกว่า ProtracTor มีฟังก์ชันการทำงานที่สามารถทดสอบเว็บแอปพลิเคชันตั้งแต่ต้นจนจบได้

ดังนั้นจึงไม่ใช่แค่การทดสอบคำสั่งและตัวควบคุมเท่านั้น แต่ยังทดสอบสิ่งอื่นใดที่อาจปรากฏบนหน้า HTML ด้วย

ลองดูตัวอย่างว่าเราจะบรรลุเป้าหมายนี้ได้อย่างไร

ในตัวอย่างด้านล่าง เราจะมีแอปพลิเคชัน AngularJS ซึ่งสร้างตารางข้อมูลโดยใช้คำสั่ง ng-repeat

  1. ขั้นแรกเรากำลังสร้างตัวแปรที่เรียกว่า "บทช่วยสอน" และกำหนดคู่คีย์-ค่าให้กับมันในขั้นตอนเดียว คู่คีย์-ค่าแต่ละคู่จะถูกใช้เป็นข้อมูลเมื่อแสดงตาราง จากนั้นตัวแปรบทช่วยสอนจะถูกกำหนดให้กับวัตถุขอบเขตเพื่อให้สามารถเข้าถึงได้จากมุมมองของเรา
  2. สำหรับแต่ละแถวของข้อมูลในตาราง เราใช้คำสั่ง ng-repeat คำสั่งนี้จะผ่านคู่คีย์-ค่าแต่ละคู่ในออบเจ็กต์ขอบเขตการสอนโดยใช้ตัวแปร ptutor
  3. ในที่สุดเราก็ใช้ แท็กพร้อมกับคู่ค่าคีย์ (ptutor.Name และ ptutor.Description) เพื่อแสดงข้อมูลตาราง
<table>
  <tr ng-repeat="ptutor in tutorial">
    <td>{{ ptutor.Name }}</td>
    <td>{{ ptutor.Description }}</td>
  </tr>
</table>
</div>
<script type="text/javascript">
var app = angular.module('DemoApp', []);
app.controller('DemoController', function($scope) {
  $scope.tutorial = [
    {Name: "Controllers", Description: "Controllers in action"},
    {Name: "Models", Description: "Models and binding data"},
    {Name: "Directives", Description: "Flexibility of Directives"}
  ];
});

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

การทดสอบของเราจะทดสอบคำสั่ง ng-repeat และให้แน่ใจว่ามีข้อมูล 3 แถวตามที่ควรจะเป็นจากตัวอย่างข้างต้น

ก่อนอื่นเราต้องแน่ใจว่ามีข้อกำหนดเบื้องต้นต่อไปนี้

ติดตั้งเวอร์ชันโปรtracติดตั้งไลบรารี Tor ผ่าน npm โดยการเรียกใช้บรรทัดคำสั่งต่อไปนี้ในพรอมต์คำสั่ง

npm install -g protractor

รหัสสำหรับการทดสอบของเราจะเป็นไปตามที่แสดงด้านล่าง

โค้ดจะอยู่ในไฟล์แยกต่างหากชื่อ CompleteTest.js ซึ่งจะวางไว้ในโฟลเดอร์ทดสอบ โค้ดด้านล่างนี้จะทำสิ่งสำคัญดังต่อไปนี้

  1. ฟังก์ชันเบราว์เซอร์นั้นให้บริการโดยผู้เชี่ยวชาญtracไลบรารี tor และสมมติว่าแอปพลิเคชัน AngularJS ของเรา (พร้อมโค้ดที่แสดงด้านบน) กำลังทำงานอยู่บนเว็บไซต์ของเรา URL – http://localhost:8080/Guru99 /
  2. var list = element.all(by.repeater('ptutor in tutorial')); - บรรทัดโค้ดนี้ดึงข้อมูลจาก directive ng-repeat ซึ่งมีค่าเป็น 'ptutor in tutorial' element และ by.repeater เป็นคีย์เวิร์ดพิเศษที่ pro จัดเตรียมไว้ให้tracไลบรารี Tor ที่ช่วยให้เราได้รับรายละเอียดของคำสั่ง ng-repeat
  3. คาดหวัง (list.count()).toEqual(3); – สุดท้ายนี้ เรากำลังใช้ฟังก์ชันคาดหวังเพื่อดูว่าเราได้รับ 3 รายการที่อยู่ในตารางของเราอันเป็นผลมาจากคำสั่ง ng-repeat
describe('Unit testing end to end', function() {
  beforeEach(function() {
    browser.get('http://localhost:8080/Guru99/');
  });

  it('Check the ng directive', function() {
    var list = element.all(by.repeater('ptutor in tutorial'));
    expect(list.count()).toEqual(3);
  });
});

การทดสอบข้างต้นจะทำงานในเบราว์เซอร์กรรมและให้ผลการผ่านเช่นเดียวกับที่แสดงในหัวข้อที่แล้ว

คาร์มา ปะทะ จัสมิน ปะทะ โปรtracทอร์: ความแตกต่างที่สำคัญ

เครื่องมือทั้งสามที่ใช้ในหน้านี้มักถูกเข้าใจผิดว่าเป็นเครื่องมือเดียวกัน เนื่องจากปรากฏอยู่ในบรรทัดคำสั่งเดียวกัน แต่แท้จริงแล้วแต่ละเครื่องมืออยู่ในระดับที่แตกต่างกันของกระบวนการทดสอบ ดังที่ตารางด้านล่างแสดงให้เห็นอย่างชัดเจน

พารามิเตอร์ กรรม ดอกมะลิ มือโปรtracTor
Category นักวิ่งทดสอบ กรอบข้อกำหนด กรอบการทำงานอัตโนมัติแบบครบวงจร
งานหลัก เปิดเบราว์เซอร์และรายงานผลลัพธ์ ให้คำอธิบาย สิ่งนั้น และสิ่งที่คาดหวัง ใช้งานแอปพลิเคชันแบบเรียลไทม์ในเบราว์เซอร์จริง
ระดับการทดสอบ หน่วยและ บูรณาการ หน่วยและการบูรณาการ ตั้งแต่ต้นจนจบ
จำเป็นต้องมีเซิร์ฟเวอร์ที่เปิดใช้งานอยู่ ไม่ ไม่ มี (ใบกำกับภาษีเต็มรูปแบบ)
แฟ้มการกำหนดค่า karma.conf.js ไม่มีเลย มันทำงานอยู่ภายในตัววิ่ง สำหรับtractor.conf.js
สถานะปัจจุบัน เลิกใช้งานแล้ว ใช้สำหรับการบำรุงรักษาเท่านั้น มีการดูแลรักษาอย่างสม่ำเสมอ เกษียณอายุในเดือนสิงหาคม พ.ศ. 2023

กล่าวโดยสรุป จัสมินเป็นผู้เขียนแบบทดสอบ คาร์มาเป็นผู้ดำเนินการทดสอบ และโปรเป็นผู้ดำเนินการทดสอบtractor ขยายไวยากรณ์ Jasmine เดียวกันนี้ไปใช้กับหน้าเว็บที่แสดงผลอย่างสมบูรณ์

แนวทางปฏิบัติที่ดีที่สุดสำหรับการทดสอบหน่วย (Unit Testing) ของ AngularJS

การปฏิบัติตามหลักการพื้นฐานเพียงไม่กี่ข้อจะช่วยให้ชุดเครื่องมือ AngularJS ทำงานได้อย่างรวดเร็วและน่าเชื่อถือเมื่อแอปพลิเคชันเติบโตขึ้น

  1. ทดสอบทีละชิ้น โหลดเฉพาะโมดูลที่กำลังทดสอบภายใน beforeEach และจำลองการทำงานของทุกผู้ร่วมงาน เพื่อให้ความล้มเหลวชี้ไปที่ไฟล์เดียว
  2. ห้ามโทรไปยังระบบแบ็กเอนด์จริงเด็ดขาด ใช้บริการ `$httpBackend` จาก `angular-mocks` เพื่อส่งคืนการตอบสนองสำเร็จรูป จากนั้นการทดสอบจะทำงานแบบออฟไลน์และให้ผลลัพธ์ที่เหมือนกันในทุกเครื่อง
  3. ควรตั้งชื่อข้อกำหนดให้สอดคล้องกับพฤติกรรมการใช้งาน ชื่อรายงานอย่างเช่น “ส่งค่า 5 กลับมาเมื่อตัวควบคุมเริ่มต้นทำงาน” อ่านง่ายกว่าชื่อ “test1”
  4. ควรล้างระบบย่อยอาหารทุกครั้ง เรียกใช้ $rootScope.$digest() หลังจากเปลี่ยนข้อมูลขอบเขต มิฉะนั้น การผูกและการตรวจสอบจะไม่ได้รับการอัปเดต และการยืนยันจะล้มเหลวด้วยเหตุผลที่ไม่ถูกต้อง
  5. วัดความครอบคลุม แต่ต้องพิจารณาอย่างรอบคอบ เพิ่ม karma-coverage เพื่อดูสาขาที่ยังไม่ได้ทดสอบ การครอบคลุมสูงแต่มีการตรวจสอบที่ไม่เข้มงวดก็ยังคงซ่อนข้อบกพร่องอยู่ดี
  6. เรียกใช้ชุดทดสอบในระบบการรวมอย่างต่อเนื่อง (Continuous Integration) ใช้ตัวเรียกใช้งาน Chrome แบบไม่มีส่วนติดต่อผู้ใช้ เพื่อให้ข้อกำหนดเดียวกันทำงานทุกครั้งที่มีการคอมมิต แทนที่จะทำงานเฉพาะบนเครื่องของนักพัฒนาเท่านั้น

การนำกฎเหล่านี้ไปใช้จะเปลี่ยนตัวอย่างข้างต้นจากการสาธิตแบบแยกส่วนไปเป็นการป้องกันความผิดพลาดสำหรับโค้ดเบส AngularJS รุ่นเก่า สำหรับภาพรวมที่กว้างขึ้น โปรดดูที่... บทช่วยสอน AngularJS ชุด.

คำถามที่พบบ่อย

โมดูลที่มีผู้ให้บริการนั้นไม่ได้ถูกโหลด เพิ่มโมดูลนั้นเข้าไปใน beforeEach(module('yourModule')) และตรวจสอบให้แน่ใจว่า angular-mocks.js อยู่ในรายการ karma.conf.js หลัง angular.js มิเช่นนั้น ตัวฉีดจะไม่สามารถแก้ไขการพึ่งพาได้

ติดตั้ง karma-chrome-launcher และตั้งค่าตัวเลือกเบราว์เซอร์เป็น ChromeHeadless ในไฟล์ karma.conf.js จากนั้นชุดโปรแกรมจะทำงานภายในไปป์ไลน์การรวมระบบอย่างต่อเนื่องและคอนเทนเนอร์ที่ไม่มีเซิร์ฟเวอร์แสดงผลให้บริการ

ใช่แล้ว ผู้ช่วยเขียนโค้ด AI จะอ่านตัวควบคุมและร่างข้อกำหนด Jasmine โดยใช้ขอบเขตและตัวจับคู่จำลอง Revโปรดตรวจสอบผลลัพธ์อย่างละเอียด เนื่องจากข้อความยืนยันที่สร้างขึ้นมักจะกล่าวถึงวิธีการใช้งานจริงแทนที่จะตรวจสอบพฤติกรรมที่ตั้งใจไว้

ใช่แล้ว เครื่องมือ AI จะแปลงข้อกำหนดของ Jasmine เป็นไวยากรณ์ Jest หรือ Vitest และระบุการเรียกใช้ angular-mocks ที่ไม่มีสิ่งที่เทียบเท่าโดยตรง การตรวจสอบด้วยตนเองยังคงมีความสำคัญ เนื่องจากรูปแบบการฉีดการพึ่งพา (dependency injection) มักจะแปลงได้ไม่สมบูรณ์แบบ

โดยทั่วไปแล้ว ทีมส่วนใหญ่ตั้งเป้าหมายการครอบคลุมคำสั่ง (statement coverage) ไว้ที่ 70-80 เปอร์เซ็นต์สำหรับคอนโทรลเลอร์และบริการต่างๆ การพยายามให้ได้ตัวเลขที่สูงกว่านั้นมักหมายถึงการทดสอบเทมเพลตและไลบรารีของบุคคลที่สาม ซึ่งจะเพิ่มต้นทุนในการบำรุงรักษาโดยไม่ได้ตรวจพบข้อบกพร่องที่แท้จริง

สรุปโพสต์นี้ด้วย: