Playwrightの導入～ .envで環境依存の設定を切り替える

E2EテストツールPlaywrightを導入する際に実施した内容のメモです。

## 前提
- OS: Windows 11
- 開発環境：Node.js＋TypeScript
- VSCode＋Playwrightの拡張を使用
 
## インストール

Playwrightのインストール基本的に下記公式ドキュメントに従って行います。

https://playwright.dev/docs/intro

https://playwright.dev/docs/getting-started-vscode

`npm init` で最低限必要な一式のインストールができます
```powershell:PowerShell
PS C:\Work\playwright-template> npm init playwright@latest
```
コマンドを実行すると幾つか質問されるので、自身の目的に合わせて入力します。今回は下記の通りに設定しました。
```powershell:PowerShell
PS C:\Work\playwright-template> npm init playwright@latest
Getting started with writing end-to-end tests with Playwright:
Initializing project in '.'
√ Do you want to use TypeScript or JavaScript? · TypeScript
√ Where to put your end-to-end tests? · src/tests
√ Add a GitHub Actions workflow? (y/N) · false
√ Install Playwright browsers (can be done manually via 'npx playwright install')? (Y/n) · true
```

一通りの入力が終わると、下記のようなファイル一式が作成されます。

```plantuml
@startsalt
{
  {T
    + <size:20><&folder><b> playwright-template</b></size> | rootフォルダ
    ++ <size:20><&file> playwright.config.ts</size> | Playwright構成ファイル
    ++ <size:20><&file> package-lock.json</size>　| package-lock.json
    ++ <size:20><&file> package.json</size>　| package.json
    ++ <size:20><&folder><b> src</b></size>　| ソースコード格納用フォルダ
    +++ <size:20><&folder><b> tests</b></size> | テストコード格納用フォルダ
    ++++ <size:20><&file> example.spec.ts</size> | テストコード *.spec.ts
    ++ <size:20><&folder><b> tests-examples</b></size> | サンプルフォルダ
    +++ <size:20><&file> demo-todo-app.spec.ts</size> | サンプルコード
  }
}
@endsalt
```

## .envファイルから環境変数を取得する
テスト環境に依存する設定値を環境毎の.envファイルに分けて登録し、テスト実行時にそれらを使い分けるようにしたいと思います。

### dotenvをインストール
.envファイルの内容を環境変数として読み込むためのモジュールdotenvをインストールします。

```powershell:PowreShell
PS C:\Work\playwright-template> npm i dotenv
```
### .env、.env.* ファイルから環境変数を取得する処理の追加

playwright.config.tsの `// require('dotenv').config();` の部分を下記コードで置き換えます。

```ts:playwright.config.ts
/**
 * Read environment variables from file.
 * https://github.com/motdotla/dotenv
 */
const dotenv = require('dotenv');
//.env から環境変数を取得
dotenv.config({ path: '.env' });
//.env.${TEST_ENV} から環境変数を取得
if (process.env.TEST_ENV) {
  dotenv.config({
    path: `.env.${process.env.TEST_ENV}`,
    override: true
  });
}
```
- この設定ではまず、.env ファイルから値を取得します
- 次に環境変数`TEST_ENV`が定義されている場合に、`.env.${TEST_ENV}`から値を取得します(`TEST_ENV="local"`の場合`.env.local`から値を取得)
- 同じ変数が両方のファイルで定義されている場合、あとから取得する`.env.${TEST_ENV}`側の値で上書きされます

### 実装例

#### .envファイルを追加
今回は例として下記ような構成で.envファイルを追加します。
テスト対象のBase URLとテスト時のログインユーザー情報を記述しています。

```.env（本番環境用）
BaseUrl="https://hogehoge.com"
LoginUser="testAdmin"
LoginPassword="yyyyyyyy"
```

```.env.local（ローカルデバッグ用）
BaseUrl="http://localhost:80031"
LoginUser="testUser"
LoginPassword="xxxxxx"
```

```.env.staging（ステージング環境用）
BaseUrl="https://hogehoge-staging.com"
```
環境毎の設定は、本番環境の設定を上書きするようにしているため、本番環境と異なる値のみを記載すればOKです。


#### 環境変数を格納するクラスを追加
読み取った環境変数を参照するには`process.env.BaseUrl`の様に書けば良いのですが、参照用のクラスを作っておくと、コード補完が効いて便利です。

```ts:env.ts
export class Env {
    static BaseUrl: string = process.env.BaseUrl ?? '';
    static LoginUser: string = process.env.LoginUser ?? '';
    static LoginPassword: string = process.env.LoginPassword ?? '';
}
```

```plantuml
@startsalt
{
  {T
    + <size:20><&folder><b> playwright-template</b></size> | rootフォルダ
    ++ <size:20><&folder><b> src</b></size>　| ソースコード格納用フォルダ
    +++ <size:20><&folder><b> tests</b></size> | テストコード格納用フォルダ
    ++++ <size:20><&file> example.spec.ts</size> | テストコード *.spec.ts
    +++ <size:20><&file> env.ts</size> | <b>←追加
    ++ <size:20><&file> playwright.config.ts</size> | Playwright構成ファイル
    ++ <size:20><&file> package-lock.json</size>　| package-lock.json
    ++ <size:20><&file> package.json</size>　| package.json
    ++ <size:20><&file> .env</size>　| <b>←追加
    ++ <size:20><&file> .env.local</size>　| <b>←追加
    ++ <size:20><&file> .env.staging</size>　| <b>←追加
  }
}
@endsalt
```

#### BaseUrlの設定

BaseUrlは、playwright.config.tsに設定しておくことができます。せっかくですから環境変数から取得した値を設定するようにしましょう。

```ts:playwright.config.ts
export default defineConfig({
  //...(前略)
  use: {
    /* Base URL to use in actions like `await page.goto('/')`. */
    baseURL: process.env.BaseUrl,

    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: 'on-first-retry',
  },
  //...(後略)
```
#### 環境を指定して実行
テスト実行前に、対象の環境を`TEST_ENV`環境変数で指定します。
```powershell:PowerShell
# localの設定でテストを実行する
PS C:\Work\playwright-template> $env:TEST_ENV="local"
PS C:\Work\playwright-template> npx playwright test

```

#### launch.jsonの設定
VSCodeで実行、デバッグする場合にはlaunch.jsonで環境変数を切り替えるのが便利です。

```json:launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "production",
            "type": "node",
            "request": "launch",
            "program": "node_modules/@playwright/test/cli.js",
            "args":["test"]
        },
        {
            "name": "local",
            "type": "node",
            "request": "launch",
            "program": "node_modules/@playwright/test/cli.js",
            "args":["test"],
            "env":{
                "TEST_ENV":"local"
            }
        },
        {
            "name": "staging",
            "type": "node",
            "request": "launch",
            "program": "node_modules/@playwright/test/cli.js",
            "args":["test"],
            "env":{
                "TEST_ENV":"staging"
            }
        }
    ]
}
```
このように設定しておけば「実行とデバッグ」からテスト対象を選択するだけで、対象環境の切り替えが可能となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/b5882632-5206-78db-65cc-231113fe5e4e.png)