---
# System prepended metadata

title: Laravel Testing
tags: [Laravel]

---

###### tags: `Laravel`

# Laravel Testing
[Laravel – Unit Test 單元測試教學](http://bit.ly/cary-test)

# 環境
- 建立測試用的資料庫
- 可以直接修改 .env 指定的 DATABASE 名即可
- 建立 Migration
- 建立 Model

# Factory 建立假資料工廠 
- php artisan make:factory PostFactory --model=Post
- --model=Post 他會自動幫你加 use 該 Model
- 建立的檔案位於 database/factories 之下
```php
	$factory->define(Post::class, function (Faker $faker) {
			return [
					// 回傳 $faker 產生的字、文章
					'title' => $faker->word,
					'content' => $faker->paragraph
			];
	});
```

# Unit Test (tests/Unit)
- php artisan make:test PostTest --unit
- --unit 將檔案放在 Unit 夾，預設為 Feature 夾
* 小心使用 use RefreshDatabase 不可用於正式環境
```php
class PostTest extends TestCase
{
    
    // 可以重整資料表，避免測試資料不斷累積。注意這會刪除所有資料，不要用在正式環境
    use RefreshDatabase;
    
    public function testExample()
    {
        // 建立5筆資料 (記得 Import Model)
        factory(Post::class, 5)->create();
				
        // 取得所有資料
        $posts = Post::all();
				
        // 判斷資料筆數: assertCount 首個變數為想要的值，後方為要檢查的資料
        $this->assertCount(5, $posts);
    }
}
```

# assert Functions 用來判斷資料是否正確
- [官方文件](http://bit.ly/laravel-assertFunc)

# Faker 假資料庫參數
- [官方文件](http://bit.ly/php-faker-type)

# 運行測試指令 vendor\bin\phpunit
- 他會去運行所有 tests 資料夾下的 *.php
- 寫於 tests 資料夾下的 Function，會被該指令執行
```php
	(Windows)
	vendor\bin\phpunit

	(Linux)
	vendor/bin/phpunit
```

# 僅測試特定 Function
- [stack overflow 看解2](http://bit.ly/laravel-test-one)
- Function 上方註解 可將該 Function 註冊在該 group
- 使用 vendor\bin\phpunit --group test 運行該組成員
```php
    /**
     * @group test
     * @group fail
     */
    public function testBasicTest()
    {
        $this->assertTrue(true);
    }
```

# Git Bash 可能會出錯
- PHPStorm 修改 Terminal 回 cmd.exe
- Tool/Terminal/shellPath "C:\Program Files\Git\bin\sh.exe"--login-i
- 修改成 cmd.exe 即可


# API Test (tests/Feature)
* 注意要測試的路由，請確認是否在 Route(web.php) 有編寫並且使用方法一致
* assertExactJson 一定要檢查所有欄位
*	assertJson      可只檢查其中幾項  (較常用) 
```php
class ProductTest extends TestCase
{
    public function testExample ()
    {
        $pid = 100;
        
        $response = $this
            ->withHeaders(['X-Header' => 'Value',])
            ->json('GET', 'products', [
                'id' => $pid,
            ]);
        
        $response
					->assertStatus(200)  // 檢查狀態碼 201 為 Created
					->assertJson([
                'id'    => $pid,
                'title' => true // 檢測存在(較常用)
                // 'title' => 'productTitle',  // 完全相同才行
            ]);
        
        
        // 若要為 Response 除錯，可以選用添加
        $response->dumpHeaders(); // 查看丟過來的 Header
        $response->dump(); // 查看丟過來的 Body
    }
}
```

# 測試錯誤訊息 彙整
- 紅: Failed
- 橘: OK, but incomplete, skipped, or risky tests!
- 綠: OK

```php
	// RED
	// Failed asserting that actual size 10 matches expected size 5.
	// 代表資料庫有10筆，但你檢測的要求為 5 筆
	
	// 此引用可以重整資料表，避免測試資料不斷累積。注意這會刪除所有資料，不要用在正式環境   
	use RefreshDatabase;
```
```php
	// OK, but incomplete, skipped, or risky tests!
	// Function 內必須有做事，否則會出現此訊息 !
	public function testBasicTest()
	{
			// 空 Function 可用 如下 檢查後面的值是否為 true，即可順利運行
			// $this->assertTrue(true);
	}
```

# 注意 test 的路徑
- Tests\Feature\ExampleTest 檔名下的 testBasicTest Function
- 希望收到 200 (OK) 但 404 (找不到)，可能是 Route 那邊沒有設定 '/'
- Expected status code 200 but received 404.
```php
	1) Tests\Feature\ExampleTest::testBasicTest
	Expected status code 200 but received 404.
	Failed asserting that false is true.
```