Google Geminiを利用したソース解析がそれなりにうまくいった話

# はじめに
この記事では、GoogleGeminiが実際の開発で、
どのような用途でどれぐらい利用できるのか、ざっくり検証したものになります。
前回は、Geminiさんと齟齬しか生じなかったお話。

環境は、以下のとおりです。

| 環境 | 詳細 | 
| - | - |
| Gemini | Gemini Advanced | 
| 検証アプリケーション | Google Spreadsheet(GAS) | 

# 作業内容
以前技術合宿で作成したWEBアプリ(GAS&Spreadsheet)をGeminiさんに食わして、
引き続きソース解析を行っていきます。
前回はGoogleDriveの該当ソースのURLを貼りつけて失敗したので、
今回はソースをまるっとプロンプトとして貼りつけて確認します。
step数が少ないソースでよかったね！
なお、前回と同じスレッド(チャット)で確認しています。

## ソースの解析
### プロンプト
```
じゃあ、ソースを貼りますね。GASです！

const sheet_id = '1YeBsRg9RBd1F1Uxxxxxxxxxxxxxxx';
const sheet_name = 'log';
…
```
### 回答
```
分析が正常に完了しませんでした

Gemini に問題が発生しました
コード全体を眺め、各関数の機能を調べます。

コードの機能を分析した結果、addFlightData 関数は https://data-live.flightradar24.com/zones/fcgi/feed.js からデータを取得し、スプレッドシートに書き込んでいることがわかりました。

このAPIがどのようなデータを返却するのか、具体的に確認していきましょう。
リクエストを処理できませんでした。プロンプトを書き変えて、もう一度お試しください。
```
### 検証
ようやくそれっぽい回答が来ましたが、
プロンプトがマズイということで詳細まで解析ができませんでした。
ただ、何がまずかったのかいまいちわからなかったので、
プロンプトの指示部分を省いて、ソースのみ貼りつけます。

### プロンプト
```
const sheet_id = '1YeBsRg9RBd1F1Uxxxxxxxxxxxxxxx';
const sheet_name = 'log';
const addFlightData  = () => {
…
```
### 回答
```
このGASのコードは、Flightradar24というサービスから航空機のリアルタイムデータを取得し、Googleスプレッドシートに記録、さらにそのデータをウェブアプリケーションで表示する機能を提供しています。

コードの解説

addFlightData関数:

Flightradar24のAPI (https://data-live.flightradar24.com/zones/fcgi/feed.js) を呼び出し、指定された範囲の航空機データを取得します。
取得したデータをパースし、aircraft プロパティに含まれる各航空機の情報をスプレッドシートの log シートに1行ずつ追加します。
getLastRecords関数:

スプレッドシートの log シートの最後の2行のデータを取得します。
各行のデータから、時刻、便名、速度、高度、出発地、目的地、緯度、経度を抽出し、フォーマットを整えます。
フォーマットされたデータをJSON形式の文字列に変換して返します。
getHistoryRecords関数:

スプレッドシートの log シートの最後の100行のデータを取得します。
getLastRecords関数と同様に、各行のデータから必要な情報を抽出し、フォーマットを整えてJSON形式の文字列に変換して返します。
getAppUrl関数:

デプロイされたウェブアプリケーションのURLを取得して返します。
doGet関数:

ウェブアプリケーションとしてデプロイされた際に、HTTP GETリクエストを処理します。
リクエストパラメータ page の値に基づいて、HTMLテンプレートファイルを選択し、HTML出力を生成します。
HTML出力のタイトルとファビコンを設定し、クライアントに返します。
コードの目的

このコードは、特定の地域の航空機情報をリアルタイムで監視し、その履歴を記録、可視化するためのものです。

addFlightData 関数は、定期的に実行することで、最新の航空機情報をスプレッドシートに記録し続けることができます。
getLastRecords 関数と getHistoryRecords 関数は、ウェブアプリケーションで最新の航空機情報や履歴を表示するために使用されます。
doGet 関数は、ウェブアプリケーションのユーザーインターフェースを提供します。
改善点

エラー処理: API呼び出しやスプレッドシート操作でエラーが発生した場合の処理を追加することで、コードの安定性を向上させることができます。
データのバリデーション: APIから取得したデータや、スプレッドシートに書き込むデータのバリデーションを追加することで、データの整合性を保つことができます。
セキュリティ: ウェブアプリケーションとしてデプロイする場合、認証や認可の仕組みを追加することで、セキュリティを強化することができます。
効率性: スプレッドシートへの書き込み処理を最適化することで、パフォーマンスを向上させることができます。
可読性: 変数名や関数名をよりわかりやすくすることで、コードの可読性を向上させることができます。
その他

コードに含まれる bounds パラメータは、Flightradar24 APIでデータを取得する際の地理的な範囲を指定しています。このパラメータを変更することで、異なる地域の航空機情報を取得することができます。
doGet 関数で使用されているHTMLテンプレートファイルの内容は不明ですが、おそらく航空機情報を表示するための地図やテーブルなどが含まれていると思われます。
このコードは、航空機情報の監視システムの基礎となるものであり、さらなる機能追加や改良によって、より高度なシステムを構築することができます。
```
### 検証
きたきた！ようやくほしい回答が返ってきましたね。
実際のソースを相違なく、概要をまとめてくれています。

しかもこれまでのプロンプトで特にお願いしていないのに、
改善点として、仕様レベルからの改善案を提案してくれます。
これこそ、まさにGAIのメリットですね。

このアプリケーションが技術合宿で作成した、24h限定成果物だったので、
まさに時間があればやりたかったことを挙げてくるのは、さすがです！

この波に乗りながら、テストについても相談しちゃいます。

## テストについてご相談
### プロンプト
```
では、このコードで単体テストを行う場合のテストパターンを教えてください
```
### 回答
```
このGASコードに対して単体テストを行う場合、各関数の機能を検証するために、以下のテストパターンを検討できます。

1. addFlightData 関数

正常系:
Flightradar24 APIからデータが正常に取得できる場合に、スプレッドシートに正しくデータが追加されることを確認します。
モックデータを使用してAPIからのレスポンスをシミュレートし、スプレッドシートへの書き込みが期待通りに行われることを検証します。
異常系:
Flightradar24 APIからデータが取得できない場合（ネットワークエラー、APIエラーなど）の処理を検証します。
例外処理が正しく行われ、エラーログが出力されることなどを確認します。
スプレッドシートへの書き込みに失敗した場合の処理を検証します。
例外処理が正しく行われ、エラーログが出力されることなどを確認します。
2. getLastRecords 関数

正常系:
スプレッドシートにデータが存在する場合に、最後の2行のデータが正しく取得され、フォーマットされてJSON形式で返されることを確認します。
異なるデータパターンでテストを行い、時刻、便名、速度、高度などの情報が正しく処理されていることを検証します。
異常系:
スプレッドシートにデータが存在しない場合の処理を検証します。
空のJSON配列が返されるか、エラー処理が正しく行われることを確認します。
スプレッドシートからデータを取得できない場合の処理を検証します。
例外処理が正しく行われ、エラーログが出力されることなどを確認します。
3. getHistoryRecords 関数

正常系:
スプレッドシートにデータが存在する場合に、最後の100行のデータが正しく取得され、フォーマットされてJSON形式で返されることを確認します。
異なるデータパターンでテストを行い、時刻、便名、速度、高度などの情報が正しく処理されていることを検証します。
異常系:
スプレッドシートにデータが存在しない場合の処理を検証します。
空のJSON配列が返されるか、エラー処理が正しく行われることを確認します。
スプレッドシートからデータを取得できない場合の処理を検証します。
例外処理が正しく行われ、エラーログが出力されることなどを確認します。
100行未満のデータしかない場合の処理を検証します。
存在する全てのデータが正しく取得されることを確認します。
4. getAppUrl 関数

正常系:
デプロイされたウェブアプリケーションのURLが正しく取得されることを確認します。
GASプロジェクトのデプロイ設定を変更し、URLが正しく更新されることを検証します。
5. doGet 関数

正常系:
異なる page パラメータ値でリクエストを行い、対応するHTMLテンプレートファイルが正しく読み込まれ、HTML出力が生成されることを確認します。
HTML出力のタイトルとファビコンが正しく設定されていることを検証します。
異常系:
存在しない page パラメータ値でリクエストを行った場合の処理を検証します。
エラーページが表示されるか、デフォルトのページが表示されることを確認します。
HTMLテンプレートファイルの読み込みに失敗した場合の処理を検証します。
例外処理が正しく行われ、エラーログが出力されることなどを確認します。
これらのテストパターンに加えて、以下の点も考慮すると良いでしょう。

境界値テスト: データの境界値や、処理の境界条件をテストすることで、予期せぬエラーを検出することができます。
パフォーマンス: 特に addFlightData 関数や getHistoryRecords 関数は、大量のデータを処理するため、パフォーマンスのテストも重要です。
セキュリティ: ウェブアプリケーションとしてデプロイする場合、セキュリティテストを実施し、脆弱性がないことを確認する必要があります。
これらのテストパターンを参考に、GASコードの品質向上に努めてください。
```
### 検証
長いけど、ちゃんと考えてくれますね。
ただ、考え方はわかりますが、実際のテストパターン作成するには、
少し抽象すぎる気がします。
もう少しつめてみます。

### プロンプト
```
では、addFlightData 関数のテストを考えていきます。

テスト条件とテスト期待値の表をTSV形式で表示してください
```
### 回答
```
分析が正常に完了しませんでした

Gemini に問題が発生しました
addFlightData関数のテスト条件とテスト期待値を検討します。
正常系と異常系を考慮し、APIのレスポンスやスプレッドシートへの書き込み結果を検証するための条件を洗い出します。
リクエストを処理できませんでした。プロンプトを書き変えて、もう一度お試しください。
```
### 検証
うーん、難しいのかな。
けどあきらめずにもう一回！

### プロンプト
```
もう一回！
```
### 回答
```
分析が正常に完了しませんでした

Gemini に問題が発生しました
addFlightData 関数のテスト条件とテスト期待値をTSV形式でまとめます。
APIのレスポンス、スプレッドシートへの書き込み、エラー処理を考慮したテストケースを作成します。
リクエストを処理できませんでした。プロンプトを書き変えて、もう一度お試しください。
```
### 検証
やっぱりだめかー。
tsv形式が難しいのかもしれません。
再度、tsvを指定せずにチャレンジ

### プロンプト
```
TSV形式じゃなくてよいので、提示ください
```
### 回答
```
分析が完了しました

addFlightData関数のテスト条件とテスト期待値をまとめます。
APIのレスポンス、スプレッドシートへの書き込み、エラー処理を考慮したテストケースを検討します。
まず、正常に動作するケースを考え、Flightradar24 APIから期待通りのデータが取得できた場合に、スプレッドシートに正しくデータが追加されることを確認します。
次に、異常系のケースとして、APIからデータが取得できない場合、スプレッドシートへの書き込みに失敗した場合などを考え、それぞれのケースで適切なエラー処理が行われることを確認します。
これらのテストケースを網羅することで、関数の品質を保証し、予期せぬエラーを防ぐことができます。

テストケース	テスト条件	テスト期待値
正常系：APIからデータ取得成功、スプレッドシート書き込み成功	Flightradar24 APIから有効なレスポンスが返される	スプレッドシートのlogシートに、APIレスポンスのaircraft配列の各要素が1行ずつ追加される
異常系：APIからデータ取得失敗（ネットワークエラー）	Flightradar24 APIへのリクエストでネットワークエラーが発生する	エラーログが出力され、スプレッドシートへの書き込みは行われない
異常系：APIからデータ取得失敗（APIエラー）	Flightradar24 APIからエラーレスポンスが返される	エラーログが出力され、スプレッドシートへの書き込みは行われない
異常系：スプレッドシート書き込み失敗	スプレッドシートへの書き込み処理でエラーが発生する（シートが存在しない、権限がないなど）	エラーログが出力され、APIから取得したデータは破棄される
異常系：APIレスポンスが不正な形式	Flightradar24 APIからJSON形式ではないデータが返される	エラーログが出力され、スプレッドシートへの書き込みは行われない
異常系：APIレスポンスにaircraftプロパティがない	Flightradar24 APIからaircraftプロパティを含まないJSONデータが返される	エラーログが出力され、スプレッドシートへの書き込みは行われない
```
### 検証
いや、tsvで出せるんかい！
けどパターンとしては出来ていますが、まんま使えないですね。
もっと具体的にお願いしてみましょう。

### プロンプト
```
テスト条件を具体的な値で提示ください
```
### 回答
```
分析が完了しました

addFlightData関数のテスト条件を具体的な値で記述します。

Flightradar24 APIのレスポンスとして、有効なJSONデータを用意し、そのデータをUrlFetchApp.fetch関数の戻り値として使用することで、APIからのデータ取得成功をシミュレートします。
APIエラーのテストケースでは、エラーコードを含むJSONデータを用意します。
スプレッドシート書き込みエラーのテストケースでは、SpreadsheetApp.openById関数やsheet.appendRow関数で例外を発生させるように設定します。
これらの具体的な値を用いることで、各テストケースをより明確に定義し、関数の動作を詳細に検証することができます。

{
"aircraft": [
["7800c1", "B789", "AAR956 ", 134.188, 34.5956, 11875, 462, 272, 0, 7500, "1670157848", "AA956", "KDFW", "RJAA", "N830AN", 1670157848, "A6225B", null],
["780b5b", "B789", "DAL278 ", 134.068, 34.6999, 9450, 447, 266, 0, 6800, "1670157848", "DL278", "KSEA", "RJAA", "N843DZ", 1670157848, "A72254", null]
]
}


* スプレッドシート書き込み:
    * `SpreadsheetApp.openById(sheet_id)` は有効なスプレッドシートオブジェクトを返す
    * `sheet.appendRow` は正常に実行され、各航空機データが1行ずつ追加される

**異常系**

* API からデータ取得失敗 (ネットワークエラー)
    * `UrlFetchApp.fetch` は `java.net.UnknownHostException` 例外をスローする

* API からデータ取得失敗 (API エラー)
    * API レスポンス:
```json
{
  "error": {
    "code": 404,
    "message": "Not Found"
  }
}
スプレッドシート書き込み失敗

SpreadsheetApp.openById(sheet_id) は SpreadsheetApp.SpreadsheetNotFoundException 例外をスローする
sheet.appendRow は Exception をスローする
API レスポンスが不正な形式

API レスポンス: 不正な JSON データ
API レスポンスに aircraft プロパティがない

API レスポンス: {"data": []}
これらの具体的な値を用いることで、addFlightData 関数のテストケースを明確に定義し、関数の動作を詳細に検証することができます。
```
### 検証
具体的なテスト条件(値)まで提示してくれました。
時間なくて試していないですが、ここまでのやりとりで詳細なイメージが出てきました。
そもそも、geminiさんは補完的な利用で考えているので、
この程度で十分ありがたいですね。

# おわり
十分な時間がないときに、こういった提案いただけるのは助かります。
案件次第で利用可否があるかもしれませんが、
利用できる環境であれば、積極的に使い倒して、生産性を上げていきたいですね。