はじめに
先月の4/18にAlexa Skills Kit SDK v2 for Node.jsが提供されました。
今まで機能テストではalexa-conversation
というテストフレームワークにお世話になっていたのですが、
v2には対応していない為、マイグレーションを考えていく上では対応を期待したいところでした。
が、半年以上更新が止まったままなので今後も動きは無いかもしれません。。。
テストフレームワークが無くても実機でテストを行えば良い話なのですが、
以前の投稿で書いたようにローカルで気軽にテストがしたいんです!
というわけで以下のような理由(一番の理由は3つめ)で自分で作ってみました!
もちろん実装はTypeScriptです!
- ローカルで気軽にテストがしたい
- マイグレーションには早めに着手したい
- とりあえずOSS開発してみたい
目次
- テストフレームワークの作成
- 公開の準備
- npm設定
- npmへのユーザ登録
- package.json設定
- .npmignore作成
- 公開
- まとめ
テストフレームワークの作成
アサーションについて
alexa-conversation
のアサーションには、以下のものがありました。
- shouldEqual
- shouldNotEqual
- shouldContain
- shouldMatch
- shouldNotMatch
- shouldApproximate
作成したフレームワークでは、以下の機能を提供することにしました。
種類は増えてしまいましたが、視覚的に何を評価しているのかがコードから判別しやすいといいなという思いです。
関数名 | 概要 |
---|---|
equalPlain(expected: IOutputSpeech) | プレーンテキストが完全一致すること |
equalSsml(expected: IOutputSpeech) | SSMLテキストが完全一致すること |
notEqualPlain(expected: IOutputSpeech) | プレーンテキストが完全一致しないこと |
notEqualSsml(expected: IOutputSpeech) | SSMLテキストが完全一致しないこと |
containsPlain(expected: IOutputSpeech) | プレーンテキストが部分一致すること |
containsSsml(expected: IOutputSpeech) | SSMLテキストが部分一致すること |
matchesPlain(expected: IOutputSpeech) | プレーンテキストが正規表現と一致すること |
matchesSsml(expected: IOutputSpeech) | SSMLテキストが正規表現と一致すること |
doesNotMatchPlain(expected: IOutputSpeech) | プレーンテキストが正規表現と一致しないこと |
doesNotMatchSsml(expected: IOutputSpeech) | SSMLテキストが正規表現と一致しないこと |
startsWithPlain(expected: IOutputSpeech) | プレーンテキストが前方一致すること |
startsWithSsml(expected: IOutputSpeech) | SSMLテキストが前方一致すること |
endsWithPlain(expected: IOutputSpeech) | プレーンテキストが後方一致すること |
endsWithSsml(expected: IOutputSpeech) | SSMLテキストが後方一致すること |
IOutputSpeech インタフェース
検証する会話の内容を設定します。
現在対応しているものは以下の4つです。
- speech - Alexaが返答する最初の発話
- reprompt - 一定時間応答が無かった場合の発話
- cardTitle - カードタイトル
- cardContent - カード内容
今後はカード情報も検証できるよう拡張していく予定です。
カードタイトル、カード内容も追加しました。
サンプル
サンプルは、githubにもありますが以下のような感じです。
呼出したインテントに合わせて結果を確認するようにメソッドチェインしていきます。
import * as Conversation from 'alexa-conversation-model-assert';
import { handler } from '../src/index';
const condition: Conversation.IConversationCondition = {
handler: handler,
request: {
locale: 'ja-JP'
},
testDescription: 'hello-world'
};
const scenario = Conversation.init(condition);
/**
* シナリオテスト
*/
scenario
.requestIntent('LaunchRequest')
.equalPlain({
speech: 'Welcome to the Alexa Skills Kit, you can say hello!',
reprompt: 'Welcome to the Alexa Skills Kit, you can say hello!'
})
.requestIntent('AMAZON.HelpIntent')
.equalPlain({
speech: 'You can say hello to me!',
reprompt: 'You can say hello to me!'
})
.requestIntent('AMAZON.StopIntent')
.equalPlain({
speech: 'Goodbye!'
})
.equalSsml({
speech: '<speak>Goodbye!</speak>'
})
.end();
利用を開始する為にはまずinit
を呼出し、初期化します。
初期化時の条件
export interface IConversationCondition {
handler: LambdaHandler;
request?: {
locale?: string;
};
testDescription: string;
isEnabledTrace?: boolean;
}
項目 | 説明 |
---|---|
handler | Lambdaハンドラー |
request.locale | ロケール設定(ja-JP, en-USなど) |
testDescription | テストの概要を入力 |
isEnabledTrace | テストフレームワーク側の任意の箇所にトレース出力を仕込んでます。 出力を有効にする場合、 true を設定。 |
requestIntent
の引数
requestIntent
の引数は、
export interface IConversationBuilder {
requestIntent(intentName: string, condition?: IRequestIntentCondition): this;
// 省略
}
項目 | 説明 |
---|---|
intentName | 呼び出すインテント名を指定 |
condition | インテント呼出の条件(後述) |
export interface IRequestIntentCondition {
context?: {
System?: {
application?: AskModel.Application;
device?: AskModel.Device;
user?: AskModel.User;
apiAccessToken?: string;
};
};
request?: {
dialogState?: AskModel.DialogState;
intent?: {
confirmationStatus?: AskModel.IntentConfirmationStatus;
slots?: {
[key: string]: AskModel.Slot
}
};
requestId?: string;
};
session?: {
newSession?: boolean;
sessionId?: string;
application?: AskModel.Application;
user?: AskModel.User;
};
slots?: {
[key: string]: AskModel.Slot;
};
}
渡された条件を基に、ask-sdk-model
のRequest
オブジェクトの中身を設定します。
slots
のみ指定しやすいように上の階層に移動しています。
(本来の設定場所は、request.intent.slots
)
↑20180520追記
指定しやすいように外出しましたが、実際自分で使ってみて元の位置で良いなという結論になったので
将来的に↑は非推奨となります。
request.intent.slots
から指定してください。
スロットを指定する場合は例えば以下のように設定します。
.requestIntent('RecipeIntent', {
request: {
intent: {
slots: {
Item: {
name: 'Item',
value: 'slot sample',
confirmationStatus: 'CONFIRMED'
}
}
}
}
})
公開の準備
npmjsへのサインアップ
以下の情報を入力しサインアップしましょう。
設定例として私が入力したものを載せています。
項目 | 設定例 | 備考 |
---|---|---|
Full Name | Daisuke Araki | |
Public Email | test@example.com | 公開可能なメールアドレス |
UserName | daisukeark | |
Password | 任意 |
こんな感じで出てきます。
設定
$ npm set init.author.name "Daisuke Araki"
$ npm set init.author.email "公開可能なメールアドレス"
npmjsへのユーザ登録
$ npm adduser
Username: `登録ユーザ名`
Password: `パスワード`
Email: (this IS public) `登録メールアドレス`
Authenticator provided OTP: `ワンタイムパスワード`
Logged in as `username` on https://registry.npmjs.org/.
package.json設定
ここは色んなサイトに情報があるので割愛します。
リンクのみ置いておきます。
.npmignore作成
ここは任意です。各モジュールに合わせて必ず作成しましょう。
alexa-conversation-model-assert
では、以下を設定しています。
.editorconfig
.git
.gitignore
.istanbul.yml
coverage/
dist/test/
package-lock.json
src/
test/
tsconfig.json
tslint.json
公開
公開は以下のコマンドを実行するだけです。(カレントディレクトリ間違えないように!)
$ npm publish ./
+ alexa-conversation-model-assert@1.0.0
まとめ
初めての公開なのでpublish
コマンド実行前は、すごい不安がありプルプルしてましたが無事公開されました\(^o^)/
〜麻雀の符計算を Alexa にお願いするまで〜で投稿したじゃらじゃら 符計算
スキルをv2へマイグレーションして使ってみたい!
ドキュメントやテストが不足しているので、まずはそこからブラッシュアップしていきます!
何も考えずとりあえず日本語で作っちゃったので、英語でも展開したいなぁと思います。
不具合や機能追加などご意見あれば、こちらへお願いします!
GitHub - Issues
npm
https://www.npmjs.com/package/alexa-conversation-model-assert
github
https://github.com/daisukeArk/alexa-conversation-model-assert