業務スケジュールテスト(PowerAutomateで実行するOfficeScripts)

## 関連記事
4つの記事に分けていますので参考にしてください
- [業務スケジュールパターン](https://qiita.com/mkuwan/items/ae03f5cc011c900fe2bc)
- [業務スケジュール設計](https://qiita.com/mkuwan/items/ff7fd78a88213188fb09)
- [業務スケジュール実装](https://qiita.com/mkuwan/items/d1d40a5de29a012c69f9)
- **業務スケジュールテスト(今回の記事)**

これまで業務スケジュールを自動作成するために、パターンの検証、設計、実装と進んできました。
最後は、作成した実装が設計に即しているかテストをしたいと思います。

## PowerAutomateを使用したテスト
ExcelでOfficeScriptを実行するため、自動テストを考え場合、PowerAutomateが有効な手段となります。
PowerAutomateでスクリプト実行を行わせます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/956246/94b55601-b684-4757-8ef7-bccfdcfbfd0c.png)
Excelからテストケースのデータを抽出し、スクリプトを実行、結果をExcelに書き込ませるというフローです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/956246/6851d376-86e2-4db5-820b-1f1492c14e53.png)
このSharePointコネクタのアクションでスクリプトを実行しています。
フロー図にすると以下の通りです。

```mermaid
graph TD
    A[行の一覧取得] --> B[変数を初期化]
    B --> C[For each]
    subgraph ForEach [各行に対して]
        C --> D[targetDate]
        D --> E[businessId]
        E --> F[SharePoint ライブラリからスクリプトを実行する]
        F --> G{期待結果 eq 対象}
        G --> H{対象の場合: 対象 業務ID eq 結果ID}
        H --> I[変数の設定 OK]
        H --> J[変数の設定 NG]
        G --> K{対象の場合: 対象 業務ID not eq 結果ID}
        K --> L[変数の設定 OK]
        K --> M[変数の設定 NG]
        I --> P[行を追加]
        J --> P[行を追加]
        L --> P[行を追加]
        M --> P[行を追加]
    end
```

## テスト用データ
本当に検証パターンを網羅しているかが重要ですが、実はこの作業がとても大変で、通常はマトリックス表を作ってパターンの洗い出しをすることが多いと思います。
しかし、こういうときこそAIの出番です。
設計ドキュメントを解析し、テスト用の業務一覧・テストケースを作成してもらうことができます。
しかし、このテストケースがAIにとっても厄介なようで、不要なテストや間違ったパターンを作成することがありました。
この辺りはプロンプトを工夫する必要があり、設計ドキュメントを基礎にすることを徹底させて、手順を示してテストデータを作成する必要がありました。
何度も作り直しを繰り返し、ようやく形になりました。

### 業務一覧
テスト用にパターンを網羅できるような業務一覧を作成しました。
以下の通りcsvファイルで作成しています。

```text
業務ID,業務名,業務詳細,業務種別,周期・頻度,基準,月,週番号,曜日,n日,非営業日振替規則,優先度,有効開始日,有効終了日,備考
1,毎日業務,,定常,日次,暦日,,,,,振替しない,通常,2024/1/1,,
2,毎営業日業務,,定常,日次,営業日,,,,,,通常,2024/1/1,,
3,毎週月曜業務,,定常,週次,暦日(曜日),,,月,,振替しない,通常,2024/1/1,,
4,毎週火曜業務,,定常,週次,暦日(曜日),,,火,,振替しない,通常,2024/1/1,,
5,毎週水曜業務,,定常,週次,暦日(曜日),,,水,,振替しない,通常,2024/1/1,,
6,毎週木曜業務,,定常,週次,暦日(曜日),,,木,,振替しない,通常,2024/1/1,,
7,毎週金曜業務,,定常,週次,暦日(曜日),,,金,,振替しない,通常,2024/1/1,,
8,毎週土曜業務,,定常,週次,暦日(曜日),,,土,,振替しない,通常,2024/1/1,,
9,毎週日曜業務,,定常,週次,暦日(曜日),,,日,,振替しない,通常,2024/1/1,,
10,毎月1日業務,,定常,月次,暦日(n日指定),,,,1,直後営業日,通常,2024/1/1,,
11,毎月2日業務,,定常,月次,暦日(n日指定),,,,2,直後営業日,通常,2024/1/1,,
12,毎月3日業務,,定常,月次,暦日(n日指定),,,,3,直後営業日,通常,2024/1/1,,
13,毎月4日業務,,定常,月次,暦日(n日指定),,,,4,直後営業日,通常,2024/1/1,,
14,毎月5日業務,,定常,月次,暦日(n日指定),,,,5,直後営業日,通常,2024/1/1,,
15,毎月10日業務,,定常,月次,暦日(n日指定),,,,10,振替しない,通常,2024/1/1,,
16,毎月15日業務,,定常,月次,暦日(n日指定),,,,15,振替しない,通常,2024/1/1,,
17,毎月20日業務,,定常,月次,暦日(n日指定),,,,20,振替しない,通常,2024/1/1,,
18,毎月25日業務,,定常,月次,暦日(n日指定),,,,25,振替しない,通常,2024/1/1,,
19,毎月末日業務,,定常,月次,暦日(月末逆算),,,,0,直前営業日,通常,2024/1/1,,
20,毎月末日から1日前業務,,定常,月次,暦日(月末逆算),,,,1,直前営業日,通常,2024/1/1,,
21,毎月末日から2日前業務,,定常,月次,暦日(月末逆算),,,,2,直前営業日,通常,2024/1/1,,
22,毎月末日から3日前業務,,定常,月次,暦日(月末逆算),,,,3,直前営業日,通常,2024/1/1,,
23,毎月末日から4日前業務,,定常,月次,暦日(月末逆算),,,,4,直前営業日,通常,2024/1/1,,
24,毎月最終営業日業務,,定常,月次,営業日(月末逆算),,,,0,,通常,2024/1/1,,
25,毎月最終営業日から1営業日前業務,,定常,月次,営業日(月末逆算),,,,1,,通常,2024/1/1,,
26,毎月最終営業日から2営業日前業務,,定常,月次,営業日(月末逆算),,,,2,,通常,2024/1/1,,
27,毎月最終営業日から3営業日前業務,,定常,月次,営業日(月末逆算),,,,3,,通常,2024/1/1,,
28,毎月最終営業日から4営業日前業務,,定常,月次,営業日(月末逆算),,,,4,,通常,2024/1/1,,
29,毎月第1月曜業務,,定常,月次,暦日(曜日),,1,月,,直後営業日,通常,2024/1/1,,
30,毎月第2月曜業務,,定常,月次,暦日(曜日),,2,月,,直後営業日,通常,2024/1/1,,
31,毎月第3月曜業務,,定常,月次,暦日(曜日),,3,月,,直後営業日,通常,2024/1/1,,
32,毎月第4月曜業務,,定常,月次,暦日(曜日),,4,月,,直後営業日,通常,2024/1/1,,
33,毎月第5月曜業務,,定常,月次,暦日(曜日),,5,月,,直後営業日,通常,2024/1/1,,
34,毎月第1火曜業務,,定常,月次,暦日(曜日),,1,火,,直後営業日,通常,2024/1/1,,
35,毎月第2火曜業務,,定常,月次,暦日(曜日),,2,火,,直後営業日,通常,2024/1/1,,
36,毎月第3火曜業務,,定常,月次,暦日(曜日),,3,火,,直後営業日,通常,2024/1/1,,
37,毎月第4火曜業務,,定常,月次,暦日(曜日),,4,火,,直後営業日,通常,2024/1/1,,
38,毎月第5火曜業務,,定常,月次,暦日(曜日),,5,火,,直後営業日,通常,2024/1/1,,
39,毎月第1水曜業務,,定常,月次,暦日(曜日),,1,水,,直後営業日,通常,2024/1/1,,
40,毎月第2水曜業務,,定常,月次,暦日(曜日),,2,水,,直後営業日,通常,2024/1/1,,
41,毎月第3水曜業務,,定常,月次,暦日(曜日),,3,水,,直後営業日,通常,2024/1/1,,
42,毎月第4水曜業務,,定常,月次,暦日(曜日),,4,水,,直後営業日,通常,2024/1/1,,
43,毎月第5水曜業務,,定常,月次,暦日(曜日),,5,水,,直後営業日,通常,2024/1/1,,
44,毎月第1金曜業務,,定常,月次,暦日(曜日),,1,金,,振替しない,通常,2024/1/1,,
45,毎月第3金曜業務,,定常,月次,暦日(曜日),,3,金,,振替しない,通常,2024/1/1,,
46,毎月第5金曜業務,,定常,月次,暦日(曜日),,5,金,,振替しない,通常,2024/1/1,,
47,毎月第1営業日業務,,定常,月次,営業日(n日指定),,,,1,,通常,2024/1/1,,
48,毎月第2営業日業務,,定常,月次,営業日(n日指定),,,,2,,通常,2024/1/1,,
49,毎月第3営業日業務,,定常,月次,営業日(n日指定),,,,3,,通常,2024/1/1,,
50,毎月第4営業日業務,,定常,月次,営業日(n日指定),,,,4,,通常,2024/1/1,,
51,毎月第5営業日業務,,定常,月次,営業日(n日指定),,,,5,,通常,2024/1/1,,
52,毎週水曜日業務,,定常,週次,暦日(曜日),,,水,,振替しない,通常,2024/1/1,,
53,毎週木曜日業務,,定常,週次,暦日(曜日),,,木,,直前営業日,通常,2024/1/1,,
54,毎週金曜日業務,,定常,週次,暦日(曜日),,,金,,直後営業日,通常,2024/1/1,,
56,1月1日業務,,定常,年次,暦日(n日指定),1,,,1,振替しない,通常,2024/1/1,,
57,2月1日業務,,定常,年次,暦日(n日指定),2,,,1,振替しない,通常,2024/1/1,,
58,3月1日業務,,定常,年次,暦日(n日指定),3,,,1,振替しない,通常,2024/1/1,,
59,4月1日業務,,定常,年次,暦日(n日指定),4,,,1,振替しない,通常,2024/1/1,,
60,5月1日業務,,定常,年次,暦日(n日指定),5,,,1,振替しない,通常,2024/1/1,,
61,6月1日業務,,定常,年次,暦日(n日指定),6,,,1,振替しない,通常,2024/1/1,,
62,7月1日業務,,定常,年次,暦日(n日指定),7,,,1,,通常,2024-01-01,,
63,8月1日業務,,定常,年次,暦日(n日指定),8,,,1,,通常,2024-01-01,,
64,9月1日業務,,定常,年次,暦日(n日指定),9,,,1,,通常,2024-01-01,,
65,10月1日業務,,定常,年次,暦日(n日指定),10,,,1,,通常,2024-01-01,,
66,11月1日業務,,定常,年次,暦日(n日指定),11,,,1,,通常,2024-01-01,,
67,12月1日業務,,定常,年次,暦日(n日指定),12,,,1,,通常,2024-01-01,,
68,3月1日四半期業務,,定常,年次,暦日(n日指定),3,,,1,,通常,2024-01-01,,
69,6月1日四半期業務,,定常,年次,暦日(n日指定),6,,,1,,通常,2024-01-01,,
70,9月1日四半期業務,,定常,年次,暦日(n日指定),9,,,1,,通常,2024-01-01,,
71,12月1日四半期業務,,定常,年次,暦日(n日指定),12,,,1,,通常,2024-01-01,,
72,3月最終営業日業務,,定常,年次,営業日(月末逆算),3,,,0,,通常,2024-01-01,,
73,6月最終営業日業務,,定常,年次,営業日(月末逆算),6,,,0,,通常,2024-01-01,,
74,9月最終営業日業務,,定常,年次,営業日(月末逆算),9,,,0,,通常,2024-01-01,,
75,12月最終営業日業務,,定常,年次,営業日(月末逆算),12,,,0,,通常,2024-01-01,,
76,2月29日業務,,定常,年次,暦日(n日指定),2,,,29,,通常,2024-01-01,,
77,12月25日業務,,定常,年次,暦日(n日指定),12,,,25,,通常,2024-01-01,,
78,3月第5金曜業務,,定常,年次,暦日(曜日),3,5,金,,,通常,2024-01-01,,
79,4月第2土曜業務,,定常,年次,暦日(曜日),4,2,土,,,通常,2024-01-01,,
80,1月第1営業日業務,,定常,年次,営業日(n日指定),1,,,1,,通常,2024-01-01,,
81,4月最終営業日業務,,定常,年次,営業日(月末逆算),4,,,0,,通常,2024-01-01,,
82,12月最終営業日業務,,定常,年次,営業日(月末逆算),12,,,0,,通常,2024-01-01,,
83,3月最終営業日業務,,定常,年次,営業日(月末逆算),3,,,0,,通常,2024-01-01,,
84,6月最終営業日業務,,定常,年次,営業日(月末逆算),6,,,0,,通常,2024-01-01,,
85,9月最終営業日業務,,定常,年次,営業日(月末逆算),9,,,0,,通常,2024-01-01,,
86,3月第1金曜業務,,定常,年次,暦日(曜日),3,1,金,,,通常,2024-01-01,,
87,3月第2金曜業務,,定常,年次,暦日(曜日),3,2,金,,,通常,2024-01-01,,
88,3月第3金曜業務,,定常,年次,暦日(曜日),3,3,金,,,通常,2024-01-01,,
89,3月第4金曜業務,,定常,年次,暦日(曜日),3,4,金,,,通常,2024-01-01,,
90,3月第5金曜業務,,定常,年次,暦日(曜日),3,5,金,,,通常,2024-01-01,,
91,3月第1月曜業務,,定常,年次,暦日(曜日),3,1,月,,,通常,2024-01-01,,
92,3月第2月曜業務,,定常,年次,暦日(曜日),3,2,月,,,通常,2024-01-01,,
93,3月第3月曜業務,,定常,年次,暦日(曜日),3,3,月,,,通常,2024-01-01,,
94,3月第4月曜業務,,定常,年次,暦日(曜日),3,4,月,,,通常,2024-01-01,,
95,3月第5月曜業務,,定常,年次,暦日(曜日),3,5,月,,,通常,2024-01-01,,
96,3月第1火曜業務,,定常,年次,暦日(曜日),3,1,火,,,通常,2024-01-01,,
97,3月第2火曜業務,,定常,年次,暦日(曜日),3,2,火,,,通常,2024-01-01,,
98,3月第3火曜業務,,定常,年次,暦日(曜日),3,3,火,,,通常,2024-01-01,,
99,3月第4火曜業務,,定常,年次,暦日(曜日),3,4,火,,,通常,2024-01-01,,
100,3月第5火曜業務,,定常,年次,暦日(曜日),3,5,火,,,通常,2024-01-01,,
101,有効開始日2024-01-01から,,定常,日次,暦日,,,,,振替しない,通常,2024/1/1,,
102,有効終了日2024-12-31まで,,定常,日次,暦日,,,,,振替しない,通常,2024/1/1,2024/12/31,
```

### テストケース
次はテストケースです。
```text
テストID,テスト内容,入力データ,テスト対象業務ID,期待結果,判定基準
1,日次業務（暦日）の判定,2025-05-15,1,対象,毎日実行される
2,日次業務（営業日）の判定-営業日,2025-05-15,2,対象,入力日が営業日の場合のみ実行
3,日次業務（営業日）の判定-非営業日,2025-05-18,2,対象外,入力日が営業日でない場合は対象外
4,週次業務（月曜）の判定-月曜日,2025-05-19,3,対象,入力日が月曜日の場合に実行
5,週次業務（月曜）の判定-火曜日,2025-05-20,3,対象外,入力日が月曜日でない場合は対象外
6,週次業務（火曜）の判定,2025-05-20,4,対象,入力日が火曜日の場合に実行
7,週次業務（水曜）の判定,2025-05-21,5,対象,入力日が水曜日の場合に実行
8,週次業務（木曜）の判定,2025-05-22,6,対象,入力日が木曜日の場合に実行
9,週次業務（金曜）の判定,2025-05-23,7,対象,入力日が金曜日の場合に実行
10,週次業務（土曜）の判定,2025-05-24,8,対象,入力日が土曜日の場合に実行
11,週次業務（日曜）の判定,2025-05-25,9,対象,入力日が日曜日の場合に実行
12,月次業務（暦日n日指定）の判定,2025-05-01,10,対象,入力日が1日の場合に実行
13,月次業務（暦日n日指定）・非営業日振替（直後）,2025-05-01,10,対象,5月1日が営業日の場合、そのまま実行
14,月次業務（暦日n日指定）・閾値チェック,2025-05-02,10,対象外,入力日が対象日と異なる場合は対象外
15,月次業務（暦日n日指定）の判定-別日,2025-05-15,16,対象,入力日が15日の場合に実行
16,月次業務（暦日n日指定）・振替なし・非営業日,2025-05-18,15,対象外,振替なしで非営業日の場合は対象外
17,月次業務（暦日月末逆算）の判定,2025-05-31,19,対象外,入力日が月末日だが非営業日のため対象外
18,月次業務（暦日月末逆算）・非営業日振替（直前）,2024-06-28,19,対象,6月30日（日曜・非営業日）の振替日（直前営業日）に実行
19,月次業務（暦日月末逆算n日前）の判定,2025-05-30,20,対象,入力日が月末から1日前の場合に実行
20,月次業務（営業日月末逆算）の判定,2025-05-30,24,対象,入力日が最終営業日の場合に実行
21,月次業務（営業日月末逆算）・閾値チェック,2025-05-29,24,対象外,入力日が最終営業日でない場合は対象外
22,月次業務（営業日月末逆算n日前）の判定,2025-05-29,25,対象,入力日が最終営業日から1営業日前の場合に実行
23,月次業務（第n曜日指定）の判定,2025-05-05,29,対象,入力日が第1月曜（祝日）の場合に実行（直後営業日振替適用）
24,月次業務（第n曜日指定）・非営業日振替（直後）,2025-06-02,29,対象,非営業日の振替日（直後営業日）に実行
25,月次業務（第n曜日指定）・閾値チェック,2025-05-12,29,対象外,入力日が第1月曜でない場合は対象外
26,月次業務（第5曜日存在チェック）,2025-05-26,33,対象外,第5月曜が存在しない月は対象外
27,月次業務（第5曜日存在チェック）,2025-06-30,33,対象,第5月曜が存在する月は対象
28,月次業務（第n営業日）の判定,2025-05-01,47,対象,入力日が第1営業日の場合に実行
29,月次業務（第n営業日）・閾値チェック,2025-05-02,47,対象外,入力日が第1営業日でない場合は対象外
30,月次業務（第n営業日）の判定,2025-05-07,49,対象,入力日が第3営業日の場合に実行
31,年次業務（暦日n日指定）の判定,2025-01-01,56,対象,指定月・指定日の場合に実行
32,年次業務（暦日n日指定）・月チェック,2025-02-01,56,対象外,指定月でない場合は対象外
33,年次業務（閏年チェック）・存在しない日,2025-02-29,76,対象外,閏年でない年の2月29日は対象外
34,年次業務（閏年チェック）・存在する日,2024-02-29,76,対象,閏年の2月29日は対象
35,年次業務（四半期業務）の判定,2025-03-01,68,対象,四半期ごとの指定日に実行
36,年次業務（四半期業務）・月チェック,2025-04-01,68,対象外,指定月でない場合は対象外
37,年次業務（営業日月末逆算）の判定,2025-03-31,72,対象,指定月の最終営業日の場合に実行
38,年次業務（営業日月末逆算）・月チェック,2025-04-30,72,対象外,指定月でない場合は対象外
39,年次業務（第n曜日指定）の判定,2025-03-07,86,対象,指定月の第1金曜日の場合に実行
40,年次業務（第n曜日指定）・月チェック,2025-04-04,86,対象外,指定月でない場合は対象外
41,年次業務（第5曜日）・存在しない週チェック,2025-03-31,90,対象外,第5金曜が存在しない場合は対象外
42,年次業務（第5曜日）・存在する週チェック,2025-05-30,46,対象,第5金曜が存在する場合に実行
43,振替規則（直前営業日）のテスト,2025-04-30,19,対象,4月30日は4月の最終営業日（直前営業日振替ルール適用）
44,振替規則（直後営業日）のテスト,2025-05-07,14,対象,5月5日（こどもの日・非営業日）の振替日として5月7日が対象
45,振替規則（振替なし）のテスト,2025-01-12,15,対象外,1月15日が休日の場合に振替なしで対象外
46,有効期間（開始日）チェック,2024-01-01,101,対象,有効開始日以降の日付は対象
47,有効期間（開始日）チェック,2023-12-31,101,対象外,有効開始日より前の日付は対象外
48,週次業務の振替規則（直前営業日）,2025-05-02,53,対象外,木曜日(5/1)が営業日の場合、翌日(5/2)は振替対象外
49,週次業務の振替規則（直後営業日）,2025-05-07,54,対象外,2025-05-02(金)が営業日のため振替対象外
50,連休時の振替規則テスト,2025-05-07,10,対象外,5月1日が営業日のため振替は発生せず、5月7日は対象外
51,営業日判定・祝日チェック,2025-05-05,2,対象外,祝日は営業日ではないため対象外
52,営業日判定・休日チェック,2025-05-10,2,対象外,土曜日は営業日ではないため対象外
53,月末日の営業日判定,2024-06-28,19,対象,6月30日（非営業日）の月末振替として6月28日が対象
54,年次業務（第1営業日）の判定,2025-01-06,80,対象,1月の第1営業日の場合に実行
55,年次業務（第1営業日）・月チェック,2025-02-03,80,対象外,指定月でない場合は対象外
56,日次業務・連続実行チェック,2025-05-14,1,対象,平日の連続実行
57,日次業務・連続実行チェック,2025-05-16,1,対象,平日の連続実行
58,月をまたぐ営業日判定,2025-05-30,24,対象,5月最終営業日
59,月をまたぐ営業日判定,2025-06-02,24,対象外,6月の日付で5月最終営業日判定
60,複合条件（年次+第n曜日）,2025-03-31,95,対象,3月第5月曜が存在する月は対象
61,GW中の振替規則テスト,2025-05-07,14,対象,5月5日（こどもの日）の振替日として5月7日が対象
62,月末直前営業日振替テスト,2025-05-30,19,対象,5月31日（土曜・非営業日）の振替として5月30日が対象
63,週次業務の振替規則（直後営業日）・休日の金曜日,2024-02-26,54,対象,2024-02-23(金・天皇誕生日)の振替日（直後営業日）として実行
64,複合条件（年次+第n曜日）・存在しない月,2025-04-28,95,対象外,4月第5月曜が存在しない月は対象外
65,有効期間（終了日）チェック,2024-12-31,102,対象,有効終了日当日は対象
66,有効期間（終了日）チェック,2025-01-01,102,対象外,有効終了日を過ぎた日付は対象外
67,四半期業務（6月）の判定,2025-06-01,69,対象,6月1日の四半期業務として実行
68,四半期業務（9月）の判定,2025-09-01,70,対象,9月1日の四半期業務として実行
69,四半期業務（12月）の判定,2025-12-01,71,対象,12月1日の四半期業務として実行
70,日次業務（振替なし）の土曜日チェック,2025-05-17,1,対象,毎日業務は土曜日も実行される
71,日次業務（振替なし）の日曜日チェック,2025-05-18,1,対象,毎日業務は日曜日も実行される
72,月次業務（第5営業日）の判定,2025-05-09,51,対象,入力日が第5営業日の場合に実行
73,年次業務（第3営業日）の判定,2025-03-05,49,対象,3月の第3営業日として実行
74,連続休日振替の複合チェック,2025-01-06,10,対象,1月4日（土）、5日（日）の後の最初の営業日に複数の振替が集中
75,閏年でない年の2月末日チェック,2025-02-28,19,対象,2月28日は非閏年の2月末日として処理
76,木曜週次業務の直前営業日振替テスト,2025-03-19,53,対象,3月20日（木・祝日）の振替日として3月19日（水）が実行対象
77,火曜週次業務の非営業日テスト,2024-12-31,4,対象,火曜日で振替なしルールで非営業日の場合も実行対象
78,水曜週次業務の非営業日テスト,2025-01-01,52,対象,水曜日でも振替なしルールで非営業日の場合も実行対象
79,月次業務（第2火曜）の判定,2025-05-13,35,対象,入力日が第2火曜日の場合に実行
80,月次業務（第3水曜）の判定,2025-05-21,41,対象,入力日が第3水曜日の場合に実行
81,月次業務（暦日月末逆算2日前）の判定,2025-05-29,21,対象,入力日が月末から2日前の場合に実行
82,月次業務（暦日月末逆算3日前）の判定,2025-05-28,22,対象,入力日が月末から3日前の場合に実行
83,年次業務（6月最終営業日）の判定,2025-06-30,73,対象,6月の最終営業日の場合に実行
84,年次業務（9月最終営業日）の判定,2025-09-30,74,対象,9月の最終営業日の場合に実行
85,年次業務（12月最終営業日）の判定,2025-12-30,75,対象,12月の最終営業日の場合に実行
86,同一日に複数業務集中テスト,2025-03-03,91,対象,3月第1月曜に複数業務（第1月曜かつ3日）が重なる場合
87,同一日に複数業務集中テスト,2025-03-03,29,対象,同一日に複数業務（第1月曜と第1営業日）が重なる場合
88,年末年始連続休暇の振替処理テスト,2025-01-02,11,対象,1月2日が1月1日（祝日）の振替日として実行
89,年次業務（12月25日）の判定,2025-12-25,77,対象,12月25日に実行される特定日付業務
```

### テスト実行用にコードを修正
以前の記事でソースコードを掲載しましたが、mainメソッドを以下のように修正しました。
```ts
function main(workbook: ExcelScript.Workbook, targetDate: string = "", businessIds: string = "", isTest: boolean = false): string {
```
検証する日付、業務IDを入力できるようにします。
またテスト用のフラグを設定しました。

元のコードは業務一覧からすべての業務を読み込んでいますが、ここにテストフラグ検証を追加して、テストの場合は入力された業務IDのみを抽出するようにしました。

```ts
        // 業務IDが指定されている場合、該当するデータのみを抽出　(主にテストで使用する想定です)
        if (businessIds && businessIds !== "") {
            debugLog(workbook, `指定された業務ID: ${businessIds}`);

            // 既存のデータをクリア(テストで使用するため)
            if (isTest) {
                const scheduleSheet = workbook.getWorksheet("業務スケジュール");
                const existingRange = scheduleSheet.getUsedRange();
                if (taskSheet && existingRange.getRowCount() > 1) {
                    // ヘッダー行以外をクリア
                    const dataRange = scheduleSheet.getRange(`A4:I${existingRange.getRowCount()}`);
                    dataRange.clear();
                }
            }

```

## テストの実施
PowerAutomateでExcelの読み込み・書き込みをさせていますが、スクリプトではデバッグログを書きこませているので時間がかかります。

テストが自動実行できるので、裏で勝手にやってもらえばいいわけなので、テストの速度を改善することはしていません。デバッグログなしにすればかなり早くなるのですがログ出力は大事なので・・・。

クラウド上のExcelだとスクリプト実行に1件あたり30秒弱かかるようでした。
それでも手作業で1件ずつテストするよりも効率的ですね。

### 結果
こんな感じで出力されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/956246/8a03870b-da91-4ed8-8c9d-557fc3ca4595.png)

一発で全部OKにはなりませんでした。
NGがあった場合は、まとめて修正するのではなく、1件ずつAI(Github Copilot)に問い合わせると、正しく検証してくれました。

### NGの修正指示とAIによる解析結果

```text
テストID60ですが、テストを実施した結果NGとなりました。
原因を確認してください。
```
```text
テストID60のテスト結果がNGとなった原因を確認するために、まずテストケースの内容を詳しく確認します。

テストID60は「複合条件（年次+第n曜日）」のテストで、日付が2025-03-31、テスト対象業務IDが95となっています。
期待結果は「対象外」で、判定基準は「3月第5月曜が存在しない場合は対象外」となっています。

まず、このテストケースに関連する情報をさらに収集してみましょう。

これで業務ID 95に関連する情報が見つかりました。こちらは「3月第5月曜業務」であり、年次業務で「暦日(曜日)」タイプであることがわかります。

テスト仕様では、「3月第5月曜が存在しない場合は対象外」という判定基準で、テスト日付2025-03-31における実行結果が「対象外」であることを期待しています。

次に、2025年3月のカレンダーを確認して、第5月曜日が存在するかどうかを調べる必要があります。
2025年3月のカレンダーを確認するために、PowerShellコマンドを実行してみましょう。
```
```powershell
$startDate = Get-Date -Year 2025 -Month 3 -Day 1; $endDate = $startDate.AddMonths(1).AddDays(-1); $calendar = for ($day = $startDate; $day -le $endDate; $day = $day.AddDays(1)) { [PSCustomObject]@{ Date = $day.ToString('yyyy-MM-dd'); DayOfWeek = $day.DayOfWeek } }; $calendar | Where-Object { $_.DayOfWeek -eq 'Monday' } | Format-Table
```
```text
コマンドの結果が空のため、エラーが発生した可能性があります。PowerShellのコマンドを修正して再試行します。
```
```powershell
$startDate = Get-Date -Year 2025 -Month 3 -Day 1; $endDate = $startDate.AddMonths(1).AddDays(-1); $days = @(); for ($day = $startDate; $day -le $endDate; $day = $day.AddDays(1)) { if ($day.DayOfWeek -eq 'Monday') { $days += $day.ToString('yyyy-MM-dd') } }; Write-Output "2025年3月の月曜日:"; $days
```
```text
2025年3月の月曜日は以下のとおりです：

2025-03-03（第1月曜日）
2025-03-10（第2月曜日）
2025-03-17（第3月曜日）
2025-03-24（第4月曜日）
2025-03-31（第5月曜日）
興味深いことに、2025年3月には第5月曜日が存在します（2025-03-31）。
テストID60の判定基準では「3月第5月曜が存在しない場合は対象外」となっていますが、実際には2025年3月の第5月曜日は存在します。

そのため、期待される結果が「対象外」となっていることには矛盾があります。
テスト仕様書では、第5月曜が存在しない場合は対象外とされていますが、2025年3月には第5月曜日が存在するため、実際の結果は「対象」になるはずです。

このNG結果の原因は以下の可能性が考えられます：

テストケースの記述ミス：テストケースの判定基準が誤っている可能性があります。
2025年3月には第5月曜日が実際に存在するため、「第5月曜が存在しない場合は対象外」という判定基準は誤りです。

実装上の問題：業務ID 95（「3月第5月曜業務」）の実装において、第5月曜日の存在チェックに問題がある可能性があります。
例えば、カレンダー計算で第5月曜日が正しく検出されていない可能性があります。

テスト実施時の環境問題：テスト実行時に使用されたカレンダーデータに問題があり、2025年3月の第5月曜日が誤って「存在しない」と判定された可能性があります。

スケジューラーのコードを確認して、第5月曜日の存在チェックがどのように実装されているかを確認してみましょう。

scheduler.osts の 1 から 501 行を読み取り

スケジューラーのコードの続きを確認しましょう：

scheduler.osts の 501 から 1001 行を読み取り

それでは、問題となっている部分を確認するため、特に関連するisCalendarDayWeekDayTask関数とgetNthDayOfWeekInMonth関数について詳しく見てみました。

コードから以下の流れが分かります：

getNthDayOfWeekInMonth 関数は月の第n曜日を計算します。この関数が0を返す場合、その月にその第n曜日は存在しないことを意味します。

isCalendarDayWeekDayTask 関数では、まずgetNthDayOfWeekInMonthを呼び出して第n曜日の日付を取得し、その戻り値が0の場合は「その月に第n曜日は存在しない」としてfalseを返しています。

これで問題の原因が明らかになりました。2025年3月には第5月曜日が実際に存在します（2025-03-31）。
しかし、テスト仕様では「3月第5月曜が存在しない場合は対象外」という判定基準となっています。
つまり、2025年3月には第5月曜が存在するため、実行結果は「対象」になるはずです。

テストケースの期待結果「対象外」と実際の結果「対象」の間に不一致があります。

ここでのNG原因は以下のいずれかに該当すると考えられます：

テストケースの仕様ミス：2025年3月には第5月曜日が存在するため、「第5月曜が存在しない場合は対象外」という判定基準は誤りです。正しくは「第5月曜が存在する場合は対象」とすべきです。

カレンダーデータの不整合：テスト実行時に使用されたカレンダーデータと実際のカレンダーデータに差異がある可能性があります。

システムの実装ミス：第5月曜日の存在チェックが正しく行われていない可能性があります。

2025年3月には実際に第5月曜日（2025-03-31）が存在することを確認しました。そのため、最も可能性が高いのはテストケースの仕様ミスです。
テストID60の判定基準が誤っていて、正しくは「3月第5月曜が存在する場合は対象」とすべきでした。

結論
テストID60のNG原因は、テストケースの判定基準と実際のカレンダーが一致していないことです。
2025年3月には第5月曜日（2025-03-31）が存在します。そのため：

業務ID 95の「3月第5月曜業務」は、第5月曜日が存在する場合に実行されるはずです。
2025年3月には第5月曜日が存在するため、この日付で実行されるべきです。
テストケースの期待結果が「対象外」となっているのは誤りで、正しくは「対象」とすべきです。
対応策としては、テストケースの期待結果を修正するか、別の月（例えば第5月曜日が存在しない2025年4月など）でテストを行うべきです。
```

このように正確に分析をしてくれました。
設計をAIフレンドリーにすることで、分析精度が上がるように思います。

実際の開発現場ではテストNGの時の原因を探すのはとても労力と時間を必要とすることがあります。
この時短ができる可能性を見られたのはとても良かったです