Skip to content

Cara Mencapai 100% Code Coverage di Aplikasi Laravel Kita

Published: at 00.00 (4 min read)

Dalam pengembangan perangkat lunak, code coverage adalah metrik yang menunjukkan persentase kode yang telah diuji oleh test suite kita. Nilai yang tinggi pada code coverage dapat menurunkan potensi bug dan meningkatkan kualitas aplikasi. Artikel ini akan membimbing Anda mencapai 100% code coverage di aplikasi Laravel Anda dengan tips dan trik praktis.

Table of contents

Open Table of contents

1. Instalasi Laravel dengan Docker

Laravel fresh installation with Docker

Memulai dengan Laravel yang terinstal menggunakan Docker akan mempermudah pengelolaan lingkungan pengembangan. Berikut adalah perintah untuk memulainya:

docker run --rm \
    --pull=always \
    -v "$(pwd)":/opt \
    -w /opt \
    -it ramageek/image:php8.3-laravel \
    bash -c "/composer/vendor/bin/laravel new laravel"

Gunakan konfigurasi aplikasi Laravel berikut:

Laravel fresh installation: choosing DBMS

2. Mempersiapkan Lingkungan Testing

Anda dapat menyiapkan lingkungan pengujian dengan mengikuti panduan pada video ini: persiapan environment untuk testing di Laravel dengan Pest. Rincian singkatnya:

Shortcut running test suite

Buat shortcut di composer.json pada block scripts dengan nama test, isinya:

XDEBUG_MODE=coverage php artisan test --coverage

Berkas .env.testing

Buat berkas .env.testing, dengan isian:

APP_KEY=
DB_CONNECTION=sqlite
DB_DATABASE=:memory:

Kemudian running perintah php artisan key:generate --env=testing untuk mengisi variable APP_KEY diatas.

Modifikasi Pest.php

Kita akan melakukan refresh database pada setiap test case yang dijalankan, buka berkas tests/Pest.php, uncomment baris 16 yang berguna untuk memuat Illuminate\Foundation\Testing\RefreshDatabase::class.

3. Memastikan Current State Code Coverage

Sebelum meningkatkan code coverage, kita perlu tahu sejauh mana cakupan tes kita saat ini. Untuk ini, kita akan menjalankan perintah composer test yang sudah kita buat sebelumnya.

Laravel fresh installation: choosing DBMS

4. Membuat Test Case

Prioritaskan pembuatan test case yang efektif untuk fungsi dan metode yang kritikal. Gunakan prinsip FIRST (Fast, Independent, Repeatable, Self-Validating, Timely) dalam mengembangkan test case yang baik. Manfaatkan Factory dan Seeder Laravel untuk mempersiapkan data dummy. Test case yang dapat Anda buat untuk melengkapi capaian code coverage 100% di fresh codebase Laravel versi 10 adalah sebagai berikut:

<?php

use App\Console\Kernel;
use App\Http\Middleware\RedirectIfAuthenticated;
use App\Models\User;
use App\Providers\BroadcastServiceProvider;
use App\Providers\RouteServiceProvider;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Application;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\Facades\Route;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\MockObject\Rule\InvokedCount;
use Symfony\Component\HttpFoundation\Response;

use function Pest\Laravel\getJson;

it('can redirect unauthenticated user', function () {
    $response = getJson('/api/user');

    $response->assertStatus(401);
});

it('can have rate limiter', function () {
    $user = User::factory()->create();

    $this->actingAs($user);

    $response = getJson('/api/user');

    $response->assertStatus(200)
        ->assertHeader('X-Ratelimit-Limit', 60)
        ->assertHeader('X-Ratelimit-Remaining', 59);
});

it('can have trusted hosts', function () {
    $trustedHosts = app('App\Http\Middleware\TrustHosts')->hosts();
    $this->assertNotEmpty($trustedHosts);
});

it('can AuthenticatedUserIsRedirected', function () {
    Route::get('/home', fn () => 'Home')->name('home');

    // Mock the Auth facade to simulate an authenticated user
    Auth::shouldReceive('guard')->once()->andReturnSelf();
    Auth::shouldReceive('check')->once()->andReturn(true);

    $request = Request::create('/test', 'GET');
    $middleware = new RedirectIfAuthenticated;
    /** @var RedirectResponse */
    $response = $middleware->handle($request, function () {
        // do nothing
    });

    $this->assertEquals($response->getTargetUrl(), url(RouteServiceProvider::HOME));
});

it('can UnauthenticatedUserIsNotRedirected', function () {
    Route::get('/home', fn () => 'Home')->name('home');

    // Mock the Auth facade to simulate an unauthenticated user
    Auth::shouldReceive('guard')->once()->andReturnSelf();
    Auth::shouldReceive('check')->once()->andReturn(false);

    $request = Request::create('/test', 'GET');
    $middleware = new RedirectIfAuthenticated;

    $response = $middleware->handle($request, fn () => new Response());

    $this->assertInstanceOf(Response::class, $response);
});

it('can BroadcastRoutesAreRegistered', function () {
    Broadcast::shouldReceive('routes')->once();
    Broadcast::shouldReceive('channel')->andReturnSelf();

    $provider = new BroadcastServiceProvider($this->app);
    $provider->boot();
});

it('can schedule method', function () {
    $app = new Application;
    $events = new \Illuminate\Events\Dispatcher($app);

    $kernel = new Kernel($app, $events);

    /**
     * @var \PHPUnit\Framework\TestCase $this
     * @var MockObject $schedule
     * @var InvokedCount $once
     */
    $schedule = $this->createMock(Schedule::class);
    $once = $this->once();
    $schedule->expects($once)->method('command')->with('inspire')->willReturnSelf();

    // Use reflection to call protected method
    $reflection = new \ReflectionClass($kernel);
    $method = $reflection->getMethod('schedule');
    $method->setAccessible(true);

    $method->invokeArgs($kernel, [$schedule]);
});

Untuk penggunaan ulang, kode diatas dapat kalian akses melalui gist di GitHub berkas test dengan PestPHP untuk Mencapai 100% Code Coverage di Aplikasi Laravel v10. Jangan lupa menempatkan berkas tersebut pada folder tests/Feature, karena kode diatas bukanlah sebuah unit test.

Hasil Code Coverage

Hasil Code Coverage setelah membuat FullCoverageTest.php

Jangan lupa bahwa mencapai 100% code coverage bukan berarti kode kita bebas dari bug, tapi ini adalah langkah besar dalam menjamin kualitas kode yang lebih tinggi. Happy coding!

Kesimpulan

Mencapai 100% code coverage adalah sebuah proses yang menuntut dedikasi dan usaha. Namun, dengan mengikuti langkah-langkah di atas, Anda dapat meningkatkan kualitas kode dan meminimalisir potensi bug di aplikasi Laravel Anda.