C#で自動テスト(Playwright) その2 もう少しテスト実用を考える

#### 前回
https://qiita.com/noritama08/items/ed3f79e7feb061e36774

C#でPlaywrightを用いた自動テストについてまとめた。
今回は実用観点で見つつ、補足や周辺知識を確認する。
是非、ご指摘・ご助言いただきたい。

## コード提案と結果の紹介
■テスト仕様書
Playwright for .NETの公式リファレンスページに関する結合テストケースを仮定する
　Videosのページが正常に開ける事を確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214861/daea4e96-fcaa-9985-b08a-98a0f2fe07ff.png)

テストNo → メソッド名に合わせる
　Case1-1-1はCase1_1_1とするなど
 
操作 → ロケーターに対しアクション

期待する結果 → アサート処理
　期待値があいまいな場合は判断方法を考える。
　今回の例では: ページのタイトル/要素から判断/ページ上部の見出し等

※ログイン/ログアウトなどの処理は前提なのでテストケースの外に出したい
■ソース
```Case1_1.cs
using System.Threading.Tasks;
using Microsoft.Playwright;
using Microsoft.Playwright.NUnit;
using NUnit.Framework;
// キャプチャ取得処理を外に出したい
using tools;

namespace PlaywrightTests;

[Parallelizable(ParallelScope.Self)]
[TestFixture]
public class Case1_1 : PageTest
{
    // キャプチャ取得準備
    public Tool tool;

    // 動画を撮影したい場合
    public override BrowserNewContextOptions ContextOptions()
    {
        return new BrowserNewContextOptions()
        {
            // 出力先: デフォルトはbin\Debug\net8.0\
            // クラス名( Case1_1 )でエビデンスをまとめる
            RecordVideoDir = "../../../output/videos/" + GetType().Name + "/",
        };
    }

    // 各Test注釈に対し毎回事前処理
    [SetUp]
    public async Task Init()
    {
        // ログイン処理
    }

    // 各Test注釈に対し毎回事後処理
    [TearDown]
    public async Task Clean()
    {
        // ログアウト処理
    }
    
    [Test]
    public async Task Case1_1_1()
    {
        // 指定URL先で,サイドメニュー(初期画面外)のVideosを押下する
        await Page.GotoAsync("https://playwright.dev/dotnet/docs/intro");
        await Page.GetByText("Videos").ClickAsync();

        // テスト結果判定: ページのTitleを確認する
        await Expect(Page).ToHaveTitleAsync("Videos | Playwright .NET");

        // テストケース名でキャプチャ取得
        tool = new Tool();
        await tool.getCapture(Page, GetType().Name);
    }
}
```
```Tools\tool.cs
using Microsoft.Playwright;
namespace tools;
public class Tool
{
    public async Task getCapture(IPage page, string name)
    {
        await page.ScreenshotAsync(new()
        {
            Path = "../../../output/captures/"
        });
    }
}
```
■実行するためのバッチ
```
rem テストを実行: ログ出力(追記)
rem デバッグ実行用の処理をON/OFF
rem set PWDEBUG=1
dotnet test -- Playwright.LaunchOptions.Headless=false >> output\.log
```
■実行結果
結果:OKの例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214861/96f08ee7-d77c-2b79-001d-6b0cd11c0e60.png)
結果:NGの例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214861/15424eb7-7ffc-87c4-19ec-d76d671574ad.png)
デフォルトで5秒待機、9回?試行してくれる

## 補足など
#### キャプチャ取得(画面ハードコピー)
```そうじゃない.cs
await Page.ScreenshotAsync(new(){Path = "screenshot.png",});
```
上記を元にもうちょっと使いやすくした
#### 動画撮影
[Test]単位でファイル出力される
ファイル名は指定できない → 実行後にケースNo.との紐づけができない
#### レポート作成
for .NETは非対応。ついでに画像比較も。
エビデンスとして、簡単なbatを作るのはありかもしれない
```
findstr -n "失敗" output\.log > output\report.txt
```
※文字コード変換でハマるので簡単の為以下の運用
　実行.batとは別に作成する
　実行.bat叩いた後 ログの文字コードをShift-JISに変換し、レポート.batを実行
　課題: 実行で都度文字コードがUTF-8に戻る/工数

■レポートのイメージ
↓ 全体サマリとNGメソッド名を出力する
10:  失敗 Case1_1_1 [9 s]
34:  失敗 Case1_1_2 [10 s]
70:失敗!   -失敗:     1、合格:     1、スキップ:     0、合計:     2、期間: 19 s - playwright_test.dll (net8.0)
↓
メソッド名からNGケースを特定
行数を元にログファイルからNG原因を特定
#### レポート作成 その2
Playwright for .NETは非対応...とはいえ、NUnitの方で対応できたのでご紹介。
```
dotnet test --logger "html;logfilename=testResult.html" > output\sample2.log
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214861/8348086c-d506-87ab-e548-c969e97dfdde.png)

#### ブラウザの指定
```
// firefox
dotnet test -- Playwright.BrowserName=firefox

// Edge
dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Channel=msedge 

// Chrome
dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Channel=chrome

// Chromeでかつ表示したい場合
dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Channel=chrome Playwright.LaunchOptions.Headless=false >> output\.log
```
#### テスト再試行
[Test, Retry(2)]の様な記載にする

NUnit属性

https://learn.microsoft.com/ja-jp/dotnet/core/testing/unit-testing-with-nunit

## 後書き
エビデンスの充実を理由にPlaywrightを選定したのに...
この辺をもっとしっかりするやり方ないでしょうか。。
動画: 名前めちゃめちゃ...せめてと思いフォルダ分け済み
【解決済み】スクショ: 1行にまとまらない
【解決済み】レポート: 非対応ですって!?