Привет, Хабр!
Laravel — это целая экосистема, которая позволяет разрабатывать качественные веб-приложения. Но вот вопрос: как быть уверенным, что все эти красивые строки кода не развалятся в самый неподходящий момент? Ответ очевиден — тесты!
Какие тесты бывают в Laravel
Laravel поддерживает три главных типа тестов: юнит-тесты, интеграционные тесты и функциональные тесты. Каждому своё, каждый важен.
Юнит-тесты
Юнит-тесты — маленькие тесты для маленьких частей кода: методов, функций, классов. Они изолированы от всего остального — ни базы данных, ни API не трогаем, только чистая логика.
Пример? Пожалуйста:
namespace Tests\Unit; use PHPUnit\Framework\TestCase; use App\Services\DiscountService; class DiscountServiceTest extends TestCase { public function test_calculate_discount() { $price = 100; $expectedDiscount = 90; // 10% скидки $service = new DiscountService(); $actualDiscount = $service->calculateDiscount($price); $this->asnamespace Tests\Unit; use PHPUnit\Framework\TestCase; use App\Services\DiscountService; class DiscountServiceTest extends TestCase { public function test_calculate_discount() { $price = 100; $expectedDiscount = 90; // 10% скидки $service = new DiscountService(); $actualDiscount = $service->calculateDiscount($price); $this->assertEquals($expectedDiscount, $actualDiscount); } } sertEquals($expectedDiscount, $actualDiscount); } }
Здесь тестируем метод calculateDiscount
. 100 рублей на входе — 90 на выходе. Всё по плану.
Интеграционные тесты
Интеграционные тесты — это когда ты смотришь, как всё взаимодействует в связке. Вот у тебя есть сервис, который лезет в БД, обращается к внешнему API и возвращает что-то вкусное. Тут юнит-тесты уже не помогут — нужно посмотреть на всю картину в целом.
Например, есть сервис, который получает данные от API и сохраняет их в базу. Проверим, как это работает:
namespace Tests\Feature; use Tests\TestCase; use Illuminate\Foundation\Testing\RefreshDatabase; use App\Services\ExternalApiService; class ApiIntegrationTest extends TestCase { use RefreshDatabase; public function test_external_api_data_is_saved_to_database() { $this->mock(ExternalApiService::class, function ($mock) { $mock->shouldReceive('fetchData') ->once() ->andReturn([ 'name' => 'Test Item', 'price' => 100 ]); }); $response = $this->get('/api/fetch-data'); $response->assertStatus(200); $this->assertDatabaseHas('items', [ 'name' => 'Test Item', 'price' => 100 ]); } }
Здесь мы имитируем то, что наш API вернул данные, и проверяем, что они сохранились в базе.
Функциональные тесты
Функциональные тесты — это взгляд на приложения глазами пользователя. Тут пригодится Laravel Dusk — инструмент для браузерных тестов.
Допустим, есть форма входа. Проверим, что она работает корректно:
namespace Tests\Browser; use Laravel\Dusk\Browser; use Tests\DuskTestCase; class LoginTest extends DuskTestCase { public function test_user_can_login() { $this->browse(function (Browser $browser) { $browser->visit('/login') ->type('email', 'test@example.com') ->type('password', 'password') ->press('Login') ->assertPathIs('/home'); }); } }
Этот тест имитирует реального пользователя: он заходит на страницу логина, вводит email и пароль, а затем проверяет, что после успешного входа его перенаправляют на страницу /home.
Тестирование API
Если есть API его нужно его тестировать, то ларавелл умеет проверять JSON-запросы и ответы. Вот, например, как мы проверим список продуктов:
namespace Tests\Feature; use Tests\TestCase; class ProductsApiTest extends TestCase { public function test_get_products() { $response = $this->getJson('/api/products'); $response->assertStatus(200) ->assertJsonStructure([ '*' => ['id', 'name', 'price'] ]); } }
Этот тест проверяет, что API возвращает список продуктов с нужными полями.
Примеры использования
Тестирование отправки письма при успешной регистрации
Следующий пример — это классическая ситуация, когда при регистрации нового пользователя система должна отправить приветственное письмо. Нужно убедиться, что оно действительно отправляется.
namespace Tests\Feature; use Tests\TestCase; use Illuminate\Support\Facades\Mail; use App\Mail\WelcomeEmail; use App\Models\User; use Illuminate\Foundation\Testing\RefreshDatabase; class WelcomeEmailTest extends TestCase { use RefreshDatabase; public function test_welcome_email_is_sent_upon_registration() { Mail::fake(); // Выполняем регистрацию пользователя $response = $this->post('/register', [ 'name' => 'Ivan Ivanov', 'email' => 'ivan@example.com', 'password' => 'password123', 'password_confirmation' => 'password123' ]); // Проверяем, что пользователь успешно создан $this->assertDatabaseHas('users', ['email' => 'ivan@example.com']); // Проверяем, что письмо было отправлено Mail::assertSent(WelcomeEmail::class, function ($mail) { return $mail->hasTo('ivan@example.com'); }); } }
Тест позволит убедиться, что система действительно отправляет email каждому новому пользователю.
Тестирование удаления записей из базы данных
Предположим, есть CRUD-система для управления записями. Нужно убедиться, что записи корректно удаляются, а также правильно обрабатываются сопутствующие данные. Протестируем сценарий удаления записи и проверим, что данные действительно ушли в никуда.
namespace Tests\Feature; use Tests\TestCase; use Illuminate\Foundation\Testing\RefreshDatabase; use App\Models\Post; class PostDeletionTest extends TestCase { use RefreshDatabase; public function test_post_can_be_deleted() { // Создаем пост $post = Post::factory()->create(); // Отправляем запрос на удаление $response = $this->delete('/posts/' . $post->id); // Проверяем успешный статус и редирект $response->assertStatus(302); $response->assertRedirect('/posts'); // Проверяем, что запись удалена из базы $this->assertDatabaseMissing('posts', ['id' => $post->id]); } }
Этот тест проверяет:
-
Успешное удаление записи.
-
Отсутствие записи в базе данных после удаления.
Тест защитит от сценариев, когда запись вроде бы удаляется, но остаётся в базе.
Всех желающих приглашаем на открытый урок «Использование GraphQL в Laravel проектах». На нем сравним RESTFul и Graphql; предоставим API, используя Graphql; а также посмотрим, как работать с Graphql на фронтэнде. Записаться на урок можно на странице курса «Framework Laravel».
ссылка на оригинал статьи https://habr.com/ru/articles/849962/
Добавить комментарий