How to perform Google Add-on automated unit testing and publishing with Circle CI — Part 2

Jerome Marhic
effilab
Published in
5 min readJun 18, 2018

In this second part, we will setup an automated test system for our new google spreadsheet add-on. If you haven’t yet, you can read part 1 here.

Suppose we accidentally made a typo in the sayHello function :

Now our application is broken ! We need a way to catch those errors before we deploy them. Thankfully a library named Gast was specially created to test Google App scripts : https://github.com/zixia/gast . Its aim is to provide “an easy way to verify whether GAS programs you write is behaving as expected or not”, by implementing unit testing cases.

Create a new test.js file, with the following code (don't forget to replace the URL) :

What we are doing here is calling the sayHello function, and verifying that we indeed wrote “Hello” in the A1 cell.

In the script editor, you can execute the gastTestRunner function (Menu Run -> Run Function -> gastTestRunner) and view the resulting logs (Menu View -> Logs).

We can clearly see that the test failed.

Now we need a way to call this function and get the results from our CI. Luckily App Scripts includes an API to run script functions : https://developers.google.com/apps-script/api/reference/rest/v1/scripts/run

The API only works for API executables, so let’s first deploy our add-on as an API executable : Menu Publish, Deploy as API Executable.

and open the Google Cloud Platform (GCP) project associated to your script (Menu Resources, Cloud Platform project)

On the GCP page of your project, look for Apps Script API with the search bar and enable it.

Create new OAuth credentials (select “other” for the client type) and download the client secrets json file (we will rename it to client_secret.json).

Because our add-on needs some authorizations (to access an user spreadsheet) we need to list them in the manifest file appsscript.json. You can view the necessary authorization scope in Menu File, Project Properties, Scopes.

Edit the appsscript.json file like so:

Notice we added the necessary authorization under the oauthScopes key. From experience, the API calls won’t work unless these are present.

We should be all set to call the gastTestRunner function via the API !

A note about credentials :

The client uses oauth token to communicate with the google APIs. A token is only valid for a certain duration (typically one hour) but the googleapi client includes a refresh mechanism so we don’t need to worry about it yet. You can read more about Google OAuth here : https://developers.google.com/identity/protocols/OAuth2

See https://developers.google.com/apps-script/api/concepts/ for more information about the Apps Script API, with examples in various languages. We will use NodeJS from now on. Install the googleapis library for nodejs : https://github.com/google/google-api-nodejs-client .

Our repo auth.js file (https://github.com/Effilab/HelloAddon/blob/master/auth.js) exports the authenticate function. Call it once with the client_secret.json file at the root, it will request a token with the desired scopes and write it in a credentials.json file. Meanwhile, clasp stores the token in your home .clasprc.json file.

Note that a token is only valid for a given application and scopes, we cannot reuse the clasp token to call our script test function, for instance.

The script test.js calls the gastTestRunner function :

The function is called successfully (you can view the execution history in Menu View, Executions)

However since we don’t return anything it is not useful yet. Let’s modify the testGastRunner` function so that it returns a log of the test execution, and the number of failed tests :

We can now modify our test script to parse the result of the execution. We exit with the failure count so that the CI will fail if there is any test failure (a value greater than 0 indicate failure) :

Now all that’s left to do is to setup our CI to execute the test.js script automatically : what we need is to checkout the code, push it on google drive using clasp, and call the test function. Here is an example using Circleci :

You need to setup the following environment variables in your ci:

From your client_secret.json :

TEST_CLIENT_ID

TEST_PROJECT_ID

TEST_CLIENT_SECRET

From the generated credentials.json :

TEST_CLIENT_ACCESS_TOKEN

TEST_CLIENT_REFRESH_TOKEN

TEST_CLIENT_EXPIRY_DATE

This is your script id (you can find it in the url) :

TEST_SCRIPT_ID

From ~/.clasprc.json (after your logged-in) :

CLASPRC_ACCESS_TOKEN

CLASPRC_REFRESH_TOKEN

CLASPRC_EXPIRY_DATE

You should see the test failing in circle ci :

let’s fix the sayHello function and push again

Our CI tests are now green ! To complete our CI, let’s head over to part 3 and automatize the publishing of the add-on.

--

--