Execute mocha unit test for your Alexa custom skill in an AWS Lambda
VUI application like a Alexa skill should monitor the application health. So some developer like me want to ru […]
目次
VUI application like a Alexa skill should monitor the application health.
So some developer like me want to run testing code in production.
In AWS, we can run Mocha unittest by using AWS Lambda.
Target function
This is the simple skill code.
$ vim index.js
const Alexa = require('ask-sdk')
const skillBuilder = Alexa.SkillBuilders.standard()
const ExampleHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest'
},
handle(handlerInput) {
return handlerInput.responseBuilder.speak('hello').getResponse()
}
}
module.exports.ExampleHandler = ExampleHandler
module.exports.handler = skillBuilder
.addRequestHandlers(ExampleHandler)
.addRequestHandler(
'TestIntent',
(handlerInput) => {
return handlerInput.responseBuilder.speak('goodby').getResponse()
})
.lambda()
And we will be add test code
Preparation
Create a new project by Serverless Framework
We can easy to create and deploy AWS resources by the Serverless Framework.
$ sls create -t aws-nodejs-ecma-script -p lambda-alexa-monitor
$ cd lambda-alexa-monitor
$ npm i
Install npm libraries
And install lambda-mocha-runner
package.
$ npm i -S lambda-mocha-runner ask-sdk mocha power-assert
The lambda-mocha-runner
runs mocha test in AWS Lambda.
Make test files
Finally, we can make a test file by the specific directory.
$ mkdir tests
$ touch tests/index.js
Write test code
Next, we will create a new test code to the Lambda function.
$ vim tests/index.js
const assert = require('power-assert')
const {
handler
} = require('../index')
// Alexa Skills Kit request object
const event = {
session: {
new: true,
sessionId: 'amzn1.echo-api.session.[unique-value-here]',
attributes: {},
user: {
userId: 'amzn1.ask.account.[unique-value-here]'
},
application: {
applicationId: 'amzn1.ask.skill.[unique-value-here]'
}
},
version: '1.0',
request: {
locale: 'en-US',
timestamp: '2016-10-27T18:21:44Z',
type: 'LaunchRequest',
requestId: 'amzn1.echo-api.request.[unique-value-here]'
},
context: {
AudioPlayer: {
playerActivity: 'IDLE'
},
System: {
apiEndpoint: 'https://api.amazonalexa.com',
apiAccessToken: 'exampleAccessToken',
device: {
supportedInterfaces: {
AudioPlayer: {}
}
},
application: {
applicationId: 'amzn1.ask.skill.[unique-value-here]'
},
user: {
userId: 'amzn1.ask.account.[unique-value-here]'
}
}
}
}
// Promise wrapper to invoke the function
const invokeHandler = async (handler, event) => {
return new Promise((resolve, reject) => {
return handler(event, {}, (err, result) => {
if (err) return reject(err)
return resolve(result)
})
})
}
// execute test
describe('test', () => {
it('test11', async () => {
const r = await invokeHandler(handler, event)
assert.equal(r.response.outputSpeech.ssml, '<speak>hello</speak>')
})
})
Make a test function
Finally, we can make a new Lambda function to execute the test.
Define AWS Resource
Define AWS resources by the Serverless Framework.
$ vim serverless.yml
service:
name: lambda-alexa-monitor
provider:
name: aws
runtime: nodejs6.10
functions:
# Lambda function for the Alexa Skill
target:
handler: index.handler
events:
- alexaSkill
# Lambda function to run the test
testAlexa:
handler: test.handler
events:
- schedule: cron(0/1 * * * ? *)
It will be created a new AWS Lambda and CloudWatch Event.
Write a execution tests
And make a js file to execute test.
$ vim test.js
const Runner = require('lambda-mocha-runner')
// eslint-disable-next-line import/prefer-default-export
class Lambda {
static run(event, c, callback) {
const context = {
mochaOptions: {},
testDir: './tests/'
}
return Runner.run(context)
.then(response => callback(null, response))
.catch(err => callback(err))
}
}
module.exports.handler = (event, context, callback) => {
return Lambda.run(event, context, callback)
}
Run the test
That’s complete! We can run test by the CloudWatch Schedule event or specific request.
// Invoke the function by local
$ sls invoke local -f testAlexa
// Invoke AWS Lambda
$ sls invoke -f testAlexa
And we can see the test result by the following JSON.
// Pass the test
{
"suite": {
"type": "suite",
"isPassing": true,
"numPassing": 2,
"numFailing": 0
},
"tests": [
{
"type": "test",
"durationInMillis": 0,
"testTitle": "test run",
"stackTrace": "",
"isPassing": true
},
{
"type": "test",
"durationInMillis": 4,
"testTitle": "test test11",
"stackTrace": "",
"isPassing": true
}
]
}
// Fail the test
{
"suite": {
"type": "suite",
"isPassing": false,
"numPassing": 0,
"numFailing": 1
},
"tests": [
{
"type": "test",
"durationInMillis": 5,
"testTitle": "test test11",
"stackTrace": "AssertionError [ERR_ASSERTION]: '<speak>hello</speak>' == '<speak>goodbye</speak>'\n at Decorator._callFunc (node_modules/empower-core/lib/decorator.js:110:20)\n at Decorator.concreteAssert (node_modules/empower-core/lib/decorator.js:103:17)\n at Function.decoratedAssert [as equal] (node_modules/empower-core/lib/decorate.js:51:30)\n at Context.it (tests/index.js:63:12)",
"isPassing": false
}
]
}