GASのテスト(Jest)を書く!!!

 

GASを書いていて、テストを書きたくなる時って結構ありませんか?
ただ、なかなか手をつけることができずにテストを書かずにおいてしまい罪悪感が積もりに積もったので、ついにテストを書きました 🎉🍾✨
そのことについてまとめます❕
(TypeScriptはまだまだ勉強中でエセなのでご了承ください🙇)

もくじ

 

準備🎒

npm install -D clasp @types/google-apps-script

$ npm install -D clasp @types/google-apps-script

tsconfig.jsonを追加

$ tsc -init
//tsconfig.json
{
  "compilerOptions": {
    "lib": ["esnext"],
    "experimentalDecorators": true
  }
}

npx clasp create --type standalone --rootDir src

$ npx clasp create --type standalone --rootDir src

// src/appsscript.json と .clasp.json が生成される

// src/appsscript.json
{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

// .clasp.json
{"scriptId":"xxx","rootDir":"src"}

テストコードはclasp pushする必要がないためsrc/以下にappsscript.jsonを生成しました。

//構成
.
├── README.md
├── node_modules/
│
├── src    ←clasp pushの対象ルートディレクトリ 
│   ├── _utils.ts
│   ├── appsscript.json
│   └── code.ts
│
├── tests ←テストコードのディレクトリ(clasp pushしない)
│   ├── _utils.test.ts
│   ├── date-mock.ts
│   └── gmail-message-mock.ts
│
├── jest.config.js
├── package.json
├── tsconfig.json
└── .clasp.json

npm install -D jest "@types/jest" ts-jest typescript

$ npm install -D jest "@types/jest" ts-jest typescript

jest.config.jsを追加

$ jest --init

参考: https://typescript-jp.gitbook.io/deep-dive/intro-1/jest#suteppu2jestwosuru

//jest.config.js
module.exports = {
  "roots": [
    "<rootDir>"
  ],
  "testMatch": [
    "**/__tests__/**/*.+(ts|tsx|js)",
    "**/?(*.)+(spec|test).+(ts|tsx|js)"
  ],
  "transform": {
    "^.+\\.(ts|tsx)$": "ts-jest"
  },
}

tsconfig.jsonにesModuleInterop=trueを追加

以下のwarningがでたため、言われるがままに”esModuleInterop”: trueを追加しました。

ts-jest[config] (WARN) message TS151001: If you have issues related to imports, you should consider setting `esModuleInterop` to `true` in your TypeScript configuration file (usually `tsconfig.json`)
//tsconfig.json
{
  "compilerOptions": {
    "lib": ["esnext"],
    "experimentalDecorators": true,
+   "esModuleInterop": true,  //追加
  }
}

src/appsscript.jsonのtimeZoneを”Asia/Tokyo”に修正

//src/appsscript.json
{
- "timeZone": "America/New_York",
+ "timeZone": "Asia/Tokyo",
  ...
}

npm testでテスト実行できるようにする

//package.json
{
  ....
+ "scripts": {
+   "test": "jest"
+ }
}

テストを書く📊

GmailMessageのモックを作る

テストできるように、インターフェースGmailMessageを実装してモック(GmailMessageMock)を作成しました。

tests/gmail-message-mock.ts

import GmailMessage = GoogleAppsScript.Gmail.GmailMessage;

export class GmailMessageMock implements GmailMessage {
    constructor(
        private body: string,
    ) {
    }

    getBody(): string {
        return this.body;
    }
    ...
}

tests/_utils.test.ts

import { Utils } from "../src/_utils";
import { GmailMessageMock } from "./gmail-message-mock";

describe('Utils.createBodyMessage', () => {
    test('[body]xxxを生成できること', () => {
        const inputGmailMessage = new GmailMessageMock('テストメッセージです');

        const util = new Utils();
        const actual = util.createBodyMessage(inputGmailMessage);
        expect(actual).toBe('[body]テストメッセージです');
    })
})

src/_utils.ts

export class Utils {
    public createBodyMessage(gmailMessage: GoogleAppsScript.Gmail.GmailMessage): string {
        return "[body]" + gmailMessage.getBody();
    }
}

ついに、テストできるようになりましたー🎉🎉🎉

$ npm test

> test
> jest

 PASS  tests/_utils.test.ts
  Utils.createBodyMessage
    ✓ [body]xxxxを生成できること (2 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.657 s
Ran all test suites.

メモ📝

– GASではimportができないので、読み込み順序をいい感じにするために先に読み込まれる必要があるファイルについては_hoge.tsのようにアンダーバーから始まるファイル名にしました🚨
– clasp pushされるとcode.ts→code.gsに変換されます。

参考にした記事🙇

https://developers.google.com/apps-script/guides/clasp
– https://kotamat.com/post/gas-testing/

最後に

詳細が気になる方は、https://github.com/kin29/line-notify-from-gmailにコミット履歴があるので参考にしてみてください。

(最初yarn使ってたのですが、npmだけでいけそうなので最後にyarn.lockを消したりしてます)

 

投稿者:

kin29man

農学部卒の7年目エンジニアです👩‍💻 PHPとGASが好きです!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です