Ứng dụng Testing

Giới thiệu

Laravel cung cấp một API khá tiện để làm cho các HTTP requests đến ứng dụng, kiểm tra đầu ra, và cả thông tin điền vào form. Ví dụ, xem định nghĩa test sau đây:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return  void
     */
    public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5')
             ->dontSee('Rails');
    }
}

Hàm visit tạo một request GET vào ứng dụng. Hàm see khẳng định rằng chúng ta nên xem text được đưa ra trong response trở lại ứng dụng. Hàm dontSee khẳng định rằng text đã cho không được trả lại response. Đó là một test cơ bản nhất tồn tại trong Laravel.

Bạn có thể sử dụng hàm 'visitRoute' để tạo một 'GET' request qua tên route:

$this->visitRoute('profile');

$this->visitRoute('profile', ['user' => 1]);

Tương tác với ứng dụng

Tất nhiên, bạn có thể làm nhiêu hơn khẳng định các text xuất hiện trong response. Hãy xem một số ví dụ về clicking links và điền forms:

Tương tác với Links

Trong test này, chúng ta sẽ tạo một request đến ứng dụng, "click" một link trả về response, và sau đó chúng ta khẳng định rằng đã click vào URI. Ví dụ, giả sử link trong response của chúng ta có giá trị text là "About Us":

<a href="/about-us">About Us</a>

Bây giờ, hãy viết một test khi user click vào link và khẳng định rằng user đã click đúng trang:

public function testBasicExample()
{
    $this->visit('/')
         ->click('About Us')
         ->seePageIs('/about-us');
}

Bạn có thể kiểm tra user có đến đúng tên route bằng hàm seeRouteIs:

->seeRouteIs('profile', ['user' => 1]);

Tương tác với Forms

Laravel ngoài ra còn cung cấp một vài phương thức cho testing forms. Hàm type, select, check, attach, và press cho phép bạn tương tác với tất cả form's inputs. Ví dụ, hãy tưởng tương tồn tại form trong trang đăng ký của ứng dụng:

<form action="/register" method="POST">
    {{ csrf_field() }}

    <div>
        Name: <input type="text" name="name">
    </div>

    <div>
        <input type="checkbox" value="yes" name="terms"> Accept Terms
    </div>

    <div>
        <input type="submit" value="Register">
    </div>
</form>

Chúng ta có thể viết test để hoàn thành form và quan sát result:

public function testNewUserRegistration()
{
    $this->visit('/register')
         ->type('Taylor', 'name')
         ->check('terms')
         ->press('Register')
         ->seePageIs('/dashboard');
}

Tất nhiên, nếu form chứa một số inputs khác như radio buttons hoặc drop-down boxes, bạn có thể dễ dàng tìm ra types của nó. Đây là danh sách các hàm thao tác form:

Phương thức Miêu tả
$this->type($text, $elementName) "Type" text vào một trường đã cho.
$this->select($value, $elementName) "Select" trường radio button hoặc drop-down.
$this->check($elementName) "Check" trường checkbox.
$this->uncheck($elementName) "Uncheck" trường checkbox.
$this->attach($pathToFile, $elementName) "Attach" một file vào form.
$this->press($buttonTextOrElementName) "Press" một button với giá trị text hoặc tên.

File Inputs

Nếu form chứa file inputs, bạn có thể đính kèm files vào form sử dụng hàm attach:

public function testPhotoCanBeUploaded()
{
    $this->visit('/upload')
         ->attach($pathToFile, 'photo')
         ->press('Upload')
         ->see('Upload Successful!');
}

Testing JSON APIs

Laravel ngoài ra còn cung cấp một vài helpers cho testing JSON APIs và responses của nó. Ví dụ, phương thức json, get, post, put, patch, và delete có thể sử dụng để gửi requests với HTTP verbs. Bạn có thể dễ dàng truyền dữ liệu và headers vào các phương thức đó. Để bắt đầu, hãy viết một test để khẳng định POST request đến /user và khẳng định data được trả về:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return  void
     */
    public function testBasicExample()
    {
        $this->json('POST', '/user', ['name' => 'Sally'])
             ->seeJson([
                 'created' => true,
             ]);
    }
}

Hàm seeJson chuyển một mảng thành JSON, và sau đó gửi tất cả các JSON fragment ra anywhere bên trong JSON response kết quả trả về. Vì vậy, nếu có các thuộc tính khác trong JSON response, test này sẽ vẫn truyền như bình thường.

Xác minh khớp Exact

Nếu bạn muốn xác minh một mảng khớp với exact kết quả JSON trả về, bạn có thể sử dụng hàm seeJsonEquals:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return  void
     */
    public function testBasicExample()
    {
        $this->json('POST', '/user', ['name' => 'Sally'])
             ->seeJsonEquals([
                 'created' => true,
             ]);
    }
}

Xác minh khớp cấu trúc

Nó cũng có thể xác minh một JSON response tuân thủ theo đúng cấu trúc. Trong trường hợp này, bạn có thể sử dụng hàm seeJsonStructure và truyền vào cấu trúc JSON mong muốn:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return  void
     */
    public function testBasicExample()
    {
        $this->get('/user/1')
             ->seeJsonStructure([
                 'name',
                 'pet' => [
                     'name', 'age'
                 ]
             ]);
    }
}

Ví dụ trên muốn kết quả nhận được có thuộc tính name lồng bên trong đối tượng pet name và thuộc tính age. seeJsonStructure sẽ không thất bại nếu bổ sung thêm các tham số đó trong response. Ví dụ, the test sẽ tiếp tục thành công nếu pet có một thuộc tính weight.

Bạn có thể sử dụng * để khẳng định kết quả JSON trả về có cấu trúc là 1 danh sách các item chưa ít nhất các thộc tính tìm thấy trong tập giá trị:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return  void
     */
    public function testBasicExample()
    {
        // Assert that each user in the list has at least an id, name and email attribute.
        $this->get('/users')
             ->seeJsonStructure([
                 '*' => [
                     'id', 'name', 'email'
                 ]
             ]);
    }
}

Bạn cũng có thể lồng ký hiệu *. Trong trường hợp này, chúng ta sẽ khẳng định mỗi user trong JSON response chưa một giá trị được thiết lập và các thuộc tính pet trên mỗi user cũng có chưa một tập hợp các thuộc tính:

$this->get('/users')
     ->seeJsonStructure([
         '*' => [
             'id', 'name', 'email', 'pets' => [
                 '*' => [
                     'name', 'age'
                 ]
             ]
         ]
     ]);

Sessions / Authentication

Laravel cung cấp một số hàm helpers làm việc với session trong khi testing. Đầu tiên, bạn có thể đặt session data vào một mảng sử dụng hàm withSession. Nó sẽ rất tốn cho việc tải session với dữ liệu trước khi có request đến ứng dụng:

<?php

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $this->withSession(['foo' => 'bar'])
             ->visit('/');
    }
}

Tất nhiên, thường sử dụng session là để duy trì authenticated user. Hàm actingAs cung cấp một cách đơn giải để authenticate người dùng như là user hiện tại. Ví dụ, chúng ta sử dụng một model factory để tạo và authenticate một user:

<?php

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $user = factory(App\User::class)->create();

        $this->actingAs($user)
             ->withSession(['foo' => 'bar'])
             ->visit('/')
             ->see('Hello, '.$user->name);
    }
}

Ngoài ta bạn có thể sử dụng guard cụ thể để authenticate user bằng cách truyền qua tên guard như là tham số thứ 2 vào hàm actingAs:

$this->actingAs($user, 'api')

Vô hiệu hóa Middleware

Khi testing ứng dụng, bạn có thể nó thuận tiện để vô hiệu hóa middleware cho một số tests. nó sẽ cho phép bạn test routes và controller mà không có middleware. Laravel đã có một trait WithoutMiddleware bạn có thể sử dụng để tự động vô hiệu hóa middleware cho test class:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use WithoutMiddleware;

    //
}

Nếu bạn chỉ muốn vô hiệu hóa duy nhất một middleware cho vài hàm test, bạn có thể gọi hàm withoutMiddleware bên trong hàm test:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return  void
     */
    public function testBasicExample()
    {
        $this->withoutMiddleware();

        $this->visit('/')
             ->see('Laravel 5');
    }
}

Tùy biến HTTP Requests

Nếu bạn muốn tạo một tùy biến HTTP request trong ứng dụng và lấy cả đối tượng Illuminate\Http\Response bạn có thể sử dụng hàm call:

public function testApplication()
{
    $response = $this->call('GET', '/');

    $this->assertEquals(200, $response->status());
}

Nếu bạn đang tạo POST, PUT, hoặc PATCH requests bạn có truyền vào một input data bên trong request.Tất nhiên, data sẽ tồn tại trong routes và controller qua Request instance:

   $response = $this->call('POST', '/user', ['name' => 'Taylor']);

PHPUnit Assertions

Laravel cung cấp một vài hàm tùy biến khẳng định cho PHPUnit tests:

Phương thưc Miêu tả
->assertResponseOk(); Khẳng đinh client response có mã code OK.
->assertResponseStatus($code); Khẳng định client response có code.
->assertViewHas($key, $value = null); Khẳng định response view có một phần dữ liệu ràng buộc.
->assertViewHasAll(array $bindings); Khẳng định view has có một danh sách dữ liệu ràng buộc.
->assertViewMissing($key); Khẳng định response view thiếu một phần dữ liệu ràng buộc.
->assertRedirectedTo($uri, $with = []); Khẳng định liệu client đã chuyển về URI chưa.
->assertRedirectedToRoute($name, $parameters = [], $with = []); Khẳng định liệu client đã chuyển về một route chưa.
->assertRedirectedToAction($name, $parameters = [], $with = []); khẳng định liệu client đã chuyển về một action chưa.
->assertSessionHas($key, $value = null); Khẳng định một session có giá trị.
->assertSessionHasAll(array $bindings); Khẳng định session có một danh dách giá trị.
->assertSessionHasErrors($bindings = [], $format = null); Khẳng định session có lỗi ràng buộc.
->assertHasOldInput(); Khẳng định session có old input.
->assertSessionMissing($key); Khẳng định session lỗi key.
Nguồn: https://laravel.com/docs/5.3/application-testing