Nafies Luthfi

Life will always feel wonderful if we always think positively.

Testing Laravel: Definisi Fitur dan First Failing Test

Bismillahirrahmanirrahim

Sebelumnya kita membahas setup project baru laravel dengan testing, sekarang kita lanjutkan membuat definisi dari fitur yang akan kita buat. Pada tutorial TDD ini, ceritanya kita akan membuat Fitur CRUD Task atau Create, Read, Update, and Delete Task.

Pada penerapan TDD, proses yang kita lakukan saat membuat sebuah fitur kurang lebih seperti ini (mulai perencanaan hingga implementasi) :

  1. Mendefinisikan fitur.
  2. Memprioritas sub-fitur.
  3. Membuat kelas TestCase fitur.
  4. Membuat method test untuk masing-masing sub-fitur.
  5. Mulai membuat failing test untuk method test.
  6. Mulai kerjakan (menulis kode) fitur pada aplikasi sampai failing test menjadi passed test.
  7. Ulangi langkah 4 s/d 6 hingga fitur selesai dibuat.

1. Definisi Fitur

Mendefinisikan sama dengan menentukan/menyusun spesifikasi dari fitur yang kita ingin buat. Kali ini kita akan membuat fitur CRUD Task dengan spesifikasi sebagai berikut :

  • Record pada database disimpan dalam tabel tasks dengan atribut name, description, dan is_done
  • Atribut is_done : 0 belum dikerjakan, 1 sudah dikerjakan.
  • User dapat melihat daftar Task
  • User dapat menginput Task baru
  • User dapat meng-edit Task
  • User dapat menghapus Task

2. Menyusun Prioritas Sub-fitur

Berikutnya kita susun prioritas pengerjaan fitur/sub-fitur mana yang kita kerjakan duluan dari spesifikasi di atas, dilengkapi dengan rencana konsep pengoperasian oleh user.

  1. Input Task
    Untuk melakukan Input Task baru, user membuka halaman Daftar Task, kemudian mengisi form name dan description, klik tombol “Create Task”. Setelah berhasil, record Task tersimpan ke database, user redirect ke halaman Daftar Task, dan melihat Task yang telah diinput tampil pada halaman webnya.
  2. Lihat Daftar Task
    Jika ada record Task di dalam database, kemudian user membuka halaman Daftar Task. Muncul nama dan deskripsi Task yang ada.
  3. Edit/Update Task
    Jika ada record Task di dalam database, kemudian user membuka halaman Daftar Task, User meng-klik tombol “Edit Task”, mengubah name dan description kemudian tekan tombol “Update Task”. Setelah berhasil, record tersimpan di database, user redirect ke halaman Daftar Task, dan melihat Task yang telah diupdate pada halaman webnya.
  4. Hapus Task
    Jika ada record Task di dalam database, kemudian user membuka halaman Daftar Task, User melihat tombol “Delete Task”. User meng-klik tombol “Delete Task”. Setelah berhasil, user redirect ke halaman Daftar Task, record Task tidak tampil dan hilang dari database.

Penyusunan prioritas ini penting, agar kita tahu sub-fitur mana yang mesti dikerjakan terlebih dahulu dibandingkan dengan sub-fitur yang lain. Ini melatih kita (sebagai developer) untuk efisien waktu dan manajemen project. Lama-kelamaan kita bisa dengan mudah meng-estimasi lama pengerjaan dari sebuah fitur dengan spesifikasi tertentu.

3. Membuat Kelas TestCase

Kelas TestCase adalah kelas testing untuk sebuah fitur, yang dibuat untuk mengelompokkan pengujian sub-sub fiturnya. Misal kita ingin membuat sebuah kelas testing untuk fitur Kalkulator, maka kelas TestCase yang kita buat bernama KalkulatorTest. Di dalam kelas KalkulatorTest terdapat method-method test untuk masing-masing sub-fitur dari kalkulator tersebut.

Baik, kita lanjut. Pada terminal, kita cd ke direktori Project Laravel, kemudian jalankan testing untuk memastikan testing yang sudah ada berjalan dengan baik :

$ vendor/bin/phpunit

Before Add ManageTasksTest{:style=“width:100%”}

Hasilnya, 2 tests dan 2 assertions, sama seperti kondisi akhir artikel sebelumnya.

Untuk membuat TestCase baru, kita berikan perintah :

$ php artisan make:test ManageTasksTest

Laravel membuat TestCase pada direktori tests/Feature bernama ManageTasksTest.php.

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ManageTasksTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testExample()
    {
        $this->assertTrue(true);
    }
}

Sekarang kita coba jalankan lagi testingnya :

$ vendor/bin/phpunit

Add ManageTasksTest{:style=“width:100%”}

Oke, sudah ada 3 tests dan 3 assertions artinya kelas ManageTasksTest sudah jalan. Sampai disini kita lanjutkan membuat method-method testingnya.

Akhiran (suffix) Test wajib untuk setiap nama kelas TestCase. Karena tanpa suffix Test, PHPUnit tidak mengenali kelas tersebut sebagai kelas testing yang harus dijalankan. Referensi.

4. Membuat Method Test

Method Test atau Test Method adalah method-method pada kelas TestCase yang akan dijalankan oleh PHPUnit. Untuk mempermudah pemahaman kita, satu Test Method itu sama dengan pengujian untuk satu sub-fitur. Jadi kita akan membuat :

  • Satu Test Method untuk Input Task
  • Satu Test Method untuk Lihat Daftar Task
  • Satu Test Method untuk Edit Task
  • Satu Test Method untuk Hapus Task

Baik kita edit file kelas tests/Feature/ManageTasksTest.php dan kita update seperti ini :

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ManageTasksTest extends TestCase
{
    /** @test */
    public function user_can_create_a_task()
    {
        $this->assertTrue(true);
    }

    /** @test */
    public function user_can_browser_tasks_index_page()
    {
        $this->assertTrue(true);
    }

    /** @test */
    public function user_can_edit_an_existing_task()
    {
        $this->assertTrue(true);
    }
    
    /** @test */
    public function user_can_delete_an_existing_task()
    {
        $this->assertTrue(true);
    }
}

Ingat, satu test method mewakili satu sub-fitur :

  • user_can_create_a_task untuk Input Task
  • user_can_browser_tasks_index_page untuk Lihat Daftar Task
  • user_can_edit_an_existing_task untuk Edit Task
  • user_can_delete_an_existing_task untuk Hapus Task

Sekarang kita jalankan lagi PHPUnit-nya, seharusnya kita mendapat hasil seperti berikut :

After add test methods{:style=“width:100%”}

“Hijau” ya? Baik, sampai di sini kita punya 4 sub-fitur dengan Test Method masing-masing untuk fitur CRUD Task.

Syarat sebuah test method : harus berupa public method dan nama method harus diawali dengan test atau diberikan anotasi @test pada docblock method. Referensi.

5. Membuat “Failing Test”

Sekarang kita fokus ke method user_can_create_a_task() untuk membuat failing test, yaitu script testing yang kita buat ini untuk menguji fitur yang belum ada di sistem, jadi pasti gagal (fail).

Oke, untuk mempermudah membuat script testing, kita buat beberapa perumpamaan langkah/proses yang dilakukan oleh user ketika menggunakan sub-fitur tersebut dengan PHP comment line. Seperti ini :

<?php
// Kelas ManageTasksTest.php

    /** @test */
    public function user_can_create_a_task()
    {
        // User buka halaman Daftar Task

        // Isi form `name` dan `description` kemudian submit

        // Lihat Record tersimpan ke database

        // Redirect ke halaman Daftar Task

        // Tampil hasil task yang telah diinput
    }

Metode ini saya pelajari dari video youtube Laravel Daily.

Setelah membuat comment seperti di atas, kita coba buat testing script-nya untuk masing-masing langkah ini.

<?php
// Kelas ManageTasksTest.php

    /** @test */
    public function user_can_create_a_task()
    {
        // User memngunjungi halaman Daftar Task
        $this->visit('/tasks');
        
        // Isi form `name` dan `description` kemudian submit
        $this->submitForm('Create Task', [
            'name' => 'My First Task',
            'description' => 'This is my first task on my new job.',
        ]);
        
        // Lihat Record tersimpan ke database
        $this->seeInDatabase('tasks', [
            'name' => 'My First Task',
            'description' => 'This is my first task on my new job.',
            'is_done' => 0,
        ]);
        
        // Redirect ke halaman Daftar Task
        $this->seePageIs('/tasks');

        // Tampil hasil task yang telah diinput
        $this->see('My First Task');
        $this->see('This is my first task on my new job.');
    }

Kita bisa lihat, setiap langkah/proses yang seharusnya dilakukan oleh user (manusia) kita gantikan dengan testing script yang sesuai :

  1. $this->visit('/tasks'); untuk mengunjungi halaman dengan URL tertentu.
  2. $this->submitForm('Create Task', ... untuk mengisi form dan klik tombol “Create Task”.
  3. $this->seePageIs('/tasks'); melihat URL yang kita dapatkan setelah action sebelumnya.
  4. $this->seeInDatabase('tasks', ... melihat isi tabel tasks pada database.
  5. $this->see('.....'); melihat isi tulisan yang tampil di halaman web.

Oke, jika kita jalankan kembali PHPUnitnya :

$ vendor/bin/phpunit 

Hasilnya? First Failing Test 01{:style=“width:100%”}

First Failing Test 02{:style=“width:100%”}

Yap kita dapat “Merah”, “failing test” pertama berhasil dibuat :)

Pada error ini, yang kita perhatikan adalah tulisan-tulisan pada posisi saya garis bawahi pada gambar di atas :

  1. Tulisan di bawah Kelas dan method test
  2. Status Code yang didapatkan
  3. Baris keberapa pada Kelas Test kita mendapatkan error ini
  4. Disebabkan oleh apa error ini terjadi.

Dengan memperhatikan 4 hal di atas, kita bisa tahu, apa yang menyebabkan error ini terjadi, sehingga kita dapat memperbaiki kode di aplikasi yang kita buat. Untuk error yang pertama ini, kita mendapatkan NotFoundHttpException, artinya route untuk URL /tasks itu tidak ditemukan.

Untuk membuktikannya, sekarang coba kita buka halaman webnya :

$ php artisan serve
Laravel development server started: <http://127.0.0.1:8000>

Kita coba buka URL di browser : http://127.0.0.1:8000/tasks.

Open in Browser

Setiap error yang tampil pada terminal saat kita menjalankan test, umumnya sama dengan tampilan error yang muncul di layar web. Pesan di atas sama dengan NotFoundHttpException dan status code = 404, hanya saja dihandle oleh Laravel dengan menampilkan halaman error 404.

Baik, sampai di sini cukup dulu. Insyaallah pada artikel berikutnya, kita akan menulis kode aplikasi untuk sub-fitur input Task, sampai testing method user_can_create_a_task() mendapatkan hasil “Hijau”.

Jika ada yang kurang jelas dengan penjelasan dan tutorial pada artikel ini, atau ada hal yang keliru, mohon disampaikan pada komentar.

Terima kasih untuk waktu teman-teman berkenan membaca.

Source untuk kelas ManageTasksTest dapat dilihat commit github ini.