3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

clasp の Hello Apps Script のテストコードを書く

Last updated at Posted at 2023-08-12

はじめに

弊社では、Googleスプレッドシートに Google Apps Script を組み合わせて使うことがあります。

最近になって、自分も Google Apps Script を使う機会ができたので、使い方を覚えることにします。

以下のことができるようにします。

  • clasp を使用する。
  • TypeScript を使用する。
  • テストコードを Jest で書く。

手順

初期プロジェクトの作成

clasp をインストールする

npm init -y

npm install @google/clasp

Google Apps Script API を有効にすることも忘れずに。

Googleスプレッドシートと Apps Script を作成する

npx clasp create \
--type sheets \
--title sample20230812-01 \
--rootDir .

--title で指定した名前の Googleスプレッドシートが、マイドライブに作成されます。

.claspignore を作成する

echo "node_modules/**
coverage/**
jest.config.ts
**/*.test.ts
" > .claspignore

.claspignore ファイルを作成する場合、node_modules/** を含めておかないと、clasp push がえんえんと実行中になり終わらない...

eslint をインストールする

npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint typescript

echo "/* eslint-env node */
module.exports = {
  extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
  parser: '@typescript-eslint/parser',
  plugins: ['@typescript-eslint'],
  root: true,
};" > .eslintrc.cjs

Goolge Apps Script の TypeScript 用の設定を追加する

npm i -S @types/google-apps-script

echo '{
  "compilerOptions": {
    "lib": ["esnext"],
    "experimentalDecorators": true
  }
}' > tsconfig.json

Jest をインストールする

npm install --save-dev jest
npm install --save-dev ts-jest
npm install --save-dev @jest/globals
npm install --save-dev @types/jest
npm install --save-dev ts-node

npx jest --init

The following questions will help Jest to create a suitable configuration for your project

✔ Would you like to use Jest when running "test" script in "package.json"? … yes
✔ Would you like to use Typescript for the configuration file? … yes
✔ Choose the test environment that will be used for testing › node
✔ Do you want Jest to add coverage reports? … yes
✔ Which provider should be used to instrument code for coverage? › v8
✔ Automatically clear mock calls, instances, contexts and results before every test? … yes

✏  Modified /(プロジェクトのパス)/package.json

📝  Configuration file created at /(プロジェクトのパス)/jest.config.ts

「TypeScript Deep Dive」のサイトに記載のある設定を追加します。

なお、設定ファイルが jest.config.js という名前で作成されますが、ファイル内に記述されている import type {Config} from 'jest'; という書き方が TypeScript 用の書き方に見えるので、ファイル名を jest.config.ts に変えてみます。

mv jest.config.ts jest.config.ts.org

cat jest.config.ts.org | sed -e 's/^};$/  roots: [\n    "<rootDir>"\n  ],\n  testMatch: [\n    "**\/__tests__\/**\/*.+(ts|tsx|js)",\n    "**\/?(*.)+(spec|test).+(ts|tsx|js)"\n  ],\n  transform: {\n    "^.+\\\\.(ts|tsx)$": "ts-jest"\n  },\n};/' > jest.config.ts

# rm jest.config.ts.org

js.config.ts に追加される内容は以下。

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

ソースコードとテストコードを作成する

ソースコード

たとえば clasp の GitHub で紹介されているデモ用のソースコードの場合。

Google Apps Script で定義されている Logger.log() が使用されており、テストを実行するために少々工夫します。

src/hello.ts
function hello(): void {
  Logger.log("Hello, Apps Script!");
}

module.exports = hello;

確認用に、関数の戻り値の型を書いてみました。

TypeScript 構文が読み取られる設定が正しく行われていなければ、:void の部分で構文エラーになります。そうなったら、何かを間違えているはず。エラーがなくなるように頑張るしかない (-_-;

また、テストコードから関数を参照できるようにするために、module.exports を追加しました。

テストコード

tests/hello.test.ts
import { describe, expect, test } from '@jest/globals';

const hello = require('../src/hello');

// Logger をモックするためのクラスを定義する
class LoggerMock implements GoogleAppsScript.Base.Logger {
  private lastLog: string;
  clear (): void { this.lastLog = undefined; }
  getLog (): string { return this.lastLog; }
  log (data: string): LoggerMock { this.lastLog = data; return this; }
}

describe('テストです', ()=> {
  beforeEach(() => {
    // Logger にインスタンスをセットする
    global.Logger = new LoggerMock();
  });
  
  test('ログ出力に成功すること', () => {
    hello();
    expect(global.Logger.getLog()).toBe('Hello, Apps Script!');
  });
});

Google Apps Script で Logger という変数が定義されていますが、テストの実行時は値が undefined になっているので、代わりのオブジェクトを代入します。

global 名前空間の変数の値を書き換えるとは、なんてことをしてくれるんだ、というアンチパターンなのかもしれませんが、そもそも値が undefined なのだから、まぁいいか...

テストを実行する

npm run test

 PASS  tests/hello.test.ts
  テストです    ✓ ログ出力に成功すること (2 ms)

リモートにプッシュして実行する

npx clasp login
npx clasp push

プッシュに成功したら、Google Apps Script のエディタ画面で実行してみて、スクリプトの実行が成功するかを確認します。

20230812-01_AppsScriptLog.png

おわりに

Google Apps Script を TypeScript で書きつつ、テストコードの実行ができました。

参考

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?