Testing Laravel: Menggunakan Model Factory
Bismillahirrahmanirrahim
Di beberapa artikel sebelumnya kita masih bicara seputar satu fitur, yaitu Input Task. Sekarang kita akan membuat testing agar user dapat melihat daftar Task yang ada. Sebenarnya fitur ini secara tidak langsung sudah ada pada tahap pengerjaan fitur sebelumnya, kita sudah dapat melihat daftar task. Tetapi kali ini kita membuat task tanpa harus input task dari form. Kita akan memanfaatkan Model Factory Laravel untuk meng-generate beberapa task pada testing.
Model Factory adalah fitur yang berfungsi untuk membuat instance dari kelas model laravel dengan atribut-atribut yang sesuai dengan kolom-kolom tabel yang sesuai pada database. Setiap penggunaan model factory akan menghasilkan instance model atau collection (list) dari beberapa model yang sama.
Pada artikel Definisi Fitur, kita sudah membuat sebuah test method untuk artikel ini, yaitu user_can_browse_tasks_index_page
. Isinya hanya $this->assertTrue(true);
, sebuah assert sederhana agar test method ini passed
(untuk sementara waktu). Kita akan bekerja pada method test ini.
<?php
// ...
class ManageTasksTest extends TestCase
{
// ... user_can_create_a_task()
/** @test */
public function user_can_browse_tasks_index_page()
{
$this->assertTrue(true);
}
// ... user_can_edit_an_existing_task()
// ... user_can_delete_an_existing_task()
}
Sebelum mulai kerja, kita jalankan dulu PHPUnit, untuk memastikan aplikasi tidak ada masalah.
# 1
$ vendor/bin/phpunit
OK (7 tests, 13 assertions)
Membuat Test Method
Sekarang kita lanjut mendefinisikan langkah dalam testing method tersebut (dalam bentuk PHP comment line) sesuai yang kita inginkan. Seperti ini :
<?php
/** @test */
public function user_can_browse_tasks_index_page()
{
// Generate 3 record task pada table `tasks`.
// User membuka halaman Daftar Task.
// User melihat ketiga task tampil pada halaman.
// User melihat link untuk edit task pada masing-masing item task.
}
}
Baik, itu misinya, sekarang kita buat script untuk memenuhi langkah tersebut.
<?php
// ...
use App\Task; // Tambahkan ini
class ManageTasksTest extends TestCase
{
// ... user_can_create_a_task()
/** @test */
public function user_can_browse_tasks_index_page()
{
// Generate 3 record task pada table `tasks`.
$tasks = factory(Task::class, 3)->create();
// User membuka halaman Daftar Task.
$this->visit('/tasks');
// User melihat ketiga task tampil pada halaman.
$this->see($tasks[0]->name);
$this->see($tasks[1]->name);
$this->see($tasks[2]->name);
// User melihat link untuk edit task pada masing-masing item task.
// <a href="/tasks?action=edit&id=1" id="edit_task_1">edit</a>
$this->seeElement('a', [
'id' => 'edit_task_'.$tasks[0]->id,
'href' => url('tasks?action=edit&id='.$tasks[0]->id)
]);
// <a href="/tasks?action=edit&id=2" id="edit_task_2">edit</a>
$this->seeElement('a', [
'id' => 'edit_task_'.$tasks[1]->id,
'href' => url('tasks?action=edit&id='.$tasks[1]->id)
]);
// <a href="/tasks?action=edit&id=3" id="edit_task_3">edit</a>
$this->seeElement('a', [
'id' => 'edit_task_'.$tasks[2]->id,
'href' => url('tasks?action=edit&id='.$tasks[2]->id)
]);
}
}
Jangan lupa
use App\Task;
di atas kelas ManageTasksTest.
Oke, kita jalankan PHPUnit untuk mendapatkan error pertama.
# 2
$ vendor/bin/phpunit
Hasil: Error
InvalidArgumentException: Unable to locate factory with name [default] [App\Task].
Penyebab
Kita belum memiliki model factory untuk model App\Task
.
Solusi
Kita belum buat model factory untuk model App\Task
.
Membuat Model Factory “App\Task”
$ php artisan make:factory TaskFactory --model=Task
Laravel akan membuat database/factories/TaskFactory.php
. Kita edit file tersebut dan tambahkan atribut name
dan description
untuk model App\Task
.
<?php
use Faker\Generator as Faker;
$factory->define(App\Task::class, function (Faker $faker) {
return [
'name' => $faker->word,
'description' => $faker->sentence,
];
});
Jalankan PHPUnit.
# 3
$ vendor/bin/phpunit
Hasil: Error
Failed asserting that the page contains the element [a] with the attributes
{"id":"edit_task_1","href":"http:\/\/localhost\/tasks?action=edit&id=1"}.
Please check the content above.
Penyebab
Kita belum membuat link untuk edit masing-masing task.
Solusi
Buka view tasks.index
atau file resources/views/tasks/index.blade.php
, kita buat link untuk edit masing-masing task.
<!-- resources/views/tasks/index.blade.php -->
<h2>Tasks</h2>
<ul class="list-group">
@foreach ($tasks as $task)
<li class="list-group-item">
<a
href="{% raw" >}}{{ url('tasks') }}{% endraw" >}}?action=edit&id={% raw" >}}{{ $task->id }}{% endraw" >}}"
id="edit_task_{% raw" >}}{{ $task->id }}{% endraw" >}}"
class="pull-right">
edit
</a>
{% raw" >}}{{ $task->name }}{% endraw" >}} <br>
{% raw" >}}{{ $task->description }}{% endraw" >}}
</li>
@endforeach
</ul>
Jalankan PHPUnit.
# 4
$ vendor/bin/phpunit
OK (7 tests, 22 assertions)
Sip, sekarang sudah dapat Hijau
. Artinya ketiga task yang kita generate dengan model factory tadi sudah muncul pada halaman web, beserta link edit nya masing-masing.
Sekarang coba kita buka aplikasi melalui browser, kita lihat tampilannya setelah ditambahkan link edit seperti ini.
Sampai di sini proses TDD kita untuk fitur melihat daftar Task.
Kita lanjut bahas sedikit tentang beberapa method assert yang kita gunakan di atas.
Method “$this->see()”
Method $this->see()
adalah method assert browserkit untuk melihat teks pada halaman html. Method ini kita gunakan untuk melihat teks apapun yang kita ingin lihat pada halaman web, baik di dalam tag heading, paragraf, form, label, div, dan lain-lain.
Contoh
$this->see('123');
akan passed
jika di dalam halaman terdapat :
<h1>Rp. 123.000</h1>
<p>Testing 123</p>
<span class="badge">Status 123</span>
Method “$this->seeElement()”
Method $this->seeElement()
adalah method assert browserkit untuk melihat element pada halaman html. Method ini kita gunakan untuk melihat apakah terdapat elemen tersebut (beserta atributnya) dalam halaman html.
Contoh Passed
$this->seeElement('h1', ['class' => 'page-header', 'id' => 'judul-halaman']);
akan passed
jika di dalam halaman terdapat :
<h1 class="page-header" id="judul-halaman">Rp. 123.000</h1>
<h1 class="page-header" id="judul-halaman">Judul Halaman</h1>
$this->seeElement('button', ['class' => 'btn btn-info']);
akan passed
jika di dalam halaman terdapat :
<button class="btn btn-info">Submit</h1>
<button class="btn btn-info" id="judul-halaman">Simpan</h1>
Contoh Failed
$this->seeElement('h1', ['class' => 'page-header', 'id' => 'judul-halaman']);
akan failed
jika di dalam halaman hanya terdapat :
<h1 class="page-header">Rp. 123.000</h1>
<h1 id="judul-halaman">Judul Halaman</h1>
Oke, mudah-mudahan teman-teman yang mencoba praktek artikel ini mendapatkan hasil yang sesuai dengan proses di atas. Jika menemui kendala atau ada keliru dalam proses di atas, silakan disampaikan melalui komentar.
Selanjutnya kita akan mengerjakan Form Edit Task dari link edit yang sudah dibuat di atas. Terima kasih atas waktunya.