如何对需要用户 select 在 Bot Framework 中进行选择的自定义提示进行单元测试
How to unit test custom prompt that requires user select a choice in Bot Framework
我有一些使用自适应卡片制作的自定义提示,需要用户输入 input.ChoiceSet 和 input.Text。
我的问题是,如果我有一张有 3 个选择的卡片('Red'、'Blue'、'Green'),我想测试“红色”的结果select编辑。如何发送选择并在我的测试代码中获得结果。
我想在 selected 并且用户点击提交按钮后对结果和流程进行单元测试。
我使用 JObject 获取用户的 selection 作为字符串;
在我的对话框的构造函数中 class 我已将提示添加到对话框中。
AddDialog(new CustomPrompt("cardPrompt", DialogValidators.AdaptiveCardValidatorAsync));
这是我用于测试的对话代码。
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();
}
下面是我的测试代码。
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....);
如何使用 DialogTestClient 进行测试?
感谢您为此付出宝贵的时间。
更新
下面是我的提示class。它扩展了具有抽象方法(OnPromptAsync 和 OnRecognizeAsync)的 Prompt2 并扩展了 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);
}
}
这是我的卡片结构。
{
"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"
我想知道如何测试我是否 select 使用 TestFlow 选择任何卡片并从机器人那里获得正确的响应。
谢谢。
提示 class 中的代码显示自适应卡片提交操作数据已传输到 activity 值 属性:
中的机器人
/*Add handling for Value from adaptive card*/
else if (message.Value != null)
{
result.Succeeded = true;
result.Value = message.Value.ToString();
}
您在测试中必须做的就是通过自己填充其值 属性 来模拟发送这样一个 activity。
var activity = new Activity(ActivityTypes.Message, value: submitActionData);
reply = await testClient.SendActivityAsync<IMessageActivity>(activity);
这应该适用于对话测试客户端或测试流程。你可以在我的 cards library tests.
中看到一些这样的例子
我有一些使用自适应卡片制作的自定义提示,需要用户输入 input.ChoiceSet 和 input.Text。
我的问题是,如果我有一张有 3 个选择的卡片('Red'、'Blue'、'Green'),我想测试“红色”的结果select编辑。如何发送选择并在我的测试代码中获得结果。 我想在 selected 并且用户点击提交按钮后对结果和流程进行单元测试。
我使用 JObject 获取用户的 selection 作为字符串;
在我的对话框的构造函数中 class 我已将提示添加到对话框中。
AddDialog(new CustomPrompt("cardPrompt", DialogValidators.AdaptiveCardValidatorAsync));
这是我用于测试的对话代码。
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();
}
下面是我的测试代码。
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....);
如何使用 DialogTestClient 进行测试?
感谢您为此付出宝贵的时间。
更新
下面是我的提示class。它扩展了具有抽象方法(OnPromptAsync 和 OnRecognizeAsync)的 Prompt2 并扩展了 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);
}
}
这是我的卡片结构。
{
"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"
我想知道如何测试我是否 select 使用 TestFlow 选择任何卡片并从机器人那里获得正确的响应。 谢谢。
提示 class 中的代码显示自适应卡片提交操作数据已传输到 activity 值 属性:
中的机器人/*Add handling for Value from adaptive card*/ else if (message.Value != null) { result.Succeeded = true; result.Value = message.Value.ToString(); }
您在测试中必须做的就是通过自己填充其值 属性 来模拟发送这样一个 activity。
var activity = new Activity(ActivityTypes.Message, value: submitActionData);
reply = await testClient.SendActivityAsync<IMessageActivity>(activity);
这应该适用于对话测试客户端或测试流程。你可以在我的 cards library tests.
中看到一些这样的例子