Nuxt/Laravel サービスにソフトウェアテストを導入

## VSCodeの設定
### 現状の設定 （自動補完系のみ）
#### バックエンド
* PHPIntelephense
* Laravel Extension Pack
#### フロントエンド
* ESLint
* Prettier - Code formatter
* Vue Official
* Vetur
* JavaScript (ES6) code snippets

## 静的解析ツールの導入

### Larastan （バックエンド）

#### 選定理由
* PHPで有名なPHPStanという静的解析ツールの拡張であったため
* 調べたところ、Laravelにおけるデファクトスタンダードであったため

#### 導入方法
下記の情報を参考に導入しました。
* https://github.com/larastan/larastan/blob/2.x/README.md
* https://qiita.com/aosan/items/420e339d4b5941aac048

***

### ESLint （フロントエンド）

#### 選定理由
* 調べたところ、フロントエンドにおけるデファクトスタンダードであったため
* 現状、VSCodeの拡張機能として有効化しており、互換性があるため

#### 導入方法
Nuxtの公式ドキュメントを参考にFlat Configでの導入をしました。
プロジェクト作成時に導入していなかったためか、クイックスタートでは動かなかったので、下記の方法で導入しました。
* https://eslint.nuxt.com/packages/module

ESLintとNuxt用プラグインをインストール
```
yarn add --dev @nuxtjs/eslint-module eslint eslint-plugin-nuxt
```

TypeScript用ESLintプラグインをインストール
```
yarn add --dev @typescript-eslint/parser @typescript-eslint/eslint-plugin
```
ESLintの初期化
```
npx eslint --init
```
Flat Configでの設定用のeslint.config.mjs生成
```
npx nuxi module add eslint
```
そして公式ドキュメントを基にeslint.config.mjsに記述を追加し、package.jsonに追記すると利用できます。
ちなみに、私の環境ではeslint.config.mjsについては、下記のとおり記述しました。

```
// @ts-check
import withNuxt from "./.nuxt/eslint.config.mjs";

export default withNuxt(
  // Your custom configs here
  {
    rules: {
      "no-console": "off",
      "vue/html-self-closing": "off",
    },
  },
);
```

## コードフォーマッターの導入

### Laravel Pint （バックエンド）

#### 選定理由
* Laravel9以降デフォルトで入っているプラグインのため
* PHP Formatter で有名な PHP-CS-Fixer をラッパーしているもので、よりLaravelに特化した自動整形を期待できるため

#### 導入方法
Laravel9以降であればデフォルトで入っています。

***

### Prettier （フロントエンド）
#### 選定理由
* 調べたところ、フロントエンドのデファクトスタンダードであったため
* 現状、VSCodeの拡張機能として有効化しており、互換性があるため

#### 導入方法
下記の記事を参考に導入しました。
* https://notes.nakurei.com/post/nuxt3-prettier-setup-guide/

## pre-commitフックでESLintとPretterを走らせる
### huskyとlint-stagedの導入
これら2つを導入すると、コミット前に、変更があったファイルにのみESLintとPrettierを走らせることが可能です。
#### 導入方法
公式ドキュメントと記事を参考に導入しました。
* https://typicode.github.io/husky/
* https://zenn.dev/risu729/articles/latest-husky-lint-staged

## プッシュ時にLarastanとLaravel Pintを走らせる

#### 導入理由
* CI/CDツールを使用してみたかったため
* GitHubにアカウントやリポジトリがあれば、他社のCIサービスと別途契約しなくても良くお手軽であったため

#### 導入方法
下記の情報を参考に導入しました。

* https://docs.github.com/ja/actions
* https://qiita.com/aosan/items/420e339d4b5941aac048
* https://zenn.dev/tatsuyaaa/articles/bd5b73ef1f1882

## PHPUnitの使用

### 導入した意図
* 実務で機能の実装をする際に、単体テストを行う場面が多々あると考えており、経験しておきたかったため
* 今回はまず、GETとPOSTそれぞれのHTTPリクエストについて一つずつ作成しました

### PHPUnitの採用理由
* 調べたところ、PHPにおけるテストフレームワークのデファクトスタンダードであったため
* Laravelにデフォルトで搭載されており、手軽に実装できるため

### お気入り一覧取得テスト (GET)
下記のとおり作成しました。

```
public function test_user_favorite_drinks(): void
    {
        $drinks = Drink::factory(5)->create();
        $favorites = Favorite::factory(2)->create();

        $user = $favorites->first()->user;

        $response = $this->actingAs($user)->get('api/mypage/');

        $userFavorites = Favorite::where('user_id', $user->id)->pluck('drink_id');

        $this->assertTrue($userFavorites->isNotEmpty());

        $this->assertCount(1, $userFavorites);

        $drinks = Drink::whereIn('id', $userFavorites)->get();

        $response->assertStatus(200);

        $response->assertJsonCount(1);

        $response->assertJson([
            [
                'id' => $drinks->first()->id,
                'name_en' => $drinks->first()->name_en,
            ]
        ]);
    }
```

### ユーザー登録テスト (POST)

```
public function test_new_users_can_register(): void
    {
        $response = $this->post('api/register', [
            'name' => 'Test User',
            'email' => 'test@test.com',
            'password' => 'password',
        ]);
        $this->assertAuthenticated();
        $response->assertJson([
            'created' => true,
        ]);
    }
```

## おわりに
* 今までの開発では、VSCodeの拡張機能しか使用していませんでした。静的解析ツールとコードフォーマッターを使用することで、コードの品質を向上させることができました
* gitのprecommitフックや、GitHubActionsを使用し、自動的に静的解析ツールとコードフォーマッターを走らせることで、品質の低いコードをコミット／プッシュすることを防ぐ方法を学べました
* PHPUnitでのテストコードの記述方法について学ぶことができました
* 間違っている点等ありましたら、ご指摘いただけますと幸いです！