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.
このツールでできることは、次のとおりです。
実際にサンプルコードがあるので、ご参考下さい。
-
タグ「Google」の記事
どうも、Web業界で働き始めて9年目の駆け出しエンジニア、silverbirderです。Spotifyで音楽を聴いていると「この曲、どこかで聞いたことがあるけど、何の主題歌だったかな?」と思うこと、ありませんか?特にドライブ中や作業中に、ふと気になることが多いですよね。 私もそんな経験があり、気になったその曲が主題歌だったアニメを見始めたことがきっかけで、「簡単にタイアップ情報(アニメやドラマなど)を調べられるアプリがあったら便利だな」と思い、このアプリを作ることにしました。
ERNIE-ViLG というのが、"二次元キャラ" に強いという記事を目にしました。実際に使ってみようと、次のページで試したんですが、レスポンスがイマイチでした。そこで、次の記事を参考にして、ERNIE-ViLG を Google Colaboratory で動かすようにしました。
みなさん、ご自身のプロフィール画像ってどう管理していますか?例えば、zennのプロフィール画像って、更新していますか? 私は、プロフィール画像の更新は面倒なので、放置することが多いです。(GravatarみたいなSaaSが使えたら良いのに...)
タグ「テスト」の記事
Web のフロントエンド実装において、次のようなミスによってデザイン崩れを起こしてしまったことはありませんか。 flex-shrink の指定を忘れて、要素が押しつぶされてしまった z-index の指定を間違えて、要素が意図せず前面(また
AIの進化によって、プロダクションコードに対するテストコードは、以前と比べて格段に書きやすくなったと感じています。 単体テストに関する基本的なお作法については、以前に以下の記事で整理しました。 興味があれば、参考として読んでもらえると嬉しい
2026-01-09
はじめに Playwright で E2E テストを書く際、playwright codegen や、近年では Playwright MCP を利用して、テストコードの雛形を作成することが多いと思います。 ただし、生成したテストコードが正し
2025-12-26
タグ「フロントエンド」の記事
最近、ヒューマンインターフェース ガイドライン(HIG)という言葉を知りました。 「ヒューマンインターフェイスガイドライン」には、どのAppleプラットフォームでも優れた体験を設計できるようにするためのガイドとベストプラクティスが含まれてい
2026-01-24
主にWeb関連の個人開発をしている際に心がけていることを書きます。 月末に近づくにつれ、AIの利用上限に達してしまうことがあります。 その状況になった時、以下のいずれかの選択肢が私の中では残っています。 課金して利用上限を増やす 無料モデル
個人サイトをリニューアルをしています。 ノート風のデザインを目指して、スタイルを調整していました。 ノートの見た目は、現実にあるノートを再現しようとCSSを書いていました。 現在、以下の画像のようなノートになっています。 ノート風デザインの
2026-01-20