昨天我們提到了要減少線上錯誤,可以使用測試環境提前偵測錯誤,以及在遇到線上錯誤時使用維護頁面,提升使用者體驗。
今天我們繼續聊減少線上錯誤的方式
自動化測試是其中一個專案的保護機制,如果我們的應用沒有通過自動化測試的話,會在自動整合的階段失敗,阻止專案被部署到線上。
在開發時,我們已經透過 AI 幫我們加上了一些自動化測試,減少我們所產出的程式碼犯錯的機會。
不過,我們怎麼知道測試是否已經盡可能覆蓋到所有的狀況呢?
我們可以透過檢查自動化測試的測試覆蓋率,來協助確認這種狀況
首先,我們先安裝 xdebug 幫助我們生成測試報告
pecl install xdebug
安裝套件之後,要在 php.ini 之內引入,首先我們找到 php.ini 的位置
php --ini
Configuration File (php.ini) Path: /usr/local/etc/php
Loaded Configuration File: /Users/se07/.config/herd-lite/bin/php.ini
編輯一下 php.ini,打開 xdebug,加入
zend_extension=/opt/homebrew/lib/php/pecl/20240924/xdebug.so
xdebug.mode=coverage
加入之後,我們檢查一下是否安裝成功
php -v
Zend Engine v4.4.1, Copyright (c) Zend Technologies
with Xdebug v3.4.5, Copyright (c) 2002-2025, by Derick Rethans
看到裡面有 Xdebug
的文字出現之後,我們就確定安裝成功了。
接著,我們就可以開始生成報告了
我們所使用的測試框架 pest
依賴於 phpunit
,所以我們會需要一個 phpunit.xml
很幸運的,Laravel 已經幫我們建立好這個檔案了。
所以我們可以直接用指令生成報告
php artisan test --coverage
如果所有測試順利通過,我們可以看到類似下面的報告
Tests: 47 passed (213 assertions)
Duration: 6.76s
Console/Commands/NewUserCommand ....................................... 0.0%
Filament/Resources/Categories/CategoryResource .............. 27..32 / 80.0%
Filament/Resources/Categories/Pages/CreateCategory .................. 100.0%
Filament/Resources/Categories/Pages/EditCategory ...................... 0.0%
Filament/Resources/Categories/Pages/ListCategories .................... 0.0%
Filament/Resources/Categories/Schemas/CategoryForm .................... 0.0%
Filament/Resources/Categories/Tables/CategoriesTable .................. 0.0%
Filament/Resources/ProductImages/Pages/CreateProductImage ........... 100.0%
Filament/Resources/ProductImages/Pages/EditProductImage ............... 0.0%
Filament/Resources/ProductImages/Pages/ListProductImages .............. 0.0%
Filament/Resources/ProductImages/Pages/ViewProductImage ............... 0.0%
Filament/Resources/ProductImages/ProductImageResource ....... 29..39 / 75.0%
Filament/Resources/ProductImages/Schemas/ProductImageForm ............. 0.0%
Filament/Resources/ProductImages/Schemas/ProductImageInfolist ......... 0.0%
Filament/Resources/ProductImages/Tables/ProductImagesTable ............ 0.0%
Filament/Resources/Products/Pages/CreateProduct ..................... 100.0%
Filament/Resources/Products/Pages/EditProduct ......................... 0.0%
Filament/Resources/Products/Pages/ListProducts ........................ 0.0%
Filament/Resources/Products/Pages/ViewProduct ......................... 0.0%
Filament/Resources/Products/ProductResource ................. 29..39 / 75.0%
Filament/Resources/Products/Schemas/ProductForm ....................... 0.0%
Filament/Resources/Products/Schemas/ProductInfolist ................... 0.0%
Filament/Resources/Products/Tables/ProductsTable ...................... 0.0%
Http/Controllers/Auth/VerifyEmailController ......................... 100.0%
Http/Controllers/CategoryController ..................... 32, 79, 85 / 92.5%
Http/Controllers/Controller ......................................... 100.0%
Http/Controllers/ProductController .................................. 100.0%
Http/Controllers/ProductImageController ......... 28, 61..63, 80, 86 / 91.7%
Http/Controllers/TagController ........................................ 0.0%
Http/Requests/StoreCategoryRequest .................................. 100.0%
Http/Requests/StoreProductImageRequest .............................. 100.0%
Http/Requests/StoreProductRequest ................................... 100.0%
Http/Requests/StoreTagRequest ......................................... 0.0%
Http/Requests/UpdateCategoryRequest ................................. 100.0%
Http/Requests/UpdateProductImageRequest ............................. 100.0%
Http/Requests/UpdateProductRequest .................................. 100.0%
Http/Requests/UpdateTagRequest ........................................ 0.0%
Http/Resources/CategoryResource ..................................... 100.0%
Http/Resources/ProductImageResource ................................. 100.0%
Http/Resources/ProductResource ...................................... 100.0%
Http/Resources/TagResource ............................................ 0.0%
Livewire/Actions/Logout ............................................. 100.0%
Models/Category ..................................................... 100.0%
Models/Product ...................................................... 100.0%
Models/ProductImage ................................................. 100.0%
Models/User ......................................................... 100.0%
Policies/ProductPolicy ................................................ 0.0%
Providers/AppServiceProvider ........................................ 100.0%
Providers/Filament/AdminPanelProvider ............................... 100.0%
Providers/VoltServiceProvider ....................................... 100.0%
────────────────────────────────────────────────────────────────────────────
Total: 45.3 %
這邊就可以看到整體的報告了!
如果想要更細緻的報告,我們可以生成網頁版的報告
php artisan test --coverage-html=coverage
這會建立一個資料夾 coverage
,然後在裡面放入網頁版的報告。
我們可以從 coverage/index.html
開始,瀏覽每個資料夾,甚至每個 PHP 檔案的每一行,看看是否有被測試覆蓋到
這樣一來,我們就可以用比較直觀的方式,來看出我們哪些地方還沒有做自動化測試了
能夠看到覆蓋率報告之後,我們可能會希望透過某種自動檢查的方式,在覆蓋率不夠的時候擋住。
這個也是可以達成的!
我們可以用 --min
參數,來設定可以允許的最低覆蓋率
php artisan test --coverage --min=80
FAIL Code coverage below expected: 45.4 %. Minimum: 80.0 %.
這時候我們會看到,由於我們專案的覆蓋率沒有通過允許的覆蓋率,所以這邊拋出了錯誤
如果要加在自動整合的流程裡面,我們可以編輯一下 .github/workflows/tests.yml
的 Run Tests
- name: Run Tests
run: ./vendor/bin/pest --coverage --min=80
加入之後,如果我們試著上傳到 GitHub,我們就會在自動整合階段由於覆蓋率不足,所以被阻止
這樣一來,我們就又多了一個安全機制,在加入功能但是自動化測試覆蓋率不足的時候,避免實際部署到線上了。
今天的部分就到這邊,我們明天見