本文首發於我的博客 掌握 Laravel 的測試方法,轉載請註明出處。
無論你認可與否在研發一款產品時,軟件測試對項目而言意義重大,但現實是測試一般被咱們視而不見。這篇文章咱們主要研究 Laravel 框架的測試方法。php
或許你還不知道,Laravel 內核早已繼承了 PHPUnit 單元測試組件。PHPUnit 是 PHP 社區裏使用最普遍、最受歡迎的測試框架之一。PHPUnit 同時支持「單元測試」和「功能測試」兩種特性。laravel
咱們會簡單介紹 PHPUnit 「單元測試」和「功能測試」的基本使用方法。繼而,講解如何在 Laravel 項目中建立「單元測試」和「功能測試」用例。不過本篇咱們假定你已經對 PHPUnit 測試框架有了基本的瞭解,因此讓咱們把焦點放到 Laravel 中使用 PHPUnit 進行測試這個主題中。web
若是您已經接觸過 PHPUnit 框架,那麼您應該知道,它支持兩種類型特性 -- 「單元測試」和「功能測試」。shell
「單元測試」的目的是用於測試函數或方法的正確性。更重要的是,咱們能夠輕鬆實現代碼邏輯的正確性。數據庫
若是您在開發過程當中發現某個功能包含多個邏輯處理,那麼最好將每一個處理邏輯拆分到不一樣的方法裏,這樣以確保單個方法和代碼塊可測試。app
咱們以一個理想的方法來窺探單元測試的奧祕。框架
<?php public function getNameAttribute($value) { return ucfirst($value); }
如你所見,這個方法僅處理一個業務邏輯,方法內部經過 ucfirst 函數將字符轉換成首字母大寫格式。函數
單元測試是爲了保證每一個獨立單元的代碼正確性;功能測試則是爲了保證一個功能的正確性。一言以蔽之,就是經過特定的測試用例模擬用戶訪問應用的行爲驗證系統的正確性。工具
例如,咱們能夠爲包含以下步驟的登陸功能實現一個功能測試用例:post
這就是應該如何建立「功能測試」用例的祕密。接下來咱們將建立具體的測試用例,來說解如何在 Laravel 中使用「單元測試」和「功能測試」。
在開始建立測試用例前,咱們須要先構建起用於測試的項目依賴。
先執行下面的 artisan 命令建立一個 Post 模型及其對應的遷移文件。
$ php artisan make:model Post --migration
上面的命令將爲咱們建立一個 Post 模型類和數據庫遷移文件。
Post 模型代碼以下:
<?php // app/Post.php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { // }
數據庫遷移文件 YYYY_MM_DD_HHMMSS_create_posts_table.php 將建立在 database/migrations 目錄中。
Post 數據表會存儲一篇文章的標題。修改後 Post 數據庫遷移文件代碼以下:
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreatePostsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('posts', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('posts'); } }
如你所見,咱們經過新增的 $table->string('name') 來存儲文章的標題。接下來,執行數據庫遷移命令就回在數據庫中建立對應的數據表了。
$ php artisan migrate
在建立完數據表以後,咱們須要向 Post 模型類中加入以下代碼
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { /** * Get the post title. * * @param string $value * @return string */ public function getNameAttribute($value) { return ucfirst($value); } }
咱們剛剛添加了 accessor 方法,它的功能是修改文章的標題,這正是咱們在單元測試用例中要測試的。以上就是 Post 模型所須要修改的內容。
接下來,咱們須要建立一個文件名爲 app/Http/Controllers/AccessorController.php 的控制器,它將被用於後續功能測試。
<?php // app/Http/Controllers/AccessorController.php namespace App\Http\Controllers; use App\Post; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class AccessorController extends Controller { public function index(Request $request) { // get the post-id from request params $post_id = $request->get("id", 0); // load the requested post $post = Post::find($post_id); // check the name property return $post->name; } }
在 index 方法中,咱們經過請求中的 id 參數,從 Post 模型中查詢一篇文章。
最後,在 routes/web.php 路由配置文件裏定義相關路由。
<?php Route::get('accessor/index', 'AccessorController@index');
設置完路由後就能夠經過 http://your-laravel-site.com/accessor/index 訪問該路由是否可以正常訪問了。
上一節咱們搭建了用於測試的環境。本節咱們會在 Laravel 中編寫單元測試用例對 Post 模型進行測試。
幸運的是,Laravel 一樣爲咱們提供了建立測試用例模版文件的命令工具。
經過在命令行裏執行下面的命令來建立 AccessorTest 單元測試用例類。注意咱們須要經過 --unit 參數選項來代表這個命令建立一個單元測試用例。單元測試用例文件被建立在 tests/Unit 目錄內。
$ php artisan make:test --unit
執行上面建立測試用例命令會建立文件名爲 tests/Unit/AccessorTest.php 文件。
<?php // tests/Unit/AccessorTest.php namespace Tests\Unit; use Tests\TestCase; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseTransactions; class AccessorTest extends TestCase { /** * A basic test example. * * @return void */ public function testExample() { $this->assertTrue(true); } }
將 testExample 方法替換成更有實際意義的方法:
<?php // tests/Unit/AccessorTest.php namespace Tests\Unit; use Tests\TestCase; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseTransactions; class AccessorTest extends TestCase { /** * Test accessor method * * @return void */ public function testAccessorTest() { $db_post = DB::select('select * from posts where id = 1'); $db_post_title = ucfirst($db_post[0]->title); $model_post = Post::find(1); $model_post_title = $model_post->title; $this->assertEquals($db_post_title, $model_post_title); } }
咱們能夠看到更新後的代碼和 Laravel 代碼編碼風格徹底一致。在類的開始咱們引入了相關依賴類文件。在 testAccessorTest 方法裏,咱們但願驗證定義在 Post 模型裏面的 getNameAttribute 方法的正確性。
爲了實現這樣的測試功能,咱們經過 DB 類使用原生 SQL 查詢到一篇文章,並將文章的標題賦值給 $db_post_title 變量。
以後,咱們經過 Post 模型獲取通過 getNameAttribute 方法處理事後的同一篇文章的標題賦值給 $model_post_title。
最後,經過 assertEquals 方法比較兩個變量是否相等。
以上就是如何在 Laravel 中使用單元測試的使用方法。
這一節咱們將學習如何建立功能測試用例來對先前建立的控制器進行「功能測試」。
經過下面給出的命令,咱們將建立一個名爲 AccessorTest 的功能測試用例。注意這邊咱們沒有使用 --unit 命令行選項,因此命令會在 tests/Feature 目錄下建立一個「功能測試」用例。
$ php artisan make:test AccessorTest
命令會建立文件名爲 tests/Feature/AccessorTest.php 的測試類。
<?php // tests/Feature/AccessorTest.php namespace Tests\Feature; use Tests\TestCase; use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseTransactions; class AccessorTest extends TestCase { /** * A basic test example. * * @return void */ public function testExample() { $this->assertTrue(true); } }
一樣咱們替換掉 testExample 方法。
<?php // tests/Feature/AccessorTest.php namespace Tests\Feature; use Tests\TestCase; use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseTransactions; class AccessorTest extends TestCase { /** * A basic test example. * * @return void */ public function testBasicTest() { $db_post = DB::select('select * from posts where id = 1'); $db_post_title = ucfirst($db_post[0]->name); $response = $this->get('/accessor/index?id=1'); $response->assertStatus(200); $response->assertSeeText($db_post_title); } }
熟悉功能測試的朋友應該對上面的代碼不會太陌生。
首先,咱們仍是經過 DB 類使用原生 SQL 查詢到一篇文章,並將文章的標題賦值給 $db_post_title** 變量。接着咱們模擬一個訪問 **/accessor/index?id=1** URI 的 GET 請求,並經過 **$response 變量接收響應。
而後,咱們去匹配請求響應的狀態碼是否爲 200。在咱們的測試用例中的這個 GET 請求響應狀態碼應該是 200。此外,測試後還將獲取到一個首字母大寫的標題,判斷標題是否與 $db_post_title 相對的方法是 assertSeeText。
編寫完成全部的測試用例後。接下來須要去執行這些測試用例。在 Laravel 項目中運行 PHPUnit 測試用例,僅需在項目更目錄執行下面的命令。
$ phpunit
這個命令會運行項目中的全部測試用例。測試中的斷言會以標準的 PHPUnit 輸出顯示在控制檯。
今天,咱們探討了 Laravel 內置測試組件 PHPUnit 的測試用例實現方法。本文僅涉及 PHPUnit 「單元測試」和「功能測試」的基礎知識,工做中咱們還須要結合實際出發,對 PHPUnit 測試進行深刻研究才行。
此外,咱們還學習了經過使用 artisan 命令行工具建立分別建立了用於單元測試和功能測試的測試用例的方法。
若是你是 Laravel 初學者,或者抱着學習的目標擴展本身的視野,能夠關注 Envato Market
另外,不要害羞,就是幹!