AlexaのCustom SkillのUtteranceに対するResponseのユニットテストを書いてみた

Alexa Skills Kit

はじめに

AlexaのCustom SkillはLambdaで開発しますが、その動きは基本的には

  • Utteranceに対応するRequestをAlexa Skills Kit(ASK)から受け取る
  • 何らかの処理を行い、Responseを返す

となります。

そこで、このRequestに対するResponseをテストするユニットテストを書いてみました。

ユニットテストの仕組み

Utteranceに対応するRequestはjson形式で、前回紹介したService Simulatorにて確認することができます。またLambdaからのResponseもjson形式で、Utteranceに対応してAlexaが返す文言が含まれています。

以下のスクリーンショットを確認してください。 alexa_unittest_1

そこで、Lambdaを呼び出す際にRequestのjsonを渡し、戻り値のjsonにAlexaが返すべき文言が含まれているかをチェックするロジックをユニットテストとして実装しました。

実装について

LambdaをJavaScriptで実装したので、ユニットテストにはmochaを使用しました。

テスト対象のシナリオ

以下のようにAlexaに名前を教えると、Alexaがそれを返却するという単純なシナリオについてユニットテストを書いてみます。

  • ユーザ : my name is John
  • Alexa : Hello John!

test.js

ではテストのコードです。以下のようになります。

const helper = require("./helper.js");
const assert = require("assert");

describe("my name is", function(){  
  it("say my name", function(){
    return helper.invokeAlexa(
      "sample-lambda", 
      "functions/sample-lambda/test/myNameIs.json"
    ).then(function(result){
      assert.equal("Hello John!", result);
    });
  });
});

helperのinvokeAlexaメソッドにLambdaのFunction名とRequestのjsonパスを渡しています。helperについては後述します。jsonは先に紹介したService Simulatorにて用意し、「Lambda Request」欄に表示されるjsonをそのまま使用します。そしてassert.equalでAlexaが返すべき文言をチェックしています。

helper.js

ユニットテストの共通処理についてはhelperに纏めました。以下がそのソースとなります。

const PROFILE = "YOUR_PROFILE";
const REGION = "us-east-1";

const fs = require("fs");
var aws = require("aws-sdk");
const credentials = new aws.SharedIniFileCredentials({profile: PROFILE});
aws.config.credentials = credentials;
aws.config.region = REGION;
const lambda = new aws.Lambda();

var lambdaFunctionName = "";

exports.invokeAlexa = function(functionName, jsonPath) {
  lambdaFunctionName = functionName;
  return readJson(jsonPath)
    .then(execLambda)
    .then(getResponseSpeech);
};

function readJson(jsonPath){  
  return new Promise(function(resolve) {
    fs.readFile(jsonPath, "utf-8", function (err, data) {
      resolve(data);
    });
  });
}

function execLambda(json){
  return new Promise(function(resolve) {
    const params = {
      FunctionName : lambdaFunctionName,
      Payload  : json
    };
    lambda.invoke(params, function(err, data) {
      resolve(data);
    });
  });
}

function getResponseSpeech(response){
  const json = JSON.parse(response.Payload);
  return json["response"]["outputSpeech"]["ssml"]
    .replace("<speak> ", "")
    .replace(" </speak>", "");
}

一番上のinvokeAlexa()が、先のtest.jsから呼び出した処理です。その中で

  • Requestのjsonを読み込むreadJson()
  • Lambdaを呼び出すexecLambda()
  • Lambdaの戻り値のjsonから文言を取得するgetResponseSpeech()


を実行しています。

Lambdaの戻り値については以下のようなjsonとなるので

{
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "type": "SSML",
      "ssml": "<speak> Hello John! </speak>"
    },
(以下略)

getResponseSpeech()にて「speak」タグで囲まれた文言のみを取得しています。

まとめ

以上のようなソースで、Custom Skillのユニットテストを実装することができました。今回はLambdaをJavaScriptで実装したためmochaを使用しましたが、その他の言語の場合にもRequestとResponseをチェックするという仕組みは使えると思います。

Custom Skillを開発する際の参考になれば幸いです。

AWS Cloud Roadshow 2017 福岡