Amazon AlexaAWS

Mocha & Power-assertでalexa-sdkで作ったAlexa Skillのユニットテスト

この記事は一人Alexa Skills Kit for Node.js Advent Calendar 2017の7日目の記事です。 alexa-conversationでAlexa Skillのテストをするという記事は […]

広告ここから
広告ここまで

この記事は一人Alexa Skills Kit for Node.js Advent Calendar 2017の7日目の記事です。

alexa-conversationでAlexa Skillのテストをするという記事は以前に書きましたが、今度はMocha & Power-assertでテストする方法です。

メリット

  • eventの値を細かくシュミレートできる
  • JS定番のやり方でテストできる
  • CardやEcho Showのためのレスポンスなどもテストできる

デメリット

  • eventの値を作るのが面倒
  • callbackにアサーションを書くとハマる

eventの値をシュミレートする

AWS Lambdaのドキュメントにだいたいのイベントのサンプルが公開されていますが、Alexa Skillは例外です。
developer.amazon.comにある「
カスタムスキルのJSONインターフェースのリファレンス」から値をとってきましょう。

「自分のコードで使わないから、event = {}とかでいいかなー」と思っていると、event.sessionがないなどいろいろ怒られることになるので要注意です。

テスト対象コードのサンプル

テスト用にいわゆるHello world的なコードを用意しました。

index.js

'use strict'
const Alexa = require('alexa-sdk')
const handlers = {
  'LaunchRequest': function () {
    this.emit(':tell', 'サンプルスキルへようこそ。')
  }
}

module.exports.handler = (event, context, callback) => {
  alexa = Alexa.handler(event, context, callback)
  alexa.registerHandlers(handlers)
  alexa.execute()
}

テストコード

tests/index.test.js

const assert = require('power-assert')
const MyLambdaFunction = require('../index.js')
const { handler } = MyLambdaFunction
// eventには
// https://developer.amazon.com/docs/custom-skills/request-and-response-json-reference.html
// の値をはりつけておく
const event = {
...
}

describe('LaunchRequest', () => {
  it('Say hallo world', () => {
    event.request.type = 'LaunchRequest'
    const succeed = (data) => {
      const { response } = data
      const {
        outputSpeech
      } = response
      assert.deepEqual(
        outputSpeech,
        {
          type: 'SSML',
          ssml: '<speak> サンプルアプリへようこそ。 </speak>'
        }
      )
    }
    const fail = (e) => {
      if (e.name === 'AssertionError') {
        assert.deepEqual(e.expected, e.actual)
      } else {
        assert.ok(false)
      }
    }
    handler(event, {succeed, fail}, (error, data) => {})
  })
})

テスト結果

1 failing

  1) LaunchRequest
       Say hallo world:

      AssertionError: { type: 'SSML',
  ssml: '<speak> サンプルスキルへようこそ。 </speak>' } deepEqual { type: 'SSML',
  ssml: '<speak> サンプルアプリへようこそ。 </speak>' }
      + expected - actual

       {
      -  "ssml": "<speak> サンプルスキルへようこそ。 </speak>"
      +  "ssml": "<speak> サンプルアプリへようこそ。 </speak>"
         "type": "SSML"
       }

      at Decorator._callFunc (node_modules/empower-core/lib/decorator.js:110:20)
      at Decorator.concreteAssert (node_modules/empower-core/lib/decorator.js:103:17)
      at Function.decoratedAssert [as deepEqual] (node_modules/empower-core/lib/decorate.js:51:30)
      at Object.fail (test/unit/intent/HelpIntent.js:31:16)
      at AlexaRequestEmitter.ValidateRequest (node_modules/alexa-sdk/lib/alexa.js:181:28)
      at AlexaRequestEmitter.HandleLambdaEvent (node_modules/alexa-sdk/lib/alexa.js:121:25)
      at AlexaRequestEmitter.value (node_modules/alexa-sdk/lib/alexa.js:95:31)
      at module.exports.handler (index.js:7:9)
      at exports.executeFunction (test/unit/intent/helpers.js:42:3)
      at Context.it (test/unit/intent/HelpIntent.js:36:5)

Tips1: アサーションはcontext(第二引数)に

alexa-sdkcallbackではなく、context.succeedに成功結果を返します。
AWS Lambdaのドキュメントでは「callbackを使ってね」とありますので、そのノリでテストを書くと「あれ?」ってなります。

Tips2: context.failにもアサーションを書く

また、context.succeedでアサーションがFailするとcontext.failが呼び出されます。

なのでアサーションをcontext.succeedに書きつつ、アサーションが失敗した場合(AssertionError)はcontext.failの方でハンドリングしてやらないと、期待したメッセージが出なかったりテストをパスさせてしまったりします。

その他

今回は発話部分(data.response.outputSpeech)のテストをしていますが、Amazon Echo向けのレスポンスdata.response.directivesやAlexa APP向けの表示data.response.cardのテストなどを書く様にするとかなり便利な気がします。

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts