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' => '[email protected]',

'password' => 'password',

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

'name' => 'test_name',

'email' => '[email protected]',

'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' => '[email protected]',

'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' => '[email protected]',

'password' => 'password',

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

$repository = app(UserRepository::class);

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

$this->assertDatabaseMissing('users', [

'id' => $userId,

]); }}

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

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

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

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

參考資料

本系列文章目錄

8會員
224內容數
歡迎來到 WilliamP 的沙龍天地,在這裡將與各位讀者探討各種主題,包刮高中數學題庫、PHP開發經驗、LINE聊天機器人開發經驗、書摘筆記等,歡迎交流!
留言0
查看全部
發表第一個留言支持創作者!
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
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
練習 PHPUnit 測試的撰寫,依序創建Controller、Service,並針對計算邏輯進行單元測試的練習。
Thumbnail
在 Laravel 中的測試中,PHPUnit 和 Mockery 都可以用來創建測試替身(test double),但它們有不同的方式和功能,以下簡單介紹兩種寫法方式。
前言 基本準備差不多了,也能跑自己的測試,再來就是關於測試腳本的核心:元素定位跟動作,本篇會著重介紹 XPATH 定位的部分
Thumbnail
前言 上篇我們成功執行第一個測試案例,從 Python 腳本透過 Appium 控制模擬器點選設定中的電池,下個問題就是怎麼找元件,這時候就要請出 Appium Inspector 了
前言 經過五個小單元的準備,終於可以開始跑第一個測試了,Appium 本身是個工具,可以搭配各種語言,這邊選擇 Python 作為測試腳本語言,以便之後跟 Robot Framework 串接。
前言 前四篇,把主機作業系統跟待測物準備交代完畢,有需要請自行跳轉取用,接下來就是測試工具的部分,這次測試套件使用大名鼎鼎 Appium 2。 選擇 Appium 2 的理由 歷史悠久:Appium 2012 年公開之後,就廣受測試社群愛戴 站在巨人的肩榜上:架構類似 Selenium的主從式架構,
前言 前幾篇聊到作業系統、Docker 跟 Android 容器的準備,再來就是替 Android 容器開啟 Google Play 套件並安裝待測 App 供後續手動或者自動測試使用。
前言 前兩篇把作業系統跟 Docker 安裝講完了,接下來就是 Android 容器的安裝了,這裡選用 ReDroid ,因為它是開源、高效、又便於管理的方案。
Thumbnail
前言 前篇把 Ubuntu 作業系統的安裝跟準備談完了,有需要可以跳回去看。接下來聊容器服務 Docker 的安裝與使用。 Docker 可以應用的場合很多,這次是會用它來模擬 Android 受測裝置
前言 本 App 自動化測試專題,用來記錄自動化 App 測試的各環節,包含環境準備、套件安裝、腳本編寫、執行測試與整合。
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
練習 PHPUnit 測試的撰寫,依序創建Controller、Service,並針對計算邏輯進行單元測試的練習。
Thumbnail
在 Laravel 中的測試中,PHPUnit 和 Mockery 都可以用來創建測試替身(test double),但它們有不同的方式和功能,以下簡單介紹兩種寫法方式。
前言 基本準備差不多了,也能跑自己的測試,再來就是關於測試腳本的核心:元素定位跟動作,本篇會著重介紹 XPATH 定位的部分
Thumbnail
前言 上篇我們成功執行第一個測試案例,從 Python 腳本透過 Appium 控制模擬器點選設定中的電池,下個問題就是怎麼找元件,這時候就要請出 Appium Inspector 了
前言 經過五個小單元的準備,終於可以開始跑第一個測試了,Appium 本身是個工具,可以搭配各種語言,這邊選擇 Python 作為測試腳本語言,以便之後跟 Robot Framework 串接。
前言 前四篇,把主機作業系統跟待測物準備交代完畢,有需要請自行跳轉取用,接下來就是測試工具的部分,這次測試套件使用大名鼎鼎 Appium 2。 選擇 Appium 2 的理由 歷史悠久:Appium 2012 年公開之後,就廣受測試社群愛戴 站在巨人的肩榜上:架構類似 Selenium的主從式架構,
前言 前幾篇聊到作業系統、Docker 跟 Android 容器的準備,再來就是替 Android 容器開啟 Google Play 套件並安裝待測 App 供後續手動或者自動測試使用。
前言 前兩篇把作業系統跟 Docker 安裝講完了,接下來就是 Android 容器的安裝了,這裡選用 ReDroid ,因為它是開源、高效、又便於管理的方案。
Thumbnail
前言 前篇把 Ubuntu 作業系統的安裝跟準備談完了,有需要可以跳回去看。接下來聊容器服務 Docker 的安裝與使用。 Docker 可以應用的場合很多,這次是會用它來模擬 Android 受測裝置
前言 本 App 自動化測試專題,用來記錄自動化 App 測試的各環節,包含環境準備、套件安裝、腳本編寫、執行測試與整合。