Until now, we have been writing tests on top of existing Laravel code. We haven't touched a different (opposite) approach called TDD, Test Driven Development. So let's briefly cover it in this final section of the course.
In general, the difference is in mindset and in thinking, and in the order of how you do things.
Until now, we have been working in this order:
TDD approach is the opposite:
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 --phpunit
tests/Feature/ProductsTest.php:
class ProductsTest extends TestCase{ public function test_unauthenticated_user_cannot_access_products_page() { $response = $this->get('/products'); $response->assertRedirect('login'); }}
Notice: for TDD examples, I will use the PHPUnit syntax and not Pest, because it seems that TDD+PHPUnit are popular specifically in that combination, as both are widely used outside of Laravel framework, in other PHP projects.
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 make 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 --devphp 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 automatically changed the routes file during the installation. 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 another point is that nowhere during this lesson did we need to use the browser to test something. You write the test like you would do that in the browser, simulating the scenario.