Back to Course |
Testing in Laravel 9 For Beginners: PHPUnit, Pest, TDD

What is TDD? How it works: Simple Example

Until now, we haven't touched a different approach called TDD, Test Driven Development. In general, the difference is in mindset and in thinking, and in the order of how you do things.

Until now, we have been writing the code, then writing the test for features, and then launching the tests. TDD approach is the opposite. You write tests first, then they fail, and then you write the code until the tests succeed.

For the example, we will write a couple of the same tests we did already for a product CRUD, but with a TDD approach.


So, we have a fresh Laravel project. The first feature we will work on is a products list, which should be protected by authentication. Let's create a test.

php artisan make:test ProductsTest

tests/Feature/ProductsTest.php:

class ProductsTest extends TestCase
{
public function test_unauthenticated_user_cannot_access_products_page()
{
$response = $this->get('/products');
 
$response->assertRedirect('login');
}
}

Then, we launch the test without writing any code which will fail.

And the failure of the test is the whole point. The error of that failure would be our next step in what feature to write.

Here, we got a 404 error code, which means we need to create a route. For the Route we need to pass the Controller, so we must create it first.

php artisan make:controller ProductController --resource

routes/web.php:

use App\Http\Controllers\ProductController;
 
Route::get('/', function () {
return view('welcome');
});
 
Route::get('products', [ProductController::class, 'index'])->name('product.index');

The index method in the ProductController exists, but it doesn't contain any code. Our goal is to pass the first test passed. Now, let's re-launch the test to see what error we have and lead to what we create next.

We received a status of 200, but we expect it to be a redirect to login. Now, we need to create a login Route.

Then you think you will build an authentication system using, for example Laravel Breeze.

composer require laravel/breeze --dev
php artisan breeze:install blade

Now, if we run tests, there will be more passed tests that came from the Breeze. So, we can filter tests just for class.

We have the same 404 message. And this is because Laravel Breeze changed the routes file. That's why you should use a starter kit first before writing any code. Now we must add Route again. But now we can add this Route in the auth Middleware group.

route/web.php:

use App\Http\Controllers\ProductController;
 
Route::get('/', function () {
return view('welcome');
});
 
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
 
Route::middleware('auth')->group(function () {
Route::get('products', [ProductController::class, 'index'])->name('product.index');
 
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
 
require __DIR__.'/auth.php';

Now, after running the test, it is green.

This was our first goal with TDD. And nowhere during this lesson we needed to access a browser to test something. That's the whole point. You write the test like you would do that in the browser.