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のテストなどを書く様にするとかなり便利な気がします。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark