Google Apps Script(以下,GAS)でライブラリを公開しました。ライブラリを開発する際、 テストのフィードバックサイクルを短くする ため、Clasp + Typescript + Jest という技術スタックを選択しました。
その開発体験について共有しようと思います。特段変わったことはしていません。
script.google.comにアクセスしてデバッグ実行って、しんどくないですか?

とても ストレスフル です。単純な GAS なら別に良いんですが、少し複雑な GAS を作ろうと思うと、問題に感じます。
GAS をローカル環境で動かすことができる Clasp というコマンドラインツールが Google より公開されています。
また、Clasp は Typescript をサポートしているため、型を中心としたコーディングが可能となりました。
npmjs.comTypescript を選択すると、Interface 設計が容易になります。もちろん、.gs ファイルでも同様の事は実現できると思います。
次に、Jest と呼ばれるテストツールを組み合わせることで、ローカル環境でテストが可能になります。
jestjs.ioただ、単純にテストコードが書けません。 例えば、カレンダーイベントを取得するテストをコーディングするとき、次のようなスクリプトを書いたとします。
const calendar: Calendar = CalendarApp.getCalendarById(
"<your google calendar id>"
);
calendar
.getEvents(new Date("2020-01-01"), new Date("2020-01-02"))
.forEach((calendarEvent: CalendarEvent) => {
console.log(calendarEvent.getTitle());
});こう書いてしまうと、本当のカレンダーイベントを取りに行ってしまいます。テストであれば、そういった処理は避けたいところです。
そこで、CalendarApp を偽物のオブジェクト、つまり Mock オブジェクトに差し替えるため、依存性逆転の原則(dependency inversion principle)を適用します。
interface ICalendarApp {
calendars?: Array<ICalendar>;
getCalendarById(id: string): ICalendar;
}
interface ICalendar {
calendarEvents?: Array<ICalendarEvent>;
getEvents(startTime: Date, endTime: Date): Array<ICalendarEvent>;
}
interface ICalendarEvent {
title?: string;
getTitle(): string;
}
class CalendarAppMock implements ICalendarApp {
calendars?: Array<ICalendar>;
getCalendarById(id: string): ICalendar {
return this.calendars![0].calendar;
}
}
class CalendarAppImpl implements ICalendarApp {
getCalendarById(id: string): ICalendar {
const calendar: ICalendar = CalendarApp.getCalendarById(id);
return calendar;
}
}このようなインターフェース・クラスを準備し、先程のコードを次のようにします。
const calendar: ICalendar = new CalendarAppMock().getCalendarById();
calendar
.getEvents(new Date("2020-01-01"), new Date("2020-01-02"))
.forEach((calendarEvent: ICalendarEvent) => {
console.log(calendarEvent.getTitle());
});結果、CalendarApp の代わりに Mock オブジェクトを差し込めるようになりました。ローカルテストが可能となります。
もちろん、プロダクトコードでは、CalendarAppMock ではなく、 CalendarAppImpl を使用すれば良いです。
Mock で差し替えるオブジェクトが増えると、InversifyJS のような DI コンテナを検討してみると良いかもしれません。
こうすることで、Jest によるテストが動作するようになります。
実際に、開発・公開したライブラリでも十分にテストをすることができました。
CaAT $ npm run test -- --coverage
> jest "--coverage"
PASS __tests__/utils/dateUtils.test.ts
PASS __tests__/group/groupImpl.test.ts
PASS __tests__/member/memberImpl.test.ts
---------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------------|---------|----------|---------|---------|-------------------
All files | 98.43 | 97.62 | 96.67 | 98.37 |
__tests__ | 100 | 100 | 100 | 100 |
generator.ts | 100 | 100 | 100 | 100 |
src/calendar | 93.1 | 100 | 92.31 | 92.59 |
calendarAppImpl.ts | 60 | 100 | 50 | 60 | 6,7
calendarAppMock.ts | 100 | 100 | 100 | 100 |
src/group | 100 | 100 | 100 | 100 |
groupImpl.ts | 100 | 100 | 100 | 100 |
src/member | 100 | 94.74 | 100 | 100 |
memberImpl.ts | 100 | 94.74 | 100 | 100 | 38
src/utils | 100 | 100 | 100 | 100 |
dateUtils.ts | 100 | 100 | 100 | 100 |
---------------------|---------|----------|---------|---------|-------------------
Test Suites: 3 passed, 3 total
Tests: 23 passed, 23 total
Snapshots: 0 total
Time: 2.826s, estimated 6s
Ran all test suites.ライブラリとして提供する機能のテストが、たったの 約 3 秒 で終わります。 ストレスフリー にローカル開発が可能となりました。
詳しくは、実際に作ったライブラリのソースコード(__tests__)を御覧ください。
GAS は、とても便利です。生産性が向上します。 サクッと API を構築できますし、G Suite との連携も(当たり前ですが)簡単です。
ただ、メンテナンス性が低いコードになると、 陳腐化され誰も面倒が見れなくなります 。 常にクリーンであり続けるためには、テストコードは 必須 です。 GAS を運用する方々には、是非ともテストコードを検討下さい。
アジャイル開発で、かつ、Google Calendar で予定管理しているチームには是非とも使って頂きたいライブラリです。
CaAT is the Google Apps Script Library that Calculate the Assigned Time in Google Calendar.
このツールでできることは、次のとおりです。
実際にサンプルコードがあるので、ご参考下さい。
-
0
読み込み中...
タグ「Google」の記事
どうも、Web業界で働き始めて9年目の駆け出しエンジニア、silverbirderです。Spotifyで音楽を聴いていると「この曲、どこかで聞いたことがあるけど、何の主題歌だったかな?」と思うこと、ありませんか?特にドライブ中や作業中に、ふと気になることが多いですよね。 私もそんな経験があり、気になったその曲が主題歌だったアニメを見始めたことがきっかけで、「簡単にタイアップ情報(アニメやドラマなど)を調べられるアプリがあったら便利だな」と思い、このアプリを作ることにしました。
ERNIE-ViLG というのが、"二次元キャラ" に強いという記事を目にしました。実際に使ってみようと、次のページで試したんですが、レスポンスがイマイチでした。そこで、次の記事を参考にして、ERNIE-ViLG を Google Colaboratory で動かすようにしました。
みなさん、ご自身のプロフィール画像ってどう管理していますか?例えば、zennのプロフィール画像って、更新していますか? 私は、プロフィール画像の更新は面倒なので、放置することが多いです。(GravatarみたいなSaaSが使えたら良いのに...)
タグ「テスト」の記事
以下の記事で書いた CSSをテストする方法について、試してみました。 https://zenn.dev/silverbirder/articles/df6752b230f04c ソースコードは、以下に置いています。 https://gith
Web のフロントエンド実装において、次のようなミスによってデザイン崩れを起こしてしまったことはありませんか。 flex-shrink の指定を忘れて、要素が押しつぶされてしまった z-index の指定を間違えて、要素が意図せず前面(また
AIの進化によって、プロダクションコードに対するテストコードは、以前と比べて格段に書きやすくなったと感じています。 単体テストに関する基本的なお作法については、以前に以下の記事で整理しました。 興味があれば、参考として読んでもらえると嬉しい
2026年01月09日
タグ「フロントエンド」の記事
AI にコードを書かせた後、余計なコードを見つけて消す作業があります。 不毛なことなので、それらの作業を減らすためのお作法を紹介します。 未使用コードを消す 以下でも書きましたが、未使用コードの検査に knip を使うことが多いです。 ht
最近、iframeを使っています。 クライアントサイドで埋め込む想定で、iframeを使おうとしています。 色々と苦労したことがあったので、書いて残しておこうと思います。 レスポンスヘッダー 前提として、ウェブアプリケーションをプロダクショ
紙を積んだイラストをSVGで書こうとしていました。 (当たり前ですが)図形を表現するためには数学の知識が必要で、学生の頃の記憶を思い出したので疲れました。 所感について、諸々書こうと思います。 成果物 実際に完成したのは、以下の画像ができま
2026年02月17日