前回の続き。
テストシナリオの書き方について。
目次
前回のテストシナリオ
前回用意したテストシナリオを一つピックアップします。
tripadvisor_happypath01.convo.txt
トリップアドバイザーのテスト:Happy Path #1 #me トリップアドバイザーを開いて #bot はじめまして、トリップアドバイザースキルをご利用いただきありがとうございます。このスキルでは行きたい日本の都市名をいうとおすすめの観光名所を提案します。例えば「京都に行きたい」と言ってみてください。 #me 京都 かな #bot 京都 ですね。京都 は清水寺がおすすめです。
会話の内容がそのまま書いてあり、ユーザの発話パターンに応じて別のシナリオにしています。これはこれでいいんですが、色々バリエーションが増えてくると難しい。ということでこれを分離していきましょう。
発話のバリエーション
発話のバリエーションに対応するのがutterances.txt
になります。以下のようなファイルを用意します。
happypath01_utt.utterances.txt
HAPPYPATH01_UTT 京都 京都 かな 京都 がいいな 京都 に行きたい
convo.txtの方を修正します。
トリップアドバイザーのテスト:Happy Path #1 #me トリップアドバイザーを開いて #bot はじめまして、トリップアドバイザースキルをご利用いただきありがとうございます。このスキルでは行きたい日本の都市名をいうとおすすめの観光名所を提案します。例えば「京都に行きたい」と言ってみてください。 #me HAPPYPATH01_UTT #bot 京都 ですね。京都 は清水寺がおすすめです。
では実行してみましょう。他のテストファイルと分けるためにディレクトリを切って移動します。
$ mkdir happypath01 $ mv tripadvisor_happypath01.convo.txt happypath01/. $ mv happypath01_utt.utterances.txt happypath01/.
ディレクトリを指定するには--convos
を使います。
$ botium-cli run --convos happypath01 Botium Test-Suite ✔ トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L1 (10810ms) ✔ トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L2 (10065ms) ✔ トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L3 (10429ms) ✔ トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L4 (10022ms) 4 passing (42s)
utterances.txtに記載した4パターンでテストされているようですね。--verbose
をつけてみるとよくわかります。
$ botium-cli run --convos happypath01 --verbose (...snip...) botium-core-ScriptingProvider HAPPYPATH01_UTT ({ convoDir: 'happypath01', filename: 'happypath01_utt.utterances.txt' }): 京都|京都 かな|京都 がいいな|京都 に行きたい +0ms (...snip...) botium-core-ScriptingProvider assertBotResponse トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L1/Line 12 (Line 9: #me - 京都) BOT: 京都 ですね。京都 は清水寺がおすすめです。 = 京都 ですね。京都 は清水寺がおすすめです。 ... +5s botium-cli-run トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L1 ready, calling done function. +11s (...snip...) botium-core-ScriptingProvider assertBotResponse トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L2/Line 12 (Line 9: #me - 京都 かな) BOT: 京都 ですね。京都 は清水寺がおすすめです。 = 京都 ですね。京都 は清水寺がおすすめです。 ... +5s botium-cli-run トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L2 ready, calling done function. +10s (...snip...) botium-core-ScriptingProvider assertBotResponse トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L3/Line 12 (Line 9: #me - 京都 がいいな) BOT: 京都 ですね。京都 は清水寺がおすすめです。 = 京都 ですね。京都 は清水寺がおすすめです。 ... +5s botium-cli-run トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L3 ready, calling done function. +8s (...snip...) botium-core-ScriptingProvider assertBotResponse トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L4/Line 12 (Line 9: #me - 京都 に行きたい) BOT: 京都 ですね。京都 は清水寺がおすすめです。 = 京都 ですね。京都 は清水寺がおすすめです。 ... +5s botium-cli-run トリップアドバイザーのテスト:Happy Path #1/HAPPYPATH01_UTT-L4 ready, calling done function. +11s (...snip...) 4 passing (41s)
もちろんAlexa(というかボット側)からの発話にバリエーションがある場合もutterances.txtは使えるようです。
スロットを変数として扱う
前回作成したもう一つのテストシナリオ見てみましょう。tripadvisor_happypath02.convo.txtのほうです。
トリップアドバイザーのテスト:Happy Path #2 #me トリップアドバイザーを開いて #bot はじめまして、トリップアドバイザースキルをご利用いただきありがとうございます。このスキルでは行きたい日本の都市名をいうとおすすめの観光名所を提案します。例えば「京都に行きたい」と言ってみてください。 #me 奈良 に行きたい #bot 奈良 ですね。奈良 は東大寺がおすすめです。
ユーザが「奈良」という可変となる値、すなわち「スロット」を発話したのに対して、ボットも繰り返すように「奈良」と答えていますよね。こういう場合には変数が使えます。Botiumでは"Scripting Memory"と呼ばれる機能です。
Scripting Memoryは初期状態では有効化されていないので、まずこれを有効化しましょう。botium.jsonを開いて、botium.Capabilitiesに以下を追加します。
{ "botium": { "Capabilities": { (...snip...) "SCRIPTING_ENABLE_MEMORY": true } } }
ではテストシナリオを修正していきます。最初と同じようにディレクトリを作成してconbo.txtを移動しておきましょう。
$ mkdir happypath02 $ mv tripadvisor_happypath02.convo.txt happypath02/.
tripadvisor_happypath02.convo.txtを以下のように書き換えます。
トリップアドバイザーのテスト:Happy Path #2 #begin SET_SCRIPTING_MEMORY city|奈良 #me トリップアドバイザーを開いて #bot はじめまして、トリップアドバイザースキルをご利用いただきありがとうございます。このスキルでは行きたい日本の都市名をいうとおすすめの観光名所を提案します。例えば「京都に行 きたい」と言ってみてください。 #me $city に行きたい #bot $city ですね。$city は東大寺がおすすめです。
cityという変数を用意して、最初にSET_SCRIPTING_MEMORY
で「奈良」を設定しています。あとのやりとりではその部分はすべて$city
で記載しています。
実行してみます。
$ botium-cli run --convos happypath02 --verbose (...snip...) botium-core-SetScriptingMemoryLogicHook Set scripting memory variable "$city" from "undefined" to "奈良, isGlobal: false, type: onConvoBegin" +0ms (...snip...) botium-core-Convo トリップアドバイザーのテスト:Happy Path #2/Line 12: user says (cleaned by binary and base64 data and sourceData) { botium-core-Convo "sender": "me", botium-core-Convo "channel": null, botium-core-Convo "not": false, botium-core-Convo "optional": false, botium-core-Convo "messageText": "奈良 に行きたい", botium-core-Convo "media": null, botium-core-Convo "buttons": null, botium-core-Convo "cards": null, botium-core-Convo "forms": null, botium-core-Convo "attachments": null, botium-core-Convo "asserters": [], botium-core-Convo "userInputs": [], botium-core-Convo "logicHooks": [] botium-core-Convo } +2ms (...snip...) botium-core-ScriptingMemory fill start: {} +5s botium-core-ScriptingMemory fill end: { '$city': '奈良' } +1ms botium-core-ScriptingProvider assertBotResponse トリップアドバイザーのテスト:Happy Path #2/Line 15 (Line 12: #me - $city に行きたい) BOT: 奈良 ですね。奈良 は東大寺がおすすめです。 = 奈良 ですね。奈良 は東大寺がおすすめです。 ... +5s (...snip...) 1 passing (12s)
対話のやり取りで$cityに当たる部分が、最初に設定した「奈良」で置き換えられて会話が行われているのがわかりますでしょうか。これを使えば、スロットのような可変の値もテストができますね。
上記ではconbo.txtに直接記載して変数を設定しています。
#begin SET_SCRIPTING_MEMORY city|奈良
シナリオごとにこれを書くのはちょっと意味がないですよね。そして、ユーザの発話に応じておすすめされる「清水寺」や「東大寺」の部分も可変なので変数にしたいですね。ではこれを別のファイルに切り出して、happypath01/02のテストを一つにしてしまいましょう。
新しくディレクトリを用意して、conbo.txtをこんな感じで作ります。
$ mkdir happypath
$ vi happypath/tripadvisor_happypath.conbo.txt
トリップアドバイザーのテスト:Happy Path #me トリップアドバイザーを開いて #bot はじめまして、トリップアドバイザースキルをご利用いただきありがとうございます。このスキルでは行きたい日本の都市名をいうとおすすめの観光名所を提案します。例えば「京都に行きたい」と言ってみてください。 #me $city に行きたい #bot $city ですね。$city は$placeがおすすめです。
以下の内容でhappypath/tripadvisor_happypath.scriptingmemory.txt を作成します。
|$city |$place Case1 |京都 |清水寺 Case2 |奈良 |東大寺
実行してみましょう。scriptingmemory.txtを使う場合は--expandscriptingmemory
が必要なようです。
$ botium-cli run --convos happypath --expandscriptingmemory true --verbose (...snip...) botium-core-ScriptingProvider ReadConvosFromDirectory(happypath) scripting memories: botium-core-ScriptingProvider { botium-core-ScriptingProvider header: { name: 'Case1' }, botium-core-ScriptingProvider values: { '$city': '京都', '$place': '清水寺' }, botium-core-ScriptingProvider sourceTag: { filename: 'tripadvisor_happypath.scriptingmemory.txt' } botium-core-ScriptingProvider } botium-core-ScriptingProvider { botium-core-ScriptingProvider header: { name: 'Case2' }, botium-core-ScriptingProvider values: { '$city': '奈良', '$place': '東大寺' }, botium-core-ScriptingProvider sourceTag: { filename: 'tripadvisor_happypath.scriptingmemory.txt' } (...snip...) botium-core-Convo トリップアドバイザーのテスト:Happy Path.Case1/Line 9: user says (cleaned by binary and base64 data and sourceData) { botium-core-Convo "sender": "me", botium-core-Convo "channel": null, botium-core-Convo "not": false, botium-core-Convo "optional": false, botium-core-Convo "messageText": "京都 に行きたい", botium-core-Convo "media": null, botium-core-Convo "buttons": null, botium-core-Convo "cards": null, botium-core-Convo "forms": null, botium-core-Convo "attachments": null, botium-core-Convo "asserters": [], botium-core-Convo "userInputs": [], botium-core-Convo "logicHooks": [] botium-core-Convo } +2ms (...snip...) botium-core-ScriptingMemory fill start: {} +5s botium-core-ScriptingMemory fill end: { '$city': '京都', '$place': '清水寺' } +0ms botium-core-ScriptingProvider assertBotResponse トリップアドバイザーのテスト:Happy Path.Case1/Line 12 (Line 9: #me - $city に行きたい) BOT: 京都 ですね。京都 は清水寺がおすすめです。 = 京都 ですね。京都 は清水寺がおすすめです。 ... +5s botium-cli-run トリップアドバイザーのテスト:Happy Path.Case1 ready, calling done function. +10s ✔ トリップアドバイザーのテスト:Happy Path.Case1 (10032ms) (...snip...) botium-core-Convo トリップアドバイザーのテスト:Happy Path.Case2/Line 9: user says (cleaned by binary and base64 data and sourceData) { botium-core-Convo "sender": "me", botium-core-Convo "channel": null, botium-core-Convo "not": false, botium-core-Convo "optional": false, botium-core-Convo "messageText": "奈良 に行きたい", botium-core-Convo "media": null, botium-core-Convo "buttons": null, botium-core-Convo "cards": null, botium-core-Convo "forms": null, botium-core-Convo "attachments": null, botium-core-Convo "asserters": [], botium-core-Convo "userInputs": [], botium-core-Convo "logicHooks": [] botium-core-Convo } +1ms (...snip...) botium-core-ScriptingMemory fill start: {} +5s botium-core-ScriptingMemory fill end: { '$city': '奈良', '$place': '東大寺' } +1ms botium-core-ScriptingProvider assertBotResponse トリップアドバイザーのテスト:Happy Path.Case2/Line 12 (Line 9: #me - $city に行きたい) BOT: 奈良 ですね。奈良 は東大寺がおすすめです。 = 奈良 ですね。奈良 は東大寺がおすすめです。 ... +5s botium-cli-run トリップアドバイザーのテスト:Happy Path.Case2 ready, calling done function. +11s ✔ トリップアドバイザーのテスト:Happy Path.Case2 (10646ms) 2 passing (22s)
はい、それぞれが展開されて2回テストが行われているのがわかりました。
まとめ
まだまだ触りの部分しか触れていませんが、他にも
- テストシナリオとなるconvoは、上記の書き方以外にもExcel、CSV、YAML、JSON、Markdownなどでも書ける。
- シナリオの分割(シナリオから別のシナリオを呼び出す)もできる。
- Scripting Memoryでは関数も使える。
- マルチモーダルでのボタンアクションなどにも対応できる
などなど機能はかなり豊富にあるようですので、柔軟なテストシナリオを書くことができそうです。興味があればドキュメントをご覧ください。
次回はちょっとBotium Boxを見てみたいと思います。