iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 19
0

部落格要能夠顯示文章,首先我們的資料庫中要先有文章。

所以今天要來加入一個路由,用來新增一則貼文。

  • 關於 如何使用範例程式碼,請參考 TDD 實戰 D1
    • 本篇版本包含:4e4f

貼文路由

紅燈

class PostTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();

        $this->withoutExceptionHandling();
    }

    public function testInsertPostByGetRoute()
    {
        $text = "It's a new post.";

        $this->get("/posts/insert?post_text=$text");
        $response = $this->get('/posts/');

        $response->assertSee($text);
    }
}

我們新增了兩個函式:setUp()testInsertPostByGetRoute()

setUp()

setUp() 是所謂的 Fixture 函式 (中文直翻:"固定裝置"),用途是在每個測試函式執行前,都會先執行 setUp 的內容。

將那些同樣的事前設定移到 setUp,就能減少在各個測試中重複的程式碼,其他類似的還有 tearDown() 在每個測試後執行,另外也可以只在整個測試類別執行一次的,有 setUpBeforeClass()tearDownAfterClass() 可以幫忙。

以及在 Laravel 中使用 fixture,需要呼叫,父類別的函式:parent::setUp()

withoutExceptionHandling()

有時 PHPUnit 預設並不會把所有錯誤訊息列出來,這樣寫測試時會不容易追蹤錯誤的源頭。

因此在 setUp 中加入 withoutExceptionHandling。

綠燈

// routes/web.php
Route::get('/posts/insert', function(Request $request) {
    $post = new Post;
    $post->post_text = $request->input('post_text');
    $post->save();
});

( $ git checkout 4e )

這裡的 $post 是 Eloquent 的用法,所謂 ORM (Object Relational Mapping)。

這個 Post 是存取資料庫的介面,同時也包含該筆資料的內容。

建立物件後用直接用 成員變數名稱設值,再以 save() 存進資料庫。

$request 物件會接收當次 request 的輸入,用 input('key') 取值。

重構

這邊來做一次重構,體驗一下 TDD 的魔力。

我們原本直接把函式內容,用 closure 的方式寫在 路由中,也就是

Route::get('/posts/insert', function(Request $request) {
    ...
});

然而我們可以借助 MVC 的架構,將 路由執行邏輯 分開,也就是 ViewController,讓程式碼能夠更簡潔易讀。

以 Artisan 指令創建 PostController:

$ php artisan make:controller PostController

將剛剛路由中的程式碼搬過來。

<?php
// app/Http/Controllers/PostController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Post;

class PostController extends Controller
{
    public function insertPost(Request $request)
    {
        $post = new Post;
        $post->post_text = $request->input('post_text');
        $post->save();
    }

    public function allPost()
    {
        $response = "All Posts: ";
        $posts = Post::all();
        foreach ($posts as $post) {
            $response .= $post;
        }
        return $response;
    }
}

接著再把路由改成,呼叫這裡的控制器函式。

Route::get('/posts/', 'PostController@allPost');

Route::get('/posts/insert', 'PostController@insertPost');

( $ git checkout 4f )

於是路由這邊各自變成了簡短的一行,接著再次執行測試。

$ ./vendor/bin/phpunit
PHPUnit 8.3.5 by Sebastian Bergmann and contributors.

....                                                                4 / 4 (100%)

Time: 446 ms, Memory: 26.00 MB

通過!

即使做了一些修改,但是原本的測試依然通過,瞬間就能夠確保,我們的程式並沒有被破壞掉,感覺還不賴。

完成

今天我們完成了新增貼文的路由,接著試了重構看看,明天再來繼續強化他。


上一篇
TDD 實戰 D4:Laravel 資料庫 (3)
下一篇
TDD 實戰 D6:Laravel POST 方法 與 表單
系列文
如何一步步實踐TDD (測試驅動開發)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言