ข้ามไปยังเนื้อหาหลัก
คู่มือระบบ เนื้อหาผ่านการตรวจสอบแล้ว

Code Coverage: วัดคุณภาพการทดสอบด้วย Code Coverage

ในบทที่แล้ว เราได้เรียนรู้เรื่อง Data Providers สำหรับการทดสอบ ในบทนี้ เราจะมาทำความรู้จักกับ Code Coverage ซึ่งเป็นเมตริกที่ใช้วัดว่า test case ของเราครอบคลุมโ...

Code Coverage: วัดคุณภาพการทดสอบด้วย Code Coverage

ในบทที่แล้ว เราได้เรียนรู้เกี่ยวกับการใช้ Data Providers เพื่อทดสอบฟังก์ชันด้วยชุดข้อมูลที่หลากหลาย ทำให้เรามั่นใจได้ว่าฟังก์ชันของเราทำงานได้อย่างถูกต้องในทุกกรณี ในบทนี้ เราจะมาทำความรู้จักกับเครื่องมือที่ช่วยให้เราวัดคุณภาพของการทดสอบได้ดียิ่งขึ้น นั่นคือ Code Coverage ครับ

Code Coverage คืออะไร?

Code Coverage คือ เมตริกที่ใช้วัดว่าโค้ดส่วนใดบ้างของโปรแกรมที่เราได้ทำการทดสอบไปแล้ว พูดง่ายๆ คือ มันจะบอกเราว่า test case ของเราครอบคลุมโค้ดของเรามากแค่ไหน หาก Code Coverage สูง แสดงว่า test case ของเราได้ทดสอบโค้ดส่วนใหญ่แล้ว แต่ถ้า Code Coverage ต่ำ แสดงว่ายังมีโค้ดอีกหลายส่วนที่เรายังไม่ได้ทดสอบ ซึ่งอาจมีความเสี่ยงที่จะเกิดข้อผิดพลาดได้

ลองนึกภาพว่าเรามีฟังก์ชันที่ซับซ้อน ซึ่งมีหลายเงื่อนไข (if/else statements) และ loop การทดสอบที่ดีจะต้องครอบคลุมทุกเงื่อนไขและทุก loop เพื่อให้มั่นใจว่าฟังก์ชันทำงานได้อย่างถูกต้องในทุกสถานการณ์ Code Coverage จะช่วยให้เราเห็นภาพรวมว่าเราได้ทดสอบครอบคลุมแค่ไหน และส่วนไหนที่ยังขาดอยู่

ทำไม Code Coverage ถึงสำคัญ?

  • ช่วยระบุจุดที่ยังไม่ได้ทดสอบ: Code Coverage จะแสดงให้เห็นว่ามีโค้ดส่วนไหนบ้างที่ยังไม่มี test case ครอบคลุม ทำให้เราสามารถเขียน test case เพิ่มเติมเพื่อเพิ่มความครอบคลุม
  • เพิ่มความมั่นใจในคุณภาพของโค้ด: เมื่อ Code Coverage สูง แสดงว่าโค้ดส่วนใหญ่ได้รับการทดสอบอย่างละเอียด ทำให้เรามั่นใจได้ว่าโค้ดมีคุณภาพดีและมีโอกาสเกิดข้อผิดพลาดน้อย
  • ช่วยในการ Refactoring: เมื่อเราทำการปรับปรุงโค้ด (Refactoring) Code Coverage จะช่วยให้เรามั่นใจได้ว่าการเปลี่ยนแปลงของเราไม่ได้ทำให้เกิดข้อผิดพลาดใหม่ๆ

การวัด Code Coverage ด้วย PHPUnit

PHPUnit มีเครื่องมือที่ช่วยให้เราวัด Code Coverage ได้อย่างง่ายดาย โดยเราสามารถใช้คำสั่ง --coverage-html หรือ --coverage-clover เพื่อสร้างรายงาน Code Coverage ในรูปแบบ HTML หรือ XML ตามลำดับ

ตัวอย่างการใช้งาน:

สมมติว่าเรามีโปรเจกต์ PHP ที่มีโครงสร้างดังนี้:

my-project/
├── src/
│   └── Calculator.php
└── tests/
    └── CalculatorTest.php

ไฟล์ src/Calculator.php มีโค้ดดังนี้:

<?php

namespace App;

class Calculator
{
    public function add(int $a, int $b): int
    {
        if ($a > 100) {
            return $a;
        }
        return $a + $b;
    }
}

และไฟล์ tests/CalculatorTest.php มีโค้ดดังนี้:

<?php

namespace Tests;

use App\Calculator;
use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase
{
    public function testAdd()
    {
        $calculator = new Calculator();
        $result = $calculator->add(2, 3);
        $this->assertEquals(5, $result);
    }
}

ในการวัด Code Coverage เราสามารถรันคำสั่ง PHPUnit ดังนี้:

./vendor/bin/phpunit --coverage-html coverage

คำสั่งนี้จะทำการรัน test case ทั้งหมด และสร้างรายงาน Code Coverage ในรูปแบบ HTML ภายใน directory ชื่อ coverage

การตีความผลลัพธ์ Code Coverage

หลังจากที่รันคำสั่ง PHPUnit พร้อมกับ option --coverage-html แล้ว เราจะได้ directory ที่มีไฟล์ HTML หลายไฟล์ ซึ่งเป็นรายงาน Code Coverage ของเรา ไฟล์ที่สำคัญที่สุดคือ index.html ซึ่งเป็นหน้าแรกของรายงาน

ในหน้าแรกของรายงาน เราจะเห็นภาพรวมของ Code Coverage ของทั้งโปรเจกต์ โดยจะแสดงเป็นเปอร์เซ็นต์ของ:

  • Lines: จำนวนบรรทัดของโค้ดที่ถูกทดสอบ
  • Statements: จำนวน statement (คำสั่ง) ที่ถูกทดสอบ
  • Branches: จำนวน branch (ทางเลือก) ที่ถูกทดสอบ (เช่น if/else statements)
  • Functions and Methods: จำนวนฟังก์ชันและเมธอดที่ถูกทดสอบ
  • Classes and Traits: จำนวนคลาสและ trait ที่ถูกทดสอบ

หากเราคลิกที่ชื่อไฟล์ (เช่น Calculator.php) เราจะเห็นรายละเอียดของ Code Coverage สำหรับไฟล์นั้นๆ โดยจะมีการไฮไลท์โค้ดด้วยสีต่างๆ:

  • สีเขียว: โค้ดส่วนนี้ถูกทดสอบแล้ว
  • สีแดง: โค้ดส่วนนี้ยังไม่ได้ถูกทดสอบ
  • สีเหลือง: โค้ดส่วนนี้ถูกทดสอบบางส่วน (เช่น branch ที่ไม่ได้ถูกทดสอบทั้งหมด)

จากตัวอย่างโค้ด Calculator.php และ CalculatorTest.php ข้างต้น จะเห็นว่า test case ของเราทดสอบเฉพาะกรณีที่ $a น้อยกว่าหรือเท่ากับ 100 เท่านั้น ดังนั้น โค้ดส่วนที่ $a > 100 จะถูกไฮไลท์เป็นสีแดงในรายงาน Code Coverage

ตัวอย่างรายงาน Code Coverage:

สมมติว่ารายงาน Code Coverage ของเราแสดงผลดังนี้:

Lines:       80.00% (8/10)
Statements:  75.00% (6/8)
Branches:    50.00% (1/2)
Functions:   100.00% (1/1)
Classes:     100.00% (1/1)

จากรายงานนี้ เราสามารถสรุปได้ว่า:

  • 80% ของบรรทัดโค้ดถูกทดสอบแล้ว
  • 75% ของ statement ถูกทดสอบแล้ว
  • 50% ของ branch ถูกทดสอบแล้ว (แสดงว่ามีบางเงื่อนไขที่เรายังไม่ได้ทดสอบ)
  • 100% ของฟังก์ชันและคลาสถูกทดสอบแล้ว

เพื่อให้ Code Coverage สูงขึ้น เราจะต้องเขียน test case เพิ่มเติมเพื่อครอบคลุมโค้ดส่วนที่ยังไม่ได้ทดสอบ ในกรณีนี้ เราจะต้องเขียน test case ที่ทดสอบกรณีที่ $a > 100 ด้วย

แก้ไข tests/CalculatorTest.php:

<?php

namespace Tests;

use App\Calculator;
use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase
{
    public function testAdd()
    {
        $calculator = new Calculator();
        $result = $calculator->add(2, 3);
        $this->assertEquals(5, $result);
    }

    public function testAddWhenAIsGreaterThan100()
    {
        $calculator = new Calculator();
        $result = $calculator->add(101, 3);
        $this->assertEquals(101, $result);
    }
}

หลังจากเพิ่ม test case แล้ว ให้รันคำสั่ง PHPUnit อีกครั้ง:

./vendor/bin/phpunit --coverage-html coverage

รายงาน Code Coverage ควรจะแสดงผลเป็น:

Lines:       100.00% (10/10)
Statements:  100.00% (8/8)
Branches:    100.00% (2/2)
Functions:   100.00% (1/1)
Classes:     100.00% (1/1)

ซึ่งหมายความว่าเราได้ทดสอบโค้ดทั้งหมดแล้ว และ Code Coverage ของเราคือ 100%

ข้อควรระวังในการใช้ Code Coverage

ถึงแม้ว่า Code Coverage จะเป็นเครื่องมือที่มีประโยชน์ แต่ก็มีข้อควรระวังในการใช้งาน:

  • Code Coverage สูงไม่ได้หมายความว่าโค้ดไม่มีข้อผิดพลาด: Code Coverage เพียงแค่บอกว่าโค้ดส่วนไหนถูกทดสอบแล้ว แต่ไม่ได้บอกว่า test case เหล่านั้นมีคุณภาพดีหรือไม่ เราอาจมี Code Coverage 100% แต่ test case ของเราอาจไม่ได้ครอบคลุมทุกกรณีที่เป็นไปได้
  • อย่าให้ความสำคัญกับ Code Coverage มากเกินไป: การพยายามเพิ่ม Code Coverage ให้สูงโดยไม่คำนึงถึงคุณภาพของ test case อาจทำให้เราเสียเวลาไปกับการเขียน test case ที่ไม่มีประโยชน์ และอาจทำให้โค้ดของเราซับซ้อนขึ้น
  • Code Coverage เป็นเพียงเครื่องมือช่วย: Code Coverage เป็นเพียงเครื่องมือที่ช่วยให้เราวัดคุณภาพของการทดสอบ แต่ไม่ได้เป็นตัวตัดสินว่าโค้ดของเรามีคุณภาพดีหรือไม่ การตัดสินใจว่าโค้ดของเรามีคุณภาพดีหรือไม่ ควรพิจารณาจากหลายปัจจัย เช่น ความสามารถในการอ่าน ความสามารถในการบำรุงรักษา และความสามารถในการแก้ไขปัญหา

สรุป

Code Coverage เป็นเครื่องมือที่มีประโยชน์ในการวัดคุณภาพของการทดสอบ ช่วยให้เราเห็นภาพรวมว่าเราได้ทดสอบโค้ดส่วนไหนบ้าง และส่วนไหนที่ยังขาดอยู่ การใช้ Code Coverage ร่วมกับการเขียน test case ที่มีคุณภาพ จะช่วยให้เรามั่นใจได้ว่าโค้ดของเรามีคุณภาพดีและมีโอกาสเกิดข้อผิดพลาดน้อย ในบทถัดไป เราจะมาเรียนรู้เกี่ยวกับเทคนิคการปรับปรุงโค้ดให้สะอาด (Clean Code) และอ่านง่าย ซึ่งเป็นสิ่งสำคัญในการพัฒนาซอฟต์แวร์ที่มีคุณภาพครับ

Office.in.th Custom Service

ต้องการพัฒนาระบบหรือปรับแต่งจากโครงสร้างนี้?

Office.in.th รับพัฒนาและออกแบบ Enterprise Web Application, API Integration และระบบบริหารงานภาครัฐ/เอกชน พร้อมการสนับสนุนระยะยาว

ดูบริการรับพัฒนาซอฟต์แวร์