本記事は、サムザップ Advent Calendar 2021 の12/4の記事です。
#はじめに
はじめまして、サムザップの北島です。
突然ですが、Google Apps Script(以降、GAS)で色々している皆さん!
GASは便利ですが、ブラウザのエディター上で開発するのはちょっと大変ですよね。
そこで、今回は Docker + Clasp で開発環境を作りつつ、さらに Jest + GitHub Actions でテストもしてしまえ!という内容です。
というわけで、Docker、Clasp、Jest、GitHub Actionsと、4つについてそれぞれ書いていきます。
が、詳しく書いていくとかなり長くなってしまうため、今回はポイントを絞って簡潔にという感じにしております、ご了承ください。
#開発環境
まず、今回作る開発環境の構成は以下になります。
| - gas
| | - .github
| | | - workflows
| | | | - ci.yml
| | - .docker
| | | - Dockerfile
| | | - docker-compose.yml
| | - src
| | | - package.json
| | | - babel.config.js
| | | - node_modules
| | | - hoge
| | | | - .clasp.json
| | | | - .claspignore.json
| | | | - appsscript.json
| | | | - hoge.ts
| | | | - __test__
| | | | | - hoge.test.ts
#Docker
では、Docker環境の構築についてです。
Dockerをインストールした状態で、以下のファイルを用意してください。
なお、後に出てくる Clasp、Jest の設定もここでしてしまいます。
.docker/Dockerfile
FROM node:16.4.1
RUN npm i @google/clasp -g
.docker/docker-compose.yml
version: '3'
services:
gas:
build: .
tty: true
container_name: 'gas-container'
volumes:
- ../src/:/opt/
working_dir: /opt
src/package.json
{
"dependencies": {
"@google/clasp": "^2.4.1",
"google-spreadsheet": "^3.1.15",
"npm": "^7.20.6"
},
"devDependencies": {
"@babel/cli": "^7.14.8",
"@babel/core": "^7.15.0",
"@babel/plugin-transform-modules-commonjs": "^7.15.0",
"@babel/preset-env": "^7.15.0",
"jest": "^27.0.6",
"jest-junit": "^12.2.0"
},
"jest": {
"globals": {
"SpreadsheetApp": {}
}
}
}
src/babel.config.js
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
}
]
],
plugins: [
'@babel/plugin-transform-modules-commonjs',
]
}
用意ができたら、以下のコマンドで環境を立ち上げることができます。
初回のみ
$ cd .docker
$ docker-compose build --no-cache
$ docker-compose up -d
$ docker-compose ps
※以下があることを確認
Name Command State Ports
-----------------------------------------------------
gas-container docker-entrypoint.sh node Up
(停止するときは以下)
$ docker-compose down
初回以降
$ cd .docker
$ docker-compose up -d
(停止するときは以下)
$ docker-compose down
#Clasp
続いて、Claspについてです。
Claspは、Google が提供するGASをローカルで管理できるようになるツールになります。
素直にGASの開発を行うと、ブラウザ上のエディターにコードを書くことになりますが、Claspを使うとローカルで書いたものを clasp push
で簡単に反映できるようになります。
上記のDocker環境を立ち上げた状態で以下を実行します。
$ docker-compose exec gas bash
$ npx clasp login --no-localhost
※URLが表示されるのでブラウザでアクセスしGoogleアカウントでログイン
※codeが表示されるのでコピペ
これにより .docker/.clasprc.json
が作成され、以降はGoogleへのログインが不要になります。
次に .clasp.json
を用意します。
src/hoge/.clasp.json
{
"scriptId":"【管理したいGASのID】"
}
Claspで管理したいGASは予め作成しておいてください。
これで以下のコマンドが実行可能になります。
$ npx clasp pull
GASに反映されているコードをローカルに持ってきます
$ npx clasp open
GASをブラウザで開きます
$ npx clasp push
ローカルのコードをGASに反映します
ローカルでの開発が可能になりましたね!
#Jest
続いて、Jestです。
Jestのインストールは以下でできます。
$ docker-compose exec ikusa-gas bash
$ npm install --save-dev jest
Jestを使うことで、GASのテストコードを書くことができます。
コードは __test__
配下に置くか、ファイル名を hoge.test.ts
とします。
テストするコードのサンプル(src/hoge/hoge.ts)
/*
* 足し算
*/
function plus(a, b) {
return add(a, b);
}
/*
* スプレットシートの範囲を指定して取得、配列で返す
*/
function getSheetAsArray(ssUrl, ssName, startRow, endRow, startColumn, endColumn) {
var sheet = SpreadsheetApp.openByUrl(ssUrl+"\/").getSheetByName(ssName);
var result = sheet.getRange(startRow, startColumn, endRow-startRow+1, endColumn-startColumns+1).getValues();
return result;
}
テストコードのサンプル(src/hoge/__test__/hoge.test.ts)
import {plus, getSheetAsArray} from '../hoge.ts';
// モックの例
SpreadsheetApp.openByUrl = jest.fn(() => ({
getSheetByName: jest.fn(() => (
{
getRange: jest.fn(() => (
{
getValues: jest.fn(() => [
["HEAD1", "HEAD2", "HEAD3"],
["A1", "B1", "C1"],
["A2", "B2", "C2"],
]),
}
)),
}
)),
}));
// テストの例
describe('テスト', () => {
it('plus', () => {
var result = plus(2, 3);
expect(result).toEqual(5);
});
it('# getSheetAsArray', () => {
var output = getSheetAsArray();
expect(output[0][0]).toBe("HEAD1");
expect(output[0][1]).toBe("HEAD2");
expect(output[0][2]).toBe("HEAD3");
expect(output[1][0]).toBe("A1");
expect(output[1][1]).toBe("B1");
expect(output[1][2]).toBe("C1");
expect(output[2][0]).toBe("A2");
expect(output[2][1]).toBe("B2");
expect(output[2][2]).toBe("C2");
});
});
こんな感じで簡単にテストが書けます。
GAS開発の場合、スプレットシートを使うことが多いと思います。
スプレットシートを操作するような関数は、上記のようにモック化すると良いと思います。
テストを実行する方法は以下のとおりです。
すべてのテストを実行する場合
$ docker-compose exec gas npx jest
管理するGASが複数になり、特定のテストだけを実行する場合
例)src/hoge2 配下のテストを実行する場合
$ docker-compose exec gas npx jest --verbose hoge2
なお、テストコードはGASに上げる必要はないので .claspignore
を設定すると良いです。
src/hoge/.claspignore
__test__/*
#GitHub Actions
最後に、GitHub Actionsについてです。
上記ではテストを手動で実行しましたが、GitHub Actionsを使うことで自動で実行することができます。
(GASのコードをGitHubでバージョン管理している前提です。)
masterブランチへのプルリクが作成されたタイミングでテストを実行したい場合を例として載せておきます。
.github/workflows/ci.yml
name: CI
on:
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: git clone
uses: actions/checkout@v1
- name: Instal node
uses: actions/setup-node@v1
with:
node-version: '16.4.1'
- name: Install npm
run: npm install -g npm@7.18.1
- name: Install jest
run: npm install --save-dev jest
working-directory: ./src
- name: Install babel
run: npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/plugin-transform-modules-commonjs
working-directory: ./src
- name: Run test
run: npx jest
working-directory: ./src
#まとめ
というわけで、今回は Docker + Clasp + Jest + GitHub Actions でGAS開発をモリモリにする方法を紹介しました。
日頃、GASで開発をしている皆さんの参考になれば嬉しいです。
以上、サムザップ Advent Calendar 2021 の12/4の記事でした。
明日は @fuzy さんの記事です、お楽しみに!