12/08/2018, 13:53

Tìm hiểu sơ lược về Unit Test trong framework Symfony

1.Đặt vấn đề Trong một dự án thực tế chúng ta không thể tránh khỏi các lỗi phát sinh trong mỗi module . Vì vậy để có thể phát triển một ứng dụng tốt làm hài lòng khách hàng thì chúng ta nên tìm hiểu và áp dụng Phpunit test trong dự án của mình để có thể tạo ra các sản phẩm có chất lượng tốt ...

1.Đặt vấn đề

Trong một dự án thực tế chúng ta không thể tránh khỏi các lỗi phát sinh trong mỗi module . Vì vậy để có thể phát triển một ứng dụng tốt làm hài lòng khách hàng thì chúng ta nên tìm hiểu và áp dụng Phpunit test trong dự án của mình để có thể tạo ra các sản phẩm có chất lượng tốt hơn.

Đối với một web developer chưa từng được sử dụng test trong công việc thì sẽ đặt ra rất nhiều câu hỏi là : Tôi phải viết test trước khi thực hiện một chức năng? Tôi cần viết test để làm gì? Làm thế nào để có thể tạo ra được một test đúng trong mọi trường hợp?

Vì vậy , hôm nay chúng ta sẽ nói về Unit Test trong framwork Symfony và một ví dụ đơn giản về PHPunit test.

2.Tạo một test đơn giản trong dự án :

Trong framework Symfony chúng ta thường viết unit test trong cùng một folder . Ví dụ :

7108a753ba65e0ce6d1012433c591b0e7b87ca43.png

Trong ví dụ này chúng ta tạo một file test trong thư mục test/phpunit/unit/model có tên là SampleTest.php . Trong function test này chúng ta phải được kế thừa từ class erBasePhpunitTestCase .

Ngoài ra , một điều rất quan trọng trong việc thực thi test đó là sử dụng các dữ liệu cố định (fixture) . Có 2 dạng file fixture đó là DoctrinePropel. Ở trong bài viết này chúng ta sử dụng Doctrine.

Đầu tiên chúng ta tạo dữ liệu test (fixture data) . File có tên là user.doctrine.yml và đặt trong thư mục common để bất kì test case nào cũng có thể sử dụng được.

User:
    User_1:
        name: Loan
        address: Ha Noi
        email: nguyenloan@gmail.com
        role: 1
        password: '123456'
        created_at: 2016-09-21 13:34:52
        updated_at: 2016-09-12 14:38:05
        Product:Product_1
    User_2:
        name: Ha
        address: Ha Tay
        email: ha@gmail.com
        role: 0
        password: '123456'
        created_at: 2016-09-12 15:38:05
        updated_at: 2016-09-12 15:38:05
        Product:Product_2
Product:
    Product_1:
        name: Coca cola
        description: Nuoc giai khat
        price: 10000
        status: 10
        created_at: 2016-10-12 14:38:05
        update_at: 2016-10-12 14:38:05
    Product_2:
        name: Mi Hao
        description: Mi tom
        price: 3000
        status: 40
        created_at: 2016-09-12 14:38:05
        update_at: 2016-09-12 14:38:05

Trong dữ liệu này chúng ta thấy được rằng các bản ghi trong bảng có tên Product_1 tức là nó có khóa ngoài là bản ghi Product_1 . Bản ghi này cũng cần được khai báo trong cùng file fixture.

Trong ví dụ test hôm nay chúng ta sẽ kiểm tra xem phương thức userDelete có được thực thi đúng hay không . Phương thức này muốn xóa một bản ghi trong cơ sở dữ liệu .

public function userDelete($con = null)
{
    if (is_null($con))
    {
      $con = $this->getTable()->getConnection();
    }
    $con->beginTransaction();

    try
    {
      $this->delete($con);

      $con->commit();
    }
    catch (Exception $ex)
    {
      $con->rollback();

      throw $ex;
    }
  }

Bây giờ chúng ta xây dựng 1 file test để test thử phương thức này.

<?php
class UserTest extends erBasePhpunitTestCase implements sfPhpunitFixtureDoctrineAggregator
{
    private static $userTest = array();
    protected function _startOnce()
    {
        $this->fixture()
            ->clean()
            ->loadSnapshot('user');
        self::$userTest[1] = $this->fixture("User_User_1");
        self::$userTest[2] = $this->fixture("User_User_2");
    }

    public function testUserDelete()
    {
        $result = self::$userTest[1]]->userDelete();
        $user = UserTable::getInstance()
                    ->createQuery('a')->select('a.*')
                    ->andWhere('a.id = ?', $id)->fetchOne();
        $this->assertEquals($user, false);
    }
}

Trong class này ta có thể thấy function :

protected function _startOnce()
{
    $this->fixture()
        ->clean()
        ->loadSnapshot('user');
    self::$userTest[1] = $this->fixture("User_User_1");
    self::$userTest[2] = $this->fixture("User_User_2");
}

function này là function của Symfony Plugin cho phép ta khai báo file dữ liệu nào sẽ được sử dụng : Ở đây là file user.doctrine.yml . Khi chạy file test thì PHPunit sẽ chuyển hóa và tạo ra một CSDL tạm thời từ file fixture của chúng ta.

self::$userTest[1] = $this->fixture("User_User_1");
self::$userTest[2] = $this->fixture("User_User_2");

Đây là các bộ dữ liệu dùng để test

Sau đây , ta viết một phương thức test có tên giống với tên phương thức cần test nhưng chú ý phải có chữ test đứng ở đầu

public function testUserDelete()
{
    $result = self::$userTest[1]]->userDelete();
    $user = UserTable::getInstance()
                ->createQuery('a')->select('a.*')
                ->andWhere('a.id = ?', $id)->fetchOne();
    $this->assertEquals($user, false);
}

Kết quả khi chạy

 $ ./symfony phpunit:runtest unit/model/UserTest.php
 PHPUnit 3.4.15 by Sebastian Bergmann.

 ...

Time: 25 seconds, Memory: 120.25Mb

OK (3 tests, 2 assertions)

Lời kết

Như vậy là mình giới thiệu sơ qua về PHPunit test trong symfony . Ngoài ra chúng ta có thể tìm hiểu thêm về dataProvider sẽ giúp chúng ta không phải viết đi viết lại hàm test nhiều lần .

0