如何对需要用户在 Bot Framework 中选择一个选项的自定义提示进行单元测试 [英] How to unit test custom prompt that requires user select a choice in Bot Framework

查看:32
本文介绍了如何对需要用户在 Bot Framework 中选择一个选项的自定义提示进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些使用自适应卡片制作的自定义提示,需要用户输入,例如 input.ChoiceSet 和 input.Text.

我的问题是,如果我有一张有 3 个选项(红色"、蓝色"、绿色")的卡片,我想测试红色"的结果被选中.如何在我的测试代码中发送选择并获得结果.我想在选择某些内容并且用户点击提交按钮后对结果和流程进行单元测试.

我使用 JObject 以字符串的形式获取用户的选择;

在我的对话框类的构造函数中,我已将提示添加到对话框中.

AddDialog(new CustomPrompt("cardPrompt", DialogValidators.AdaptiveCardValidatorAsync));

这是我用于测试的对话框代码.

私有异步任务aStep(WaterfallStepContext stepContext, CancellationToken 取消令牌){varadaptiveActivity = stepContext.Context.Activity.CreateReply();自适应活动.AddCardAttachment();返回等待 stepContext.PromptAsync(卡片提示",新的提示选项{提示 = 自适应活动,RetryPrompt = MessageFactory.Text(xxx"),验证 = 新列表<字符串>{ 选择卡"}});}私有异步任务bStep(WaterfallStepContext stepContext, CancellationToken 取消令牌){JObject answerObject = (JObject)JsonConvert.DeserializeObject(stepContext.Result.ToString());string userChoice = answerObject[choiceID"].ToString();}

下面是我的测试代码.

userState = new UserState(new MemoryStorage());var subDialog = new SubDialog(userState);var MainDialog = new MainDialog(subDialog);var testClient = new DialogTestClient(Channels.Msteams, MainDialog);//这里有一些代码回复 = 等待 testClient.SendActivityAsync(Red");Assert.AreEqual(XXXX, 回复....);

如何使用 DialogTestClient 进行测试?

感谢您为此付出的时间.

更新

下面是我的提示课.它扩展了具有抽象方法(OnPromptAsync 和 OnRecognizeAsync)的 Prompt2 并扩展了 Dialog 类.

公共类 CustomPrompt : Prompt2{public CustomPrompt(string dialogId, PromptValidatorvalidator = null): base(dialogId, 验证器){}受保护的异步覆盖任务 OnPromptAsync(ITurnContext turnContext, IDictionary state, PromptOptions options, bool isRetry, CancellationTokenCancellationToken = default(CancellationToken)){if (turnContext == null){throw new ArgumentNullException(nameof(turnContext));}如果(选项 == 空){throw new ArgumentNullException(nameof(options));}if (isRetry && options.RetryPrompt != null){await turnContext.SendActivityAsync(options.RetryPrompt, cancelToken).ConfigureAwait(false);}否则如果(options.Prompt != null){await turnContext.SendActivityAsync(options.Prompt, cancelToken).ConfigureAwait(false);}}protected override Task>OnRecognizeAsync(ITurnContext turnContext, IDictionary state, PromptOptions options, CancellationToken cancelToken = default(CancellationToken)){if (turnContext == null){throw new ArgumentNullException(nameof(turnContext));}var result = new PromptRecognizerResult();if (turnContext.Activity.Type == ActivityTypes.Message){var message = turnContext.Activity.AsMessageActivity();if (!string.IsNullOrEmpty(message.Text)){result.Succeeded = true;结果.值 = 消息.文本;}/*添加对来自自适应卡的值的处理*/否则如果(消息.值!= null){result.Succeeded = true;result.Value = message.Value.ToString();}}返回 Task.FromResult(result);}}

这是我卡片的结构.

{类型":AdaptiveCard",身体":[{类型":容器",项目":[{类型":Input.ChoiceSet",包装":真,id":选择ID",值":{defaultValue}占位符":占位符文本",选择":[{标题:aaaa",值:testChoice"}],风格":扩展"}]}],行动":[{类型":Action.Submit",id":提交",标题":确认",数据":{价值":提交",id":选择卡}},{类型":Action.Submit",id":取消",标题":取消",数据":{值":取消",id":选择卡"}}],$schema":http://adaptivecards.io/schemas/adaptive-card.json",版本":1.1"

我想知道如何测试我是否选择了卡的任何选项并使用 TestFlow 获得机器人的正确响应.谢谢.

解决方案

提示类中的代码显示自适应卡片提交操作数据已传输到活动值属性中的机器人:

<块引用>

/*添加对自适应卡中的值的处理*/否则如果(消息.值!= null){result.Succeeded = true;result.Value = message.Value.ToString();}

您在测试中必须做的就是通过自己填充其 value 属性来模拟发送此类活动.

var activity = new Activity(ActivityTypes.Message, value: submitActionData);回复 = 等待 testClient.SendActivityAsync(活动);

这应该适用于对话测试客户端或测试流程.您可以在我的 卡片库测试.

I have some custom prompts made with adaptive cards which require user inputs such as input.ChoiceSet and input.Text.

My problem here is if I have a card with 3 choices ('Red', 'Blue', 'Green'), and I would like to test the result of "Red" being selected. How do I send the choice and get result in my test code. I would like to unit test the result and flow after something is selected and the user hit the submit button.

I use JObject to get the user's selection as a string;

In the constructor of my dialog class I have add the prompt to the dialog.

AddDialog(new CustomPrompt("cardPrompt", DialogValidators.AdaptiveCardValidatorAsync));

Here is my dialog code for testing.

private async Task<DialogTurnResult> aStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
            var adaptiveActivity = stepContext.Context.Activity.CreateReply();
            adaptiveActivity.AddCardAttachment();
            return await stepContext.PromptAsync(
                "CardPrompt",
                new PromptOptions
                {
                    Prompt = adaptiveActivity,
                    RetryPrompt = MessageFactory.Text("xxx"),
                    Validations = new List<string> { "selectionCard" }
                });
}

private async Task<DialogTurnResult> bStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
            JObject answerObject = (JObject)JsonConvert.DeserializeObject(stepContext.Result.ToString());
            string userChoice = answerObject["choiceID"].ToString();
}

Below is my test code.

userState = new UserState(new MemoryStorage());
var subDialog = new SubDialog(userState);
var MainDialog = new MainDialog(subDialog);
var testClient = new DialogTestClient(Channels.Msteams, MainDialog);

// some code here

reply = await testClient.SendActivityAsync<IMessageActivity>("Red");
Assert.AreEqual(XXXX, reply....);

How to work with DialogTestClient for the test?

Appreciate your time for this.

Update

Below is my prompt class. It extends Prompt2 which has abstract methods (OnPromptAsync and OnRecognizeAsync) and extends Dialog class.


public class CustomPrompt : Prompt2<string>
    {
        public CustomPrompt(string dialogId, PromptValidator<string> validator = null)
            : base(dialogId, validator)
        {
        }

        protected async override Task OnPromptAsync(ITurnContext turnContext, IDictionary<string, object> state, PromptOptions options, bool isRetry, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (isRetry && options.RetryPrompt != null)
            {
                await turnContext.SendActivityAsync(options.RetryPrompt, cancellationToken).ConfigureAwait(false);
            }
            else if (options.Prompt != null)
            {
                await turnContext.SendActivityAsync(options.Prompt, cancellationToken).ConfigureAwait(false);
            }
        }

        protected override Task<PromptRecognizerResult<string>> OnRecognizeAsync(ITurnContext turnContext, IDictionary<string, object> state, PromptOptions options, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            var result = new PromptRecognizerResult<string>();
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                var message = turnContext.Activity.AsMessageActivity();
                if (!string.IsNullOrEmpty(message.Text))
                {
                    result.Succeeded = true;
                    result.Value = message.Text;
                }

                /*Add handling for Value from adaptive card*/
                else if (message.Value != null)
                {
                    result.Succeeded = true;
                    result.Value = message.Value.ToString();
                }
            }

            return Task.FromResult(result);
        }
    }


Here is the structure of my card.

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "Container",
      "items": [
        {
          "type": "Input.ChoiceSet",
          "wrap":  true,
          "id": "choiceID",
          "value": {defaultValue}
          "placeholder": "Placeholder text",
          "choices": [
            {
              title: "aaaa",
              value: "testChoice"
            }
          ],
          "style": "expanded"
        }
      ]
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "id": "submit",
      "title": "Confirm",
      "data": {
        "value": "submit",
        "id": selectionCard"
      }
    },
    {
      "type": "Action.Submit",
      "id": "cancel",
      "title": "Cancel",
      "data": {
        "value": "cancel",
        "id": "selectionCard"
      }
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.1"

I was wondering how do I test if I select any choice of the card and get proper response from the bot using TestFlow. Thanks.

解决方案

The code in your prompt class reveals that Adaptive Card submit action data gets transferred to the bot in the activity's value property:

/*Add handling for Value from adaptive card*/
else if (message.Value != null)
{
    result.Succeeded = true;
    result.Value = message.Value.ToString();
}

All you must do in the test is to simulate sending such an activity by populating its value property yourself.

var activity = new Activity(ActivityTypes.Message, value: submitActionData);
reply = await testClient.SendActivityAsync<IMessageActivity>(activity);

This should work with either dialog test client or test flow. You can see some examples of this in my cards library tests.

这篇关于如何对需要用户在 Bot Framework 中选择一个选项的自定义提示进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆