vocus logo

方格子 vocus

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

更新 發佈閱讀 12 分鐘

今天就讓我們依照前一天的情境題,來撰寫測試案例函數吧!

先讓我們規畫擬訂測試案例:

測試案例

當使用者瀏覽文章清單頁時:

  1. 使用者可看到所有文章清單,也就是【文章清單API】要能確實將資料庫內的文章資料,筆數不多不少地回應出來。

當使用者瀏覽單一文章頁時:

  1. 使用者可看到該文章資料,也就是【單一文章API】要能確實將指定ID之文章在資料庫內的資料回應出來,並包含所有欄位。
  2. 使用者可取得單一文章評論清單資料,也就是【單一文章評論清單API】要能確實將指定ID之文章在資料庫內的評論資料回應出來,並包含所有欄位。

當使用者對單一文章新增評論時:

  1. 使用者可針對此單一文章新增評論資料,也就是【新增單一文章評論API】在接受請求後,需新增一筆資料到資料庫。
  2. 使用者新增評論後,再次呼叫該文章評論清單API時,其回應資料應有包含新增的評論資料。

話不多說,來寫 Code !

測試案例函數實作

  • tests/Feature/ArticleControllerTest.php
<?php

namespace Tests\Feature;

use App\Models\Article;

use App\Models\User;

use Database\Seeders\ArticleSeeder;

use Database\Seeders\UserSeeder;

use Illuminate\Foundation\Testing\RefreshDatabase;

use Illuminate\Foundation\Testing\WithFaker;

use Illuminate\Foundation\Testing\WithoutMiddleware;

use Tests\TestCase;

class ArticleControllerTest extends TestCase{

use WithoutMiddleware;

use WithFaker;

use RefreshDatabase;

public function setUp(): void {

parent::setUp();

// 建立通用測試資料

$this->seed([

UserSeeder::class,

ArticleSeeder::class,

]); } public function testUserBrowseArticleList() {

// 建立測試資料

$articles = Article::all();

// 執行測試行為:對【文章清單API】發出請求

$response = $this->get(route('article.list'));

$response->assertOk()

->assertJsonStructure([

'data' => [

'*' => [

'id',

'content',

], ], ]); $list = $response->json('data');

$listExpected = $articles->toArray();

// 驗證結果

$this->assertJsonStringEqualsJsonString(json_encode($listExpected), json_encode($list));

$this->assertCount($articles->count(), $list);

} public function testUserBrowseOneArticle() {

// 建立測試資料

$article = Article::find(1);

// 執行測試行為:對【單一文章API】發出請求

$response = $this->get(route('article.one', ['id' => $article->id]));

$response->assertOk()

->assertJson([

'data' => [

'id' => $article->id,

'content' => $article->content,

], ]); $comments = $article->comments;

$responseComments = $this->get(route('article.one.comments', ['id' => $article->id]));

$list = $responseComments->json('data');

$listExpected = $comments->toArray();

// 驗證結果

$this->assertJsonStringEqualsJsonString(json_encode($listExpected), json_encode($list));

$responseComments->assertOk()

->assertJsonStructure([

'data' => [

'*' => [

'id',

'article_id',

'user_id',

'content',

], ], ]); $this->assertCount($comments->count(), $list);

} public function testUserPostCommentOnOneArticle() {

// 建立測試資料

$user = User::first();

$article = Article::find(1);

$data = [

'comment' => $this->faker->text,

]; // 執行測試行為:對【新增單一文章評論API】發出請求

$response = $this->be($user)->post(route('article.one.comments.store', ['id' => $article->id]), $data);

$responseComments = $this->get(route('article.one.comments', ['id' => $article->id]));

$responseCommentsList = $responseComments->json('data');

$foundPostedComment = false;

foreach ($responseCommentsList as $comment) {

if ($comment['content'] === $data['comment']) {

$foundPostedComment = true;

break;

} } // 驗證結果

$response->assertOk();

$this->assertDatabaseHas('comments', [

'article_id' => $article->id,

'user_id' => $user->id,

'content' => $data['comment'],

]); $this->assertTrue($foundPostedComment);

}}

在以上程式碼中,我們實作了以下測試案例函數:

  • testUserBrowseArticleList()

在這個測試案例函數中,我們呼叫了【文章清單API】,並確認回應是否成功,資料結構是否符合預期,且是否就是資料庫中的所有資料。

  • testUserBrowseOneArticle()

在這個測試案例函數中,我們呼叫了【單一文章API】及【單一文章評論API】,並各自確認回應是否成功,資料結構是否符合預期,且是否就是資料庫中的所有資料。

  • testUserPostCommentOnOneArticle()

在這個測試案例函數中,我們呼叫了【新增單一文章評論API】,並確認回應是否成功,資料結構是否符合預期,且資料庫中是否有新增對應資料。接著,呼叫【單一文章評論API】,看其回應之是否包含剛新增的評論資料。

除此之外,我們在 setUp() 函數內呼叫了 2 個 Seeder,建立各測試案例函數都會用到的通用測試資料:

  • setUp()
public function setUp(): void{

parent::setUp();

// 建立通用測試資料

$this->seed([

UserSeeder::class,

ArticleSeeder::class,

]);}

此外,我們使用了幾個測試相關 Traits 來協助我們執行測試:

  • WithoutMiddleware:略過 Middleware 層之運行
  • WithFaker:方便建立假資料
  • RefreshDatabase:重建測試資料庫之用

以上就是今天的練習,希望對大家有所幫助。

下一篇讓我們再探討另一個情境題!

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

本系列文章目錄

留言
avatar-img
WilliamP的沙龍
16會員
621內容數
歡迎來到 WilliamP 的沙龍天地,在這裡將與各位讀者探討各種主題,包刮高中數學題庫、PHP開發經驗、LINE聊天機器人開發經驗、書摘筆記等,歡迎交流!
WilliamP的沙龍的其他內容
2023/12/18
在前一篇文章中,我們探討了多重資料庫連線情境下,Model 及 Database Assertion 的應對方式,不過實際上筆者認為比較有難度的,其實是 Migration 應對方式。 今天就讓我們來探討這部分吧! Migration 應對方式 對於多重資料庫連線這種情境,筆者實務上做過的對應
2023/12/18
在前一篇文章中,我們探討了多重資料庫連線情境下,Model 及 Database Assertion 的應對方式,不過實際上筆者認為比較有難度的,其實是 Migration 應對方式。 今天就讓我們來探討這部分吧! Migration 應對方式 對於多重資料庫連線這種情境,筆者實務上做過的對應
2023/12/18
今天讓我們探討「缺乏 Migration Files 與 Factory Files」的 Legacy 情境吧! 很多時候我們會遇到沒有 Migration Files 或 Factory Files 的 Legacy Codebase,原因大概有以下幾種: 該程式庫原本不是以 Laravel
2023/12/18
今天讓我們探討「缺乏 Migration Files 與 Factory Files」的 Legacy 情境吧! 很多時候我們會遇到沒有 Migration Files 或 Factory Files 的 Legacy Codebase,原因大概有以下幾種: 該程式庫原本不是以 Laravel
2023/12/18
在實務情境上,常會有在單一專案程式庫中,存取多個不同資料庫的使用情境,在這種情況下,我們通常會設置多個資料庫連線(Database Connection)設定。 在平常開發使用設很方便,但要做測試時就會發現一些問題: 在測試程式碼或 Seeder 中調用 factory() 時,都是在預設連線資
2023/12/18
在實務情境上,常會有在單一專案程式庫中,存取多個不同資料庫的使用情境,在這種情況下,我們通常會設置多個資料庫連線(Database Connection)設定。 在平常開發使用設很方便,但要做測試時就會發現一些問題: 在測試程式碼或 Seeder 中調用 factory() 時,都是在預設連線資
看更多
你可能也想看
Thumbnail
創作不只是個人戰,在 vocus ,也可以是一場集體冒險、組隊升級。最具代表性的創作者社群「vocus 野格團」,現在有了更強大的新夥伴加入!除了大家熟悉的「官方主題沙龍」,這次我們徵召了 8 位領域各異的「個人主題專家」,將再度嘗試創作的各種可能,和格友們激發出更多未知的火花。
Thumbnail
創作不只是個人戰,在 vocus ,也可以是一場集體冒險、組隊升級。最具代表性的創作者社群「vocus 野格團」,現在有了更強大的新夥伴加入!除了大家熟悉的「官方主題沙龍」,這次我們徵召了 8 位領域各異的「個人主題專家」,將再度嘗試創作的各種可能,和格友們激發出更多未知的火花。
Thumbnail
看完上篇 4 位新成員的靈魂拷問,是不是意猶未盡?別急,野格團新血的驚喜正接著登場!今天下篇接力的另外 4 位「個人主題專家」,戰力同樣驚人──領域從旅行美食、運動、商業投資到自我成長;這些人如何維持長跑般的創作動力?在爆紅的文章背後,又藏著哪些不為人知的洞察?5 大靈魂拷問繼續出擊
Thumbnail
看完上篇 4 位新成員的靈魂拷問,是不是意猶未盡?別急,野格團新血的驚喜正接著登場!今天下篇接力的另外 4 位「個人主題專家」,戰力同樣驚人──領域從旅行美食、運動、商業投資到自我成長;這些人如何維持長跑般的創作動力?在爆紅的文章背後,又藏著哪些不為人知的洞察?5 大靈魂拷問繼續出擊
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
Thumbnail
在本節中,我們介紹了PHP的基本語法,包括如何在HTML中嵌入PHP代碼,PHP腳本的執行順序,以及多種註解方式。我們還學習了如何定義和使用變數,包括單個變數和多個變數的賦值方法。這些基礎知識將幫助你開始使用PHP進行Web開發。
Thumbnail
在本節中,我們介紹了PHP的基本語法,包括如何在HTML中嵌入PHP代碼,PHP腳本的執行順序,以及多種註解方式。我們還學習了如何定義和使用變數,包括單個變數和多個變數的賦值方法。這些基礎知識將幫助你開始使用PHP進行Web開發。
Thumbnail
介紹工作後幾個常見的小問題,包括寫 Log 的好習慣、本地印出錯誤或過程、PHPCS 工具、變數儲存於設定檔、避免魔術數字、程式碼靜態分析與動態分析。
Thumbnail
介紹工作後幾個常見的小問題,包括寫 Log 的好習慣、本地印出錯誤或過程、PHPCS 工具、變數儲存於設定檔、避免魔術數字、程式碼靜態分析與動態分析。
Thumbnail
當我們架好站、WebService測試完,接著就是測試區域網路連線啦~
Thumbnail
當我們架好站、WebService測試完,接著就是測試區域網路連線啦~
Thumbnail
你好,在下最近在學習開發web,學了html css js,也得出一些心得,由於網路上已有許多教學,所以我會著重在如何開發出to do List,以及解釋我寫的程式碼。相關的教學我會直接貼網址。如果我有什麼地方出錯,或者是可以寫得更好,歡迎在下方留言,討論。 首先先介紹我的開發環境: 我用了vs
Thumbnail
你好,在下最近在學習開發web,學了html css js,也得出一些心得,由於網路上已有許多教學,所以我會著重在如何開發出to do List,以及解釋我寫的程式碼。相關的教學我會直接貼網址。如果我有什麼地方出錯,或者是可以寫得更好,歡迎在下方留言,討論。 首先先介紹我的開發環境: 我用了vs
Thumbnail
JavaScript 套件,頁碼 Pagination.js 搭配 axios API 請求範例
Thumbnail
JavaScript 套件,頁碼 Pagination.js 搭配 axios API 請求範例
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News