走進 PHPUnit 的世界:從 0 到 1 的測試入門

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

為什麼要學 PHPUnit?

在上一篇文章裡,我們聊到了「還沒開始單元測試的你一定很忙」,同時也鼓勵大家「一個人就能開始測試」。那麼接下來就要進入更實際的操作層面,帶你走進 PHP 最常見的測試框架 —— PHPUnit

很多人對 PHPUnit 的印象是「很複雜、很多設定檔、好多斷言(assert)方法」。但事實上,只要掌握幾個核心概念,就能在短時間內寫出第一支測試。就像所有新事物一樣,最難的往往是那「踏出第一步」。我們就一起從 0 開始,帶你做到 1!


為什麼選擇 PHPUnit?

  1. 社群資源豐富
    PHPUnit 在 PHP 生態系已耕耘多年,有大量的教學資源與社群討論,一遇到問題很容易查詢到解法。
  2. 與框架或純 PHP 都相容
    無論是 Laravel 等主流框架,或是純 PHP 專案都可以整合 PHPUnit,相當彈性。
  3. Composer 管理輕鬆安裝
    PHPUnit 的安裝與升級都能透過 Composer 完成,對於現代 PHP 專案來說相當方便。

雖然 PHPUnit 很主流,但也不是唯一選擇。市面上還有像 Pest、Codeception、PHPSpec 等。不同框架、不同專案需求不一,最終還是看你的開發生態做選擇。這裡先以 PHPUnit 作為「從 0 到 1」的首選示範。


安裝與初始化

建立或確認你的專案環境

  • 先準備好一個 PHP 專案目錄(舉例:my-php-project),並確保你的電腦已經安裝 PHP 與 Composer。

透過 Composer 安裝 PHPUnit

在專案目錄下,執行下列指令:

composer require --dev phpunit/phpunit
  • -dev 參數代表這是開發時期使用的套件,不會在正式環境上線時被引入(或會以不同方式處理)。

檢查安裝成功

安裝完成後,你可以在終端機執行:

vendor/bin/phpunit --version

若能看到 PHPUnit 的版本號,表示安裝成功。


寫下你的第一個測試

建立測試資料夾結構

通常我們會在專案裡建立一個 tests 資料夾,來放所有測試程式碼。

  • 結構示例:
my-php-project/
├── src/
| └── MyCalculator.php
├── tests/
| └── MyCalculatorTest.php
└── composer.json

寫個簡單的功能:MyCalculator (示範)

假設我們有一個簡單的類別 MyCalculator,負責做加法、減法。

<?php
// 檔案路徑: src/MyCalculator.php
namespace App;

class MyCalculator
{
public function add($a, $b)
{
return $a + $b;
}

public function sub($a, $b)
{
return $a - $b;
}
}

建立測試檔 MyCalculatorTest

<?php
// 檔案路徑: tests/MyCalculatorTest.php
use PHPUnit\\Framework\\TestCase;
use App\\MyCalculator;

class MyCalculatorTest extends TestCase
{
public function testAdd()
{
// Arrange
$calc = new MyCalculator();

// Act
$result = $calc->add(2, 3);

// Assert
$this->assertEquals(5, $result, '2 + 3 應該等於 5');
}

public function testSub()
{
$calc = new MyCalculator();
$result = $calc->sub(5, 2);
$this->assertEquals(3, $result, '5 - 2 應該等於 3');
}
}

這支測試分為三個常見步驟:

  • Arrange(初始化/準備):建立或準備要測試的物件、參數。
  • Act(執行):呼叫我們要測試的方法。
  • Assert(斷言):檢查結果是否符合預期。

執行測試

回到終端機,在專案根目錄執行:

vendor/bin/phpunit tests

(或僅輸入 vendor/bin/phpunit,它會自動尋找 tests 資料夾。)

如果一切順利,你會在終端機看到類似

PHPUnit x.y.z by Sebastian Bergmann and contributors.

.. 2 / 2 (100%)

OK (2 tests, 2 assertions)

這代表你的兩個測試(testAddtestSub)都通過了!

此時,你已「舉出一個實例」來證明自己成功寫了測試,也驗證了程式運作正常。這份信心很重要,因為很多人都卡在「不知道怎麼開始」。


反例示範:測試失敗時該怎麼辦?

為了讓你感受「測試失敗會長什麼樣子」,我們故意改一下 MyCalculator::sub()

public function sub($a, $b)
{
return $a + $b; // 故意改錯
}

再執行一次測試,你可能會看到:

There was 1 failure:

1) MyCalculatorTest::testSub
Failed asserting that 7 matches expected 3.

這行訊息就很直接地告訴你,預期應該得到 3,實際卻是 7,於是測試失敗。如此一來,你能在開發階段就抓到錯誤,而不必等到功能上線或被 QA 測出來。


更多 PHPUnit 常見斷言

  1. assertTrue($condition) / assertFalse($condition) 檢查布林值。
  2. assertEquals($expected, $actual) 檢查預期值與實際值是否相等。
  3. assertCount($expectedCount, $array) 檢查陣列的長度是否符合預期。
  4. assertNull($variable) 檢查變數是否為 null。
  5. assertInstanceOf($expectedClass, $object) 檢查物件是否屬於預期的類別。

這只是 PHPUnit 常見斷言的冰山一角,它的功能非常豐富。未來若有更複雜的測試場景(例:例外拋出、時間相關測試、mock 物件等),你都可以在官方文件或社群中找到相應做法。


測試與程式設計的良性循環

在寫測試的過程中,往往能促使我們寫出更結構化的程式碼,因為「要測試,就得讓程式碼更容易被呼叫、被拆分」。這是一個良性循環:

  • 寫測試 → 想要「好測」,於是去「重構程式、拆成小模組」。
  • 程式結構更好 → 寫更多測試也更輕鬆。
  • 好測試 → 開發速度與穩定度都提升。

就算是小專案,也能透過 PHPUnit 改善品質,讓你對自己的程式更有信心。


結論與後續

恭喜你!如果你跟著這篇示範,成功跑出你的第一個「單元測試」,那就已經從 0 來到 1 了。

  • 只要你的測試檔能正常跑通,就足以證明「你已經會寫單元測試」。
  • 要做到大範圍測試覆蓋、處理更複雜的業務邏輯,還需要不斷學習與演進。這篇文章只是帶你踏出第一步。

在下一篇,我們將帶領大家進一步進入 Laravel Test 實戰。利用 Laravel 已經內建的強大測試工具和輔助方法,讓你在框架環境下更輕鬆地測試 Controller、路由、資料庫操作等。敬請期待!

本文重點回顧

  1. 安裝 PHPUnit:Composer 快速安裝。
  2. 建立測試檔案與範例:一個簡單的 MyCalculator 測試,引導你做「Arrange、Act、Assert」。
  3. 執行測試、查看結果:了解測試通過(綠燈)與失敗(紅燈)時的訊息。
  4. 常用斷言assertEquals() 等基礎用法。
  5. 思考測試與程式結構:撰寫測試是改善程式架構的好時機。


下一篇(Laravel Test 實戰:與框架結合的測試技巧)見!一起繼續把測試應用到更真實的專案情境。

留言
avatar-img
留言分享你的想法!
Rewrite-avatar-img
發文者
2025/01/21
avatar-img
詹姆士的軟體易開罐
25會員
78內容數
這是一系列以軟體開發為主題的輕鬆分享,內容涵蓋了技術選擇、開發經驗、實戰應用等多方面的議題。無論是如何在眾多框架中做出選擇,還是如何應對技術轉移的挑戰,這裡有幽默、有趣的對話風格,將複雜的技術問題轉化為易懂的故事。
2025/04/05
if寫得好,可以大大提高效率與可讀性。 Guard condition在函式起始先排除不合規輸入,能簡化結構、減少錯誤,使核心邏輯更聚焦並提高可維護性,也方便擴充與測試,在團隊協作和需求變動時,都能更快速應對。建議根據實際情況彈性運用,兼顧可讀性與維護成本。
Thumbnail
2025/04/05
if寫得好,可以大大提高效率與可讀性。 Guard condition在函式起始先排除不合規輸入,能簡化結構、減少錯誤,使核心邏輯更聚焦並提高可維護性,也方便擴充與測試,在團隊協作和需求變動時,都能更快速應對。建議根據實際情況彈性運用,兼顧可讀性與維護成本。
Thumbnail
2025/01/24
還記得我剛開始負責專案時,幾乎沒有人在意測試,改了程式碼就直接上線,結果小錯不斷、大災難頻傳。那種不知道哪裡會冒出 bug 的焦慮感,讓人每天都忙到焦頭爛額,卻依舊無從掌握系統品質。走過這段混亂的過程後,我才真正體會「為什麼需要測試」,也更明白「測試文化」並非只是技術細節。
Thumbnail
2025/01/24
還記得我剛開始負責專案時,幾乎沒有人在意測試,改了程式碼就直接上線,結果小錯不斷、大災難頻傳。那種不知道哪裡會冒出 bug 的焦慮感,讓人每天都忙到焦頭爛額,卻依舊無從掌握系統品質。走過這段混亂的過程後,我才真正體會「為什麼需要測試」,也更明白「測試文化」並非只是技術細節。
Thumbnail
2025/01/24
我想探討,從「個人測試」到「團隊測試策略」的思維轉換,強調測試不僅是個人的責任,更需要整個團隊的支持與參與。文章還提供了推動測試文化的具體建議,包括設定最小測試門檻、融入開發流程,以及如何克服常見的困境如進度壓力或技術債問題。
Thumbnail
2025/01/24
我想探討,從「個人測試」到「團隊測試策略」的思維轉換,強調測試不僅是個人的責任,更需要整個團隊的支持與參與。文章還提供了推動測試文化的具體建議,包括設定最小測試門檻、融入開發流程,以及如何克服常見的困境如進度壓力或技術債問題。
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
還記得我剛開始負責專案時,幾乎沒有人在意測試,改了程式碼就直接上線,結果小錯不斷、大災難頻傳。那種不知道哪裡會冒出 bug 的焦慮感,讓人每天都忙到焦頭爛額,卻依舊無從掌握系統品質。走過這段混亂的過程後,我才真正體會「為什麼需要測試」,也更明白「測試文化」並非只是技術細節。
Thumbnail
還記得我剛開始負責專案時,幾乎沒有人在意測試,改了程式碼就直接上線,結果小錯不斷、大災難頻傳。那種不知道哪裡會冒出 bug 的焦慮感,讓人每天都忙到焦頭爛額,卻依舊無從掌握系統品質。走過這段混亂的過程後,我才真正體會「為什麼需要測試」,也更明白「測試文化」並非只是技術細節。
Thumbnail
你是不是也有過這樣的經歷:剛修好的功能,過幾天又壞了;每次修改程式碼都得手動測試一遍,還常漏掉影響到的其他地方;整天忙到翻,但最後卻不知道忙在哪裡? 如果這些情境聽起來很熟悉,那麼你可能需要開始了解 單元測試!很多人覺得測試很難,或者認為時間不夠用,其實只要從幾個簡單的步驟開始,一個人也能輕鬆上手。
Thumbnail
你是不是也有過這樣的經歷:剛修好的功能,過幾天又壞了;每次修改程式碼都得手動測試一遍,還常漏掉影響到的其他地方;整天忙到翻,但最後卻不知道忙在哪裡? 如果這些情境聽起來很熟悉,那麼你可能需要開始了解 單元測試!很多人覺得測試很難,或者認為時間不夠用,其實只要從幾個簡單的步驟開始,一個人也能輕鬆上手。
Thumbnail
歡迎支持與學習,讓阿Han幫您脫離無限加班的惡性循環… 您是否苦於網路資訊爆炸嗎? 教學何其多,但卻無法好好選擇的困境呢? 歡迎加入實戰營, 這裡不給您冗餘的雜訊, 單刀直入直接送您重點, 避開選擇障礙的困境, 讓您獲得業界標準的開發起手式, 成為Top 1的頂尖人才。
Thumbnail
歡迎支持與學習,讓阿Han幫您脫離無限加班的惡性循環… 您是否苦於網路資訊爆炸嗎? 教學何其多,但卻無法好好選擇的困境呢? 歡迎加入實戰營, 這裡不給您冗餘的雜訊, 單刀直入直接送您重點, 避開選擇障礙的困境, 讓您獲得業界標準的開發起手式, 成為Top 1的頂尖人才。
Thumbnail
網路上提到自學程式的文章,都會說自學程式非常地辛苦,而且要很自律,決心夠強;而當自己踏上這條路後,才發現何止是辛苦,根本是佈滿荊棘,常常寸步難行,且被刺地遍體鱗傷(喂~是不是有點太浮誇了),但在每個寫出程式豁然開朗的當下,卻又成就感滿滿,所以想藉著寫部落格紀錄一下自己的學習過程!
Thumbnail
網路上提到自學程式的文章,都會說自學程式非常地辛苦,而且要很自律,決心夠強;而當自己踏上這條路後,才發現何止是辛苦,根本是佈滿荊棘,常常寸步難行,且被刺地遍體鱗傷(喂~是不是有點太浮誇了),但在每個寫出程式豁然開朗的當下,卻又成就感滿滿,所以想藉著寫部落格紀錄一下自己的學習過程!
Thumbnail
這是我從程式小白到成為 Jr. 工程師的心路歷程,希望可以幫助道同樣在轉職之路上的朋友們。
Thumbnail
這是我從程式小白到成為 Jr. 工程師的心路歷程,希望可以幫助道同樣在轉職之路上的朋友們。
Thumbnail
除了增進程式技術和技巧以外,我覺得建立起正確的【自學心態】更重要,保持正確的態度能讓你持續不斷的精進學習,不會半途而廢,也更能享受進步帶來的成就感,我從自己過去零基礎開始自學程式然後做出線上服務的經驗,整理出一些入門自學的朋友應該抱持的心態,相信會很有幫助
Thumbnail
除了增進程式技術和技巧以外,我覺得建立起正確的【自學心態】更重要,保持正確的態度能讓你持續不斷的精進學習,不會半途而廢,也更能享受進步帶來的成就感,我從自己過去零基礎開始自學程式然後做出線上服務的經驗,整理出一些入門自學的朋友應該抱持的心態,相信會很有幫助
Thumbnail
在 2021 年 6 月的時候,我帶著前端學習者的身份,第一次用影片的方式跟大家分享了自己學習前端的歷程。 老實說,即便當時的我非常有目標地在準備轉職,也了解只要自己持續努力,最後有一天一定會轉職成功。 但在心中依然會有一些自我懷疑的聲音:「我真的可以嗎?」 當然不算! 關於我:
Thumbnail
在 2021 年 6 月的時候,我帶著前端學習者的身份,第一次用影片的方式跟大家分享了自己學習前端的歷程。 老實說,即便當時的我非常有目標地在準備轉職,也了解只要自己持續努力,最後有一天一定會轉職成功。 但在心中依然會有一些自我懷疑的聲音:「我真的可以嗎?」 當然不算! 關於我:
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News