kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

(20190612一部訂正)ask-cliのdialogコマンドでAlexaスキルのマルチターン会話をテストする

追記:2019/06/12

スキルアワードハッカソン2019向けに内容を見直しました。ぜひご活用ください!


Alexaスキルのテストは、

  • 開発者コンソールのテストシミュレータ
  • 実機

が基本だと思いますが、ちょっとめんどくさい・ある程度自動化したいということで調べてみました。なお、ディスプレイ対応デバイスのテストについては考えないことにします。。。。


ask-cli の simulateコマンド

simulateコマンドを使えば、「単発」の発話のテストができます。日本語も使えます。

拙作「HTTPステータス検索」スキルを使って実際にやってみます。

HTTPステータス検索

HTTPステータス検索

ちなみにスキルの一連の流れはこんな感じです。

アレクサ、HTTPステータス検索を開いて

HTTPステータス検索です。3桁のステータスコードを言ってください。

200

ステータスコード200ですね。ステータスコード200は、OK、です。リクエストは成功し、レスポンスとともに要求に応じた情報が返されます。ブラウザでページが正しく表示された場合は、ほとんどがこのステータスコードを返しています。

ではやってみます。スキル起動するところから。実行結果の出力は端折ってますのでご了承ください。

$ ask simulate -t "HTTPステータス検索を開いて" -s amzn1.ask.skill.xxx -l ja-JP
✓ Simulation created for simulation id: xxx
{
  "id": "xxx",
  "status": "SUCCESSFUL",
  "result": {
・・・
          "invocationResponse": {
            "body": {
              "version": "1.0",
              "response": {
                "outputSpeech": {
                  "type": "SSML",
                  "ssml": "<speak>HTTPステータス検索です。三桁のHTTPステータスコードを言ってください。</speak>"
                },
                "card": {
                  "type": "Simple",
                  "title": "HTTPステータス検索",
                  "content": "HTTPステータス検索です。"
                },
                "reprompt": {
                  "outputSpeech": {
                    "type": "SSML",
                    "ssml": "<speak>三桁のHTTPステータスコードを言ってください。</speak>"
                  }
                },
                "shouldEndSession": false,
                "type": "_DEFAULT_RESPONSE"
              },
・・・

ここでコマンドは終わってますが、想定の流れでそのまま続けます。

$ ask simulate -t "二百" -s amzn1.ask.skill.xxx -l ja-JP
✓ Simulation created for simulation id: xxx
{
  "id": "xxx",
  "status": "SUCCESSFUL",
  "result": {
・・・
          "invocationResponse": {
            "body": {
              "version": "1.0",
              "response": {
                "outputSpeech": {
                  "type": "SSML",
                  "ssml": "<speak>ステータスコード200ですね。ステータスコード200は、OK、です。リクエストは成功し、レスポンスとともに要求に応じた情報が返されます。ブラウザでページが正しく表示された場合は、ほとんどがこのステータスコードを返しています。</speak>"
                },
                "card": {
                  "type": "Simple",
                  "title": "HTTPステータス検索",
                  "content": "ステータスコード200ですね。ステータスコード200は、OK、です。リクエストは成功し、レスポンスとともに要求に応じた情報が返されます。ブラウザでページが正しく表示された場合は、ほとんどがこのステータスコードを返しています。"
                },
                "type": "_DEFAULT_RESPONSE"
              },
・・・

ask simulateは、「単発」の発話テスト用のコマンドですけど、きちんとスキルの想定どおりに会話フローが続いてますね。出力されたJSONの中を見ると、1回目も2回目もsessionIdが同じになってるので、コマンドが終わってもスキルのセッションは一定時間継続しているのだと思います。なので上記のQiitaの中で紹介されている通り、ユーザの発話例をテキストでまとめておいて、シェルスクリプトで順次コマンドに渡せばマルチターンのテストもできそうです。

ask-cli の dialogコマンド

ちなみに本題はこれです。以前ドキュメント見たときはなかったと思うのでいつのまにやら追加されたみたいです。手元の環境でも普通にask dialog叩いても出てこなくて、ask-cliをバージョンアップしたら使えるようになりました。まだ「開発者プレビュー」扱いなので注意。

開発者がAlexaとのマルチターンの会話をシミュレートできるダイアログモードを開始します。各ダイアログはsimulate-skillを使用します。これは、シミュレーション結果が入手できるまでポーリングを続ける非同期の操作です。結果を入手したら、Alexaのテキスト応答を表示します。パラメーターが無効な場合、対話モードは開始しません。また、ユーザーが特殊コマンドの「!quit」かCtrl+Cを入力しない限り終了しません。

これならシェルスクリプトすら不要で、ask-cliだけで完結することになりますね!

ということで、早速やってみます。ask dialogを単に実行すると対話形式になるので、想定の発話フローを入力していきます。-sでスキルIDを指定すればask-cliで作成してないスキルでも使えます。(ask-cliで作ったスキルなら、スキルのプロジェクトフォルダで実行すれば-sも不要)

$ ask dialog -s amzn1.ask.skill.xxx -l ja-JP
  User  >  HTTPステータス検索を開いて
  Alexa >  HTTPステータス検索です。三桁のHTTPステータスコードを言ってください。
  User  >  二百
  Alexa >  ステータスコード200ですね。ステータスコード200は、OK、です。リクエストは成功し、レスポンスとともに要求に応じた情報が返されます。ブラウザでページが正しく表示された場合は、ほとんどがこのステータスコードを返しています。
  User  >  !quit

できました。いかにも対話っぽい感じで良いですね。

でもこれを何度も入力するのは嫌だ、ということで、発話を記録しておいた「再生ファイル」を元にテストを行う--replayオプションというのを使います。

再生ファイルのフォーマットはこんな感じのjsonです。

{
  "skillId": "amzn1.ask.skill.xxx",
  "locale": "ja-JP",
  "type": "text",
  "userInput": ["HTTPステータス検索を開いて","二百"]
}

見ればわかると思いますが、skillIdにスキルIDを指定して、userInputのところにユーザの想定される発話を配列で並べるだけです。あとはこのファイルをask dialog --replayで食わせるだけです。

$ ask dialog --replay test.json
  [Info]: Replaying file test.json.
  User  >  HTTPステータス検索を開いて
  Alexa >  HTTPステータス検索です。三桁のHTTPステータスコードを言ってください。
  User  >  二百
  Alexa >  ステータスコード200ですね。ステータスコード200は、OK、です。リクエストは成功し、レスポンスとともに要求に応じた情報が返されます。ブラウザでページが正しく表示された場合は、ほとんどがこのステータスコードを返しています。
  User  >  !quit

ちなみに-oでファイルを指定すると、前述のask simulateとかAlexa開発者ポータルのテストで出力されるようなJSONレスポンスが指定したファイルに出力されます。これを組み合わせると、画面に出力されるのは純粋なやりとりだけ、ask simulateよりも見通しがよい、詳しく見たいなら出力ファイルを見る、って感じで、使いやすいです。

$ ask dialog --replay test.json -o result.txt

ただし、いくつかイケてないところも。

ドキュメントでは、ask dialogのプロンプトの一番最初で!recordを実行すると、発話の入力に合わせて、テスト用のファイルが作成されるみたいなんで試してみたんですが、

ask dialog -s amzn1.ask.skill.xxx -l ja-JP
  User  >  !record
? Enter the file name you want to record to: test.json
  User  >  HTTPステータス検索を開いて
  Alexa >  HTTPステータス検索です。三桁のHTTPステータスコードを言ってください。
  User  >  二百
  Alexa >  ステータスコード200ですね。ステータスコード200は、OK、です。リクエストは成功し、レスポンスとともに要求に応じた情報が返されます。ブラウザでページが正しく表示された場合は、ほとんどがこのステータスコードを返しています。
  User  >  !quit

できた再生ファイルを見ると、

{
  "skillId": "amzn1.ask.skill.xxx",
  "locale": "ja-JP",
  "type": "text",
  "userInput": []
}

userInputが空なんですよね、、、まあプレビューなのでしょうがないかもです。

追記:2019/05/25

!recordは最後に入れればよいというご指摘をいただきました。(ありがとうございます!@Toshimin8さん)なのでこんな感じになります。

$ ask dialog -s amzn1.ask.skill.xxx -l ja-JP
  User  >  HTTPステータス検索を開いて
  Alexa >  HTTPステータス検索です。三桁のHTTPステータスコードを言ってください。
  User  >  二百
  Alexa >  ステータスコード200ですね。ステータスコード200は、OK、です。リクエストは成功し、レスポンスとともに要求に応じた情報が返されます。ブラウザでページが正しく表示された場合は、ほとんどがこのステータスコードを返しています。
  User  >  !record
? Enter the file name you want to record to: test.json
  User  >  !quit

できたファイルはこんな感じになります。

test.json
{
  "skillId": "amzn1.ask.skill.xxx",
  "locale": "ja-JP",
  "type": "text",
  "userInput": [
    "HTTPステータス検索を開いて",
    "二百"
  ]
}

ちなみに補足ですが、--stage でスキルのテストのステージを選べます。スキルを公開したことがある方はご存知だと思いますが、スキルを公開すると「公開中」と「開発中」の2つが用意されます。「開発中」のスキルを修正をして申請を通過すると、それが「公開中」になる、というのが継続的なスキル開発の流れなので、このオプションはどちらのバージョンをテストするかを指定できるということです。「公開中」の場合は"live"、「開発中」の場合は"development"になります。デフォルトは"development"です。(なので公開していないスキルの場合はオプション不要ですし、気にしなくて良いと思います)

追記: 2019/6/22

以下の不具合、改修されたのかはわかりませんが、再現しなくなったので消しときます。合わせて上の例からも—stageオプション消してます。

上の例で"live"を指定しているのは、既に公開済のスキルの「開発中」バージョンに対してコマンドを実行すると「スキルのステージが公開されていない」と言われてテストができないからです。開発者コンソールで該当のスキルの「開発中」バージョンのテスト画面を確認すると確かに「非公開」になってます。これを「開発中」に変えて再度コマンド実行しても、また「非公開」になっちゃうのですよね、、、不具合なのかどうかわかりませんが、とりあえず今回の記事ではコマンドの実行の仕方を確認したかったので、問題なく実行できた—stage liveを指定してます。開発者フォーラムで確認してみたところ類似の事象もあるようなので、これもフォーラムに上げてます。

forums.developer.amazon.com

あと、最後まで進んだらコマンド終了してほしいんですけど、プロンプトで止まるんですよね。!quit は再生ファイルに含めれないみたいなので、毎回!quitするかCtrl+Cしないといけないのは面倒です。shouldEndSessionがtrueなら勝手に終わってくれればいいのに、と思いますね。

nodeモジュール「alexa-conversation」

www.npmjs.com

ざっと見る限り、これが一番テストらしいテストができそうですね。ただ、1年ぐらい更新されてない。。。。今でも使えるのかなぁ。。。。

以下に紹介記事もあるので、また確認してみたいと思います。

dev.classmethod.jp

wp-kyoto.net


ということで、Alexaスキルのテストについてでした。最近、alexa-hostedスキルが使えるようになって下手すると開発者コンソールだけで全部済んじゃうので、ask-cli使う回数がめっきり減ってますが、テストシミュレータ何度も実行するの面倒だし、このあたりはask-cliのほうが便利だなーと思います。特にask dialog、必要最低限の機能はあるのでサラッとテストするにはいい感じです。他にもっといいテスト方法があれば教えていただけると嬉しいです。

しかし、Alexaスキルのテストについてググって、見つかる記事が軒並み2017〜2018年春頃の記事で、改めて先人達はほんとすごいなと、、、、