之前都是柿子挑軟的吃,專找簡單的好重構的目標下手。今天我們就來找個比較難搞的目標 Product 功能來試看看重構吧!
第一步當然要先寫測試,以下是個簡單的測試:
public function testAddProductAndSeeProduct()
{
/** @var Generator $faker */
$faker = $this->app->make(Generator::class);
$this->browse(function (Browser $browser) use ($faker) {
$image = $faker->image(base_path('storage/app/public'), 640, 480, 'cats');
$title = '野貓';
$content = '一天要吃十個罐罐!一天要吃十個罐罐!一天要吃十個罐罐!很重要要說三次';
$browser->visit('/admin.php?act=shop&op=view')
->assertSee('標題')
->assertSee('分類')
->assertSee('成本')
->type('title', $title)
->type('cost', 100)
->type('price', 200)
->type('store', 10)
->attach('pic', $image)
->type('content', $content)
->click('.mainFrameHelp > div > input[type="submit"]');
$browser->driver->switchTo()->alert()->accept();
$browser->assertSee($title)
->assertSee($content)
->stop();
});
}
這裡使用 Faker 建 image 與 Dust 上傳檔案的功能來做測試。
接著來處理樣版,後來才發現 admin.html
其實是子樣版也是其他 admin 頁面的主樣版,所以必須來處理一下:
admin.html
-> admin/index.blade.php
admin_shop.html
-> admin/product.blade.php
在程式裡載入 Blade 樣版檔成功後,調整樣版檔讓原本的測試通過。後面可以加測試檢查 Smarty Tags 是否有忘了沒改的:
public function testShouldNotSeeSmartyTagAtAdminProductPage()
{
$this->browse(function (Browser $browser) use ($faker) {
$browser->visit('/admin.php?act=shop&op=view')
->assertDontSee('<%')
->assertDontSee('%>');
});
}
再來開始切 Controller ,先把 op=view
複製出去,除了 controller 和 route 要調整外,測試也需要調整:
// controllers
class ProductController extends Controller
{
public function main(Request $request, Shop $shop)
{
$id = $request->query('id');
return view('admin.product', [
'one' => $shop->one($id),
'all' => $shop->all(),
'all_category' => $shop->allCategory(),
]);
}
}
// routes
Route::get('/admin/product', 'Admin\ProductController@main');
// tests
$browser->visit('/admin/product');
接著,因為剛剛 /admin.php?act=shop&op=view
這個連接是可用的,我們可以用這個字串來找到程式有哪裡連結到這頁,結果應該只有在後台出現:
<a href="/admin.php?act=shop&op=view">商品管理</a>
還有 PHP 程式裡處理的 showAlert
$shop->showAlert('商品已新增', 'admin.php?act=shop&op=view')
接著,補測試到一開始的 testAddProductAndSeeProduct
測試案例,我們改由首頁點過去:
$browser->visit('/admin')
->assertSee('商品管理')
->clickLink('商品管理')
// 新增完驗連線
$browser->assertPathIs('/admin.php');
這兩個加上去是會對的,接著我們把原本的實作拔掉,測試就會壞掉了,然後我們再想辦法修好它即可。
剩下的太多了,就不繼續做了。
如此做完的話,功能可靠度就會非常高,因為我們可以注意到,每次都會用測試來確認功能被改壞或是修好。如果有被改壞再修好的過程,開發者將可以非常確定,現在改的程式是真的修好功能的。