Ví dụ viết 1 Unit Test trong PHP

Việc thiết kế chương trình để có thể test được nên được nhìn dưới khía cạnh, source code nên được tổ chức thành các function mà bản thân nó có input và output xác định, mỗi function phải là đơn vị nhỏ nhất.

Vì nếu không vậy chúng ta có thể sẽ phải viết một cái PHPUnit khác để test chính cái PHPUnit của chúng ta :D (Nói như chị Phan Hoàng Anh trưởng bộ phận IT của Officience)

Bài viết này vẫn còn ở mức độ là đề cập đến việc ứng dụng PHPUnit vào ứng dụng/website của bạn như thế và các ví dụ này để các bạn có thể hình dung được. Có một số trở ngại nhất định dành cho những ai không cài được PHPUnit trên máy tính của mình và cái đó sẽ được bàn ở một bài viết sau, về chuyện cài PHPUnit trên các nền tảng Windows, Linux với các gói bình thường và bộ xampp/lampp đi kèm. Nhưng cái đó sẽ là ở một bài khác. Bài này tôi cũng chỉ muốn nói về việc ứng dụng Unit Test như thế nào.

Giả sử ở rằng bạn có một class như sau:
 

class YouTube
{
    /**
    * Use to get the key from YouTube url
    *@example
    *    input: http://www.youtube.com/watch?v=DP9HlGB7Sy8&feature=g-vrec
    *    output: DP9HlGB7Sy8
    *@return string
    */
    public function getKeyCode($url)
    {
        $pattern  = '/v=(\w+)/';
        $matches  = array();
        preg_match($pattern, $url, $matches);
        if( isset($matches[1]) )
        {
            return $matches[1];
        }
        return false;
    }
}

Và chúng ta sẽ thực hiện các động tác test nó, bằng cách copy các link của YouTube vào, càng nhiều trường hợp các tốt. Ở đây lưu ý, mặc định thì tham số video id (v=) luôn là tham sau đầu tiên trên URL của YouTube, nhưng để biết function của ta có hoạt động tốt hay không thì chúng ta phải thử các trường hợp khác khi mà video id nằm giữa hoặc nằm cuối URL. Ví dụ như

  • http://www.youtube.com/watch?feature=g-vrec&v=PtayRZmT9Y8&context=G2de0076RVAAAAAAAACw
  • http://www.youtube.com/watch?feature=g-vrec&context=G2de0076RVAAAAAAAACw&v=PtayRZmT9Y8

Một cách test cơ bản mà các bạn có thể dễ dàng hình dung nhất là:
 

include 'YouTube.php';

class YouTubeTest extends PHPUnit_Framework_TestCase
{

    private $youTube;
   
    protected function setUp()
    {
        $this->youTube = new YouTube();
    }

    public function testCase1()
    {
        $url = 'http://www.youtube.com/watch?v=_RRnyChxijA&feature=related&';
        $keyCode = $this->youTube->getKeyCode($url);
        $this->assertEquals('_RRnyChxijA', $keyCode);
    }

    public function testCase2()
    {
        $url = 'http://www.youtube.com/watch?v=-WolCnOLPg8&feature=related';
        $keyCode = $this->youTube->getKeyCode($url);
        $this->assertEquals('-WolCnOLPg8',$keyCode);
    }
}

Đừng thắc mắc là hàm setUp để làm gì, chúng ta khoan bàn về cái đó.

Nhìn vào testCase ta thấy:

Link Key
http://www.youtube.com/watch?v=_RRnyChxijA&feature=related&    _RRnyChxijA
http://www.youtube.com/watch?v=-WolCnOLPg8&feature=related    -WolCnOLPg8

Bảng trên mổ tả dữ liệu nhập vào (mà ở đây là link của YouTube) và kết quả trả về (video id)  mong muốn tương ứng (expected result).

Vậy thì thực hiện việc test xem, kết quả có như ta mong đợi không?

Ví dụ viết 1 Unit Test

Sau khi thực hiện test ta thấy: Hàm getKeyCode() của chúng ta sai trong trường hợp 2.

Link Key Result
http://www.youtube.com/watch?v=_RRnyChxijA&feature=related&    _RRnyChxijA PASSED
http://www.youtube.com/watch?v=-WolCnOLPg8&feature=related    -WolCnOLPg8 FAILED

Bài viết tiếp theo ta sẽ nhìn sâu hơn về các khía cạnh của Unit Test như:

  1.  Nếu như ta có 20 cases để test thì liệu chúng ta phải copy và paste 20 lần hay không?  Đó là vấn đề mà chúng ta sẽ tiếp tìm hiểu trong bài viết tiếp theo.
  2.  Sau đó ta sẽ đề cập đến một số vấn đề khác như:
    • Giả sử chúng ta không có giải pháp, hàm tốt nhất trong mọi trường hợp, thì chính Uni Test sẽ cung cấp cho chúng ta cơ chế để chúng ta biết chọn hàm nào mà nó có thể PASSED nhiều trường hợp hơn. Đây là cơ sở quan trọng để đánh giá và đưa ra sự lựa chọn và giải pháp cho chương trình một cách ít cảm tính nhất.

PhúTP | HưngNQ