PHPUnit 自動化測試大作戰【CH08】

更新於 發佈於 閱讀時間約 15 分鐘

前置: Factory & UserRepository

在開始實作資料庫測試之前,先與大家介紹 Factory 這個東西。

Factory 是個 Laravel 的 ORM:Eloquent 提供的功能,它可以讓我們用很簡單的方式,去準備測試資料,在 Laravel 初始化後,預設已經幫我們準備好了一個 UserFactory (而之所以 Laravel 官方預先準備了這個 Factory,可能是因為最基本預設的資料表,就是 users),慣例上會將 Factory 檔放在 database/factories這個資料夾下,並且會命名為 XxxFactory ,其中 Xxx 是資源名稱:

  • database/factories/UserFactory.php
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

use Illuminate\Support\Str;

/** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User> */

class UserFactory extends Factory{

/** * Define the model's default state. * * @return array<string, mixed> */

public function definition() {

return [

'name' => fake()->name(),

'email' => fake()->unique()->safeEmail(),

'email_verified_at' => now(),

'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password

'remember_token' => Str::random(10),

]; } /** * Indicate that the model's email address should be unverified. * * @return static */

public function unverified() {

return $this->state(fn (array $attributes) => [

'email_verified_at' => null,

]); }}

Factory 有2種主要的使用方式,第1種是會在資料表實際建立資料,並且回應 Eloquent Enity,用法如下:

$user = User::facotry()->create();

以上程式碼會立即在資料庫建立 User資料,其中 nameemail 會使用 fake() 來隨機建立假值,email_verified_at 會用當下時間,remember_token 則會是一個隨機產生的 10 個字的字串。

另1種方式,則不會在資料庫建立資料,但仍會回應 Eloquent Enity,用法如下:

$user = User::facotry()->make();

不過要注意,用 make() 來建立資料實體,其 id 欄位值會是空值喔(因為沒有實際在資料庫建立資料)。

此外,也可以在建立資料時,指定你想要的欄位值:

$user = User::facotry()->create(['name' => 'william']);

以上就是 Factory 的相關介紹,當然其實還有更多有趣的技術細節值得探討,像是神秘的 fake() ,不過這讓我們在之後的文章再來探討吧!

理解了準備資料的方式後,讓我們來看看今天要測試的對象,以下是針對 User 這個資源,所實作的資料操作類別 UserRepository

  • app/Repositories/UserRepository.php
<?php

namespace App\Repositories;

use App\Models\User;

class UserRepository{

protected $model;

public function __construct(User $model) {

$this->model = $model;

} // 依給予的輸入資料,於資料庫中建立 User 資料

public function createUser(array $data) {

return $this->model::create($data);

} // 更新指定 ID 之 User 資料之姓名值

public function updateUserNameById($userId, string $name) {

$user = $this->getUserById($userId);

if (empty($user)) {

return false;

} $user->name = $name;

return $user->save();

} // 刪除指定 ID 之 User 資料

public function deleteUserById($userId) {

$user = $this->getUserById($userId);

if (empty($user)) {

return false;

} return $user->delete();

} // 讀取指定 ID 之 User 資料

public function getUserById($userId) {

return $this->model::find($userId);

}}

以上程式碼實作了關於 User 這個資源的 CRUD 4種操作,接著就來寫測試吧!

資料操作測試:建立

首先是建立資料功能的測試,請看以下程式碼:

namespace Tests\Feature;

use App\Repositories\UserRepository;

use Illuminate\Foundation\Testing\RefreshDatabase;

use Tests\TestCase;

class UserRepositoryTest extends TestCase{

use RefreshDatabase;

/** * Example for user creating * @return void */

public function testUserCreating() {

$repository = app(UserRepository::class);

$repository->createUser([

'name' => 'test_name',

'email' => 'test@test.test',

'password' => 'password',

]); $this->assertDatabaseHas('users', [

'name' => 'test_name',

'email' => 'test@test.test',

'password' => 'password',

]); }}

以上程式碼,會呼叫 createUser() ,並在呼叫之後,驗證資料庫中是否存有期望中的資料。

資料操作測試:讀取

namespace Tests\Feature;

use App\Repositories\UserRepository;

use Illuminate\Foundation\Testing\RefreshDatabase;

use Tests\TestCase;

class UserRepositoryTest extends TestCase{

use RefreshDatabase;

/** * Example for user reading * @return void */

public function testUserReading() {

$user = User::factory()->create();

$repository = app(UserRepository::class);

$userGot = $repository->getUserById($user->id);

$this->assertEquals($user->id, $userGot->id);

}}

以上程式碼,會先建立假資料 $user ,之後呼叫 getUserById() ,並在呼叫之後,驗證取得的資料之 ID 是否如預期。

資料操作測試:更新

namespace Tests\Feature;

use App\Repositories\UserRepository;

use Illuminate\Foundation\Testing\RefreshDatabase;

use Tests\TestCase;

class UserRepositoryTest extends TestCase{

use RefreshDatabase;

/** * Example for user updating * @return void */

public function testUserUpdating() {

$user = User::factory()->create([

'name' => 'test_name',

'email' => 'test@test.test',

'password' => 'password',

]); $repository = app(UserRepository::class);

$repository->updateUserNameById($user->id, 'name_2');

$this->assertDatabaseHas('users', [

'name' => 'name_2',

]); }}

以上程式碼,會先建立假資料 $user ,之後呼叫 updateUserNameById() ,並在呼叫之後,驗證資料是否如期更新。

資料操作測試:刪除

namespace Tests\Feature;

use App\Repositories\UserRepository;

use Illuminate\Foundation\Testing\RefreshDatabase;

use Tests\TestCase;

class UserRepositoryTest extends TestCase{

use RefreshDatabase;

/** * Example for user deletion * @return void */

public function testUserDeletion() {

$user = User::factory()->create([

'name' => 'test_name',

'email' => 'test@test.test',

'password' => 'password',

]); $userId = $user->id;

$repository = app(UserRepository::class);

$repository->deleteUserById($user->id);

$this->assertDatabaseMissing('users', [

'id' => $userId,

]); }}

以上程式碼,會先建立假資料 $user ,之後呼叫 deleteUseryId() ,並在呼叫之後,驗證資料是否如預期地刪除。

以上就是今天的資料庫測試介紹。

下一篇來為大家介紹與自動化測試相關的 Traits。

如果您喜歡這篇文章,歡迎加入追蹤以接收新文章通知 😄

參考資料

本系列文章目錄

avatar-img
8會員
337內容數
歡迎來到 WilliamP 的沙龍天地,在這裡將與各位讀者探討各種主題,包刮高中數學題庫、PHP開發經驗、LINE聊天機器人開發經驗、書摘筆記等,歡迎交流!
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
WilliamP的沙龍 的其他內容
在前幾篇文章中,我們介紹了測試3A原則,也介紹了許多 Assertion 函數,今天就讓我們實際演練吧! 過去的經驗中,最常用自動化測試來測式的對象,大概就是API了,而前後端分離也是目前 Web 開發界常用的模式,因此我們就以 API 測試來演練吧! 驗證HTTP Status Code H
今天會再與大家介紹幾個資料庫 Assertion 函數,與陣列 Assertion 函數。 與前一篇一樣,以下會提到的資料庫 Assertion 函數,並非 PHPUnit 內建,而是由 Laravel 所擴充,因此需注意是否有確實引用到 use Tests\\TestCase 。最後面介紹的2個
前一天與大家分享了幾個通用型 Assertion 函數,今天來為大家介紹幾個 HTTP 相關的 Assertion 函數吧! 今天要介紹的各函數,其使用方式和前一天所介紹的略有不同。以下所列各函數,皆是基於 HTTP Response 來做驗證測試,因此大家會看到 $response = $thi
前一天我們實作了第一個測試,我們學到了第一個 Assert 函數 assertEquals。 今天讓我們來了解其他常用的 Assert 函數吧! 通用型 Assertion 函數 assertEmpty 函數簽名:assertEmpty(mixed $actual[, string $mess
今天我們來寫第一個單元測試吧! 不過在那之前,先讓我們了解單元測試的「3個A」 單元測試3A 所謂的「3個A」,是指以下三個英文單字: Arrange:初始化工作,如準備假資料 Act:執行測試對象 Assert:驗證結果 一個良好的單元測試案例,應該包含以上的結構, 依序執行 Arra
下載與設定 Laradock 首先,讓我們在Home資料夾下,將 Laradock 下載下來: cd ~ && git clone <https://github.com/Laradock/laradock.git> Laradock 將 Laradock 下載回來後,切換到 Laradock
在前幾篇文章中,我們介紹了測試3A原則,也介紹了許多 Assertion 函數,今天就讓我們實際演練吧! 過去的經驗中,最常用自動化測試來測式的對象,大概就是API了,而前後端分離也是目前 Web 開發界常用的模式,因此我們就以 API 測試來演練吧! 驗證HTTP Status Code H
今天會再與大家介紹幾個資料庫 Assertion 函數,與陣列 Assertion 函數。 與前一篇一樣,以下會提到的資料庫 Assertion 函數,並非 PHPUnit 內建,而是由 Laravel 所擴充,因此需注意是否有確實引用到 use Tests\\TestCase 。最後面介紹的2個
前一天與大家分享了幾個通用型 Assertion 函數,今天來為大家介紹幾個 HTTP 相關的 Assertion 函數吧! 今天要介紹的各函數,其使用方式和前一天所介紹的略有不同。以下所列各函數,皆是基於 HTTP Response 來做驗證測試,因此大家會看到 $response = $thi
前一天我們實作了第一個測試,我們學到了第一個 Assert 函數 assertEquals。 今天讓我們來了解其他常用的 Assert 函數吧! 通用型 Assertion 函數 assertEmpty 函數簽名:assertEmpty(mixed $actual[, string $mess
今天我們來寫第一個單元測試吧! 不過在那之前,先讓我們了解單元測試的「3個A」 單元測試3A 所謂的「3個A」,是指以下三個英文單字: Arrange:初始化工作,如準備假資料 Act:執行測試對象 Assert:驗證結果 一個良好的單元測試案例,應該包含以上的結構, 依序執行 Arra
下載與設定 Laradock 首先,讓我們在Home資料夾下,將 Laradock 下載下來: cd ~ && git clone <https://github.com/Laradock/laradock.git> Laradock 將 Laradock 下載回來後,切換到 Laradock
你可能也想看
Google News 追蹤
提問的內容越是清晰,強者、聰明人越能在短時間內做判斷、給出精準的建議,他們會對你產生「好印象」,認定你是「積極」的人,有機會、好人脈會不自覺地想引薦給你
Thumbnail
在本章節中,我們探討了 PHP 中如何引用和管理套件。學習了如何使用 Composer 來安裝第三方套件,以及如何引用自定義模組。此外,我們還介紹了如何創建和使用自定義套件,並列舉了一些在 PHP 社群中常見且廣泛使用的套件和庫。通過掌握這些知識,開發者可以更有效地管理和利用各種資源。
Thumbnail
這一章節旨在介紹 PHP 中的物件導向編程(OOP)概念。通過詳細講解類別、建構子、訪問修飾符(公開、私有、受保護)、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda 表達式、泛型和反射等概念,使讀者能夠理解和應用這些 OOP 技術來編寫更具結構性和可維護性的 PHP 代碼。
Thumbnail
這個章節介紹了PHP的基本特性和應用領域,並且列舉了使用PHP的知名公司和網站。了解PHP的簡單易學、跨平台、嵌入HTML等特性,以及PHP在動態網站、電子商務、內容管理系統、社交媒體平台、數據庫管理和API開發中的應用。
Thumbnail
軟體系統的發展歷程大多相似,首重解決基本需求、提供操作介面,進而提升安全性、擴充功能、優化操作。
Thumbnail
Odoo ERP系統是工廠的理想選擇,為工廠繼承者提供高度客製化、使用者友善、即時資訊整合、雲端部署和持續更新的功能。本文介紹Odoo ERP系統的優勢及導入建議,並歡迎與我們預約免費30分鐘線上諮詢。
Thumbnail
進入物件導向設計的實戰階段,我們通過建立人力資源管理功能來實踐理論知識。透過這些實作練習,能夠深化對物件導向概念的理解,並學會如何在實際開發中應用這些概念。
Thumbnail
本階段介紹物件導向程式設計(OOP)基礎,從OOP概念、類別與物件基本原理,到PHP中類別與物件的應用,並深入探討封裝、繼承等OOP特性,最後以實際練習加強理解。此階段為學生掌握PHP OOP打下堅實基礎。
Thumbnail
從基本的OOP概念、PHP基礎回顧,到類別與物件的深入探討、進階概念如繼承、介面與抽象類別,再到實戰應用與設計模式入門,最後以課程總結與未來學習資源提供作結。此課程架構確保學生能夠從基礎到進階,全面掌握PHP物件導向程式設計的核心概念與技術。
Thumbnail
第一份正職工作 在iot公司擔任後端工程師,一上工就使用先前沒用過的php/laravel,也馬上負責公司產品的架構規劃,先前資料庫只有簡單記載使用者跟使用者的一些設定,很多地方有資料不一致的問題,產品內容還有很多實體的關係沒有被定義進資料庫都是這次改版我要做的事情。 改版納入公司、機器
Migration在 Laravel 中是一種用來管理資料庫結構變更的機制。它的主要目的是使開發者能夠在應用程序的不同環境中保持資料庫結構的一致性,並輕鬆地進行結構變更
提問的內容越是清晰,強者、聰明人越能在短時間內做判斷、給出精準的建議,他們會對你產生「好印象」,認定你是「積極」的人,有機會、好人脈會不自覺地想引薦給你
Thumbnail
在本章節中,我們探討了 PHP 中如何引用和管理套件。學習了如何使用 Composer 來安裝第三方套件,以及如何引用自定義模組。此外,我們還介紹了如何創建和使用自定義套件,並列舉了一些在 PHP 社群中常見且廣泛使用的套件和庫。通過掌握這些知識,開發者可以更有效地管理和利用各種資源。
Thumbnail
這一章節旨在介紹 PHP 中的物件導向編程(OOP)概念。通過詳細講解類別、建構子、訪問修飾符(公開、私有、受保護)、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda 表達式、泛型和反射等概念,使讀者能夠理解和應用這些 OOP 技術來編寫更具結構性和可維護性的 PHP 代碼。
Thumbnail
這個章節介紹了PHP的基本特性和應用領域,並且列舉了使用PHP的知名公司和網站。了解PHP的簡單易學、跨平台、嵌入HTML等特性,以及PHP在動態網站、電子商務、內容管理系統、社交媒體平台、數據庫管理和API開發中的應用。
Thumbnail
軟體系統的發展歷程大多相似,首重解決基本需求、提供操作介面,進而提升安全性、擴充功能、優化操作。
Thumbnail
Odoo ERP系統是工廠的理想選擇,為工廠繼承者提供高度客製化、使用者友善、即時資訊整合、雲端部署和持續更新的功能。本文介紹Odoo ERP系統的優勢及導入建議,並歡迎與我們預約免費30分鐘線上諮詢。
Thumbnail
進入物件導向設計的實戰階段,我們通過建立人力資源管理功能來實踐理論知識。透過這些實作練習,能夠深化對物件導向概念的理解,並學會如何在實際開發中應用這些概念。
Thumbnail
本階段介紹物件導向程式設計(OOP)基礎,從OOP概念、類別與物件基本原理,到PHP中類別與物件的應用,並深入探討封裝、繼承等OOP特性,最後以實際練習加強理解。此階段為學生掌握PHP OOP打下堅實基礎。
Thumbnail
從基本的OOP概念、PHP基礎回顧,到類別與物件的深入探討、進階概念如繼承、介面與抽象類別,再到實戰應用與設計模式入門,最後以課程總結與未來學習資源提供作結。此課程架構確保學生能夠從基礎到進階,全面掌握PHP物件導向程式設計的核心概念與技術。
Thumbnail
第一份正職工作 在iot公司擔任後端工程師,一上工就使用先前沒用過的php/laravel,也馬上負責公司產品的架構規劃,先前資料庫只有簡單記載使用者跟使用者的一些設定,很多地方有資料不一致的問題,產品內容還有很多實體的關係沒有被定義進資料庫都是這次改版我要做的事情。 改版納入公司、機器
Migration在 Laravel 中是一種用來管理資料庫結構變更的機制。它的主要目的是使開發者能夠在應用程序的不同環境中保持資料庫結構的一致性,並輕鬆地進行結構變更