无法使用 TestAdapter 为测试保留用户状态
Can't keep user state for tests using TestAdapter
我有一组自动化测试,适用于我的“基本案例”。我为通过某些 URL 访问机器人的用户显示了一些不同的默认值(例如升级联系人)。这通过在用户连接到机器人时在用户 and/or 对话状态中设置值来实现。我可以在 Emulator 中伪造这些值来测试不同的情况。这一切都适用于手动测试。
但是,当我尝试使用 TestAdapter 通过 Mocha 进行测试时,似乎没有保留用户状态。我可以在第一步中看到,我正在根据我在 activity 中的 channelId 值获取欺骗状态值。但是,当我发送第二个 activity 时,状态值已恢复为空。
我认为这是由于 processActivity
函数总是创建一个新的 TurnContext,尽管我有点不清楚为什么它至少不保留用户状态。
所以问题是,我该如何修改这个测试,或者我是否可以采用不同的测试方法,以便我可以在所有活动中保留我在用户状态中设置的值?如果需要,我可以提供 escalationActivity
文件,但它只是一个包含测试用例和测试步骤的对象,这样我就不必在我的 test.js 文件中定义它们(这样我就有可能为其他测试重用相同的框架)。
这是我的 test.js
完整文件。
const { TestAdapter, ActivityTypes, TurnContext, ConversationState, MemoryStorage, UserState } = require('botbuilder');
const { DispatchBot } = require('../../bots/dispatchBot');
const assert = require('assert');
const nock = require('nock');
require('dotenv').config({ path: './.env' });
const { escalationActivity } = require('../testData/escalationDialogTestDataPC');
const memoryStorage = new MemoryStorage();
const userState = new UserState(memoryStorage);
var userDialogStateAccessor = userState.createProperty('userDialogStateProperty');
const conversationState = new ConversationState(memoryStorage);
var dialogState = conversationState.createProperty('dialogState');
const appInsights = require('applicationinsights');
appInsights.setup('dummyKey').start();
const appInsightsClient = appInsights.defaultClient;
// Static texts
const myEatonMessage = `For more information on products and orders, please go to [My.Eaton.com](https://my.eaton.com). If you do not have a My.Eaton account, you can click "Request Access" at the top right.`;
describe('Project Center', async () => {
describe('Escalation', async () => {
const testAdapter = new TestAdapter();
async function processActivity(activity, bot) {
const context = new TurnContext(testAdapter, activity);
await bot.run(context);
}
let bot = new DispatchBot(new ConversationState(memoryStorage), new UserState(memoryStorage), appInsightsClient);
it('Welcome message', async () => {
const conversationUpdateActivity = {
type: ActivityTypes.ConversationUpdate,
channelId: 'projectCenter',
conversation: {
id: 'someId'
},
membersAdded: [
{ id: 'theUser' }
],
from: { id: 'theBot' },
recipient: { id: 'theUser' }
};
await processActivity(conversationUpdateActivity, bot);
let reply = testAdapter.activityBuffer.shift();
assert.strictEqual(reply.attachments[0].content.id, 'menuCard', 'Reply does not match.')
});
// BOT IS LOSING USER STATE ON SUBSEQUENT STEPS
Object.keys(escalationActivity).map((key) => {
describe(key, async () => {
let conversationData = escalationActivity[key].conversation;
//let channel = escalationActivity[key].channel;
//let intent = escalationActivity[key].intialOptions.topIntent;
conversationData.map((interaction, idx) => {
it(idx + '. ' + interaction.type, async () => {
// Create message activity
const messageActivity = {
type: ActivityTypes.Message,
channelId: 'projectCenter',
conversation: {
id: 'someId'
},
from: { id: 'theUser' },
recipient: { id: 'theBot' },
text: interaction.input
};
// Send the conversation update activity to the bot.
await processActivity(messageActivity, bot);
let reply = testAdapter.activityBuffer.shift();
if (idx == 0) { // First index has two extra activities that need to be skipped
reply = testAdapter.activityBuffer.shift();
reply = testAdapter.activityBuffer.shift();
}
assert.strictEqual(reply.text, interaction.reply, 'Reply does not match.');
//assertStrictEqual(1,1);
});
});
});
});
});
});
这并不是一个真正的答案,但我能够通过每次“重新欺骗”我的 projectCenter
频道来使测试工作。对于实际的 bot 功能,此信息通过直接线路中的 webchat/join
事件在 onEvent
中设置,或在所有其他渠道的 onMembersAdded
中设置。正如我的问题中提到的,user/conversation 状态 在我第一次 Mocha 测试后没有被保留 。我还没有解决这个问题,因此我不认为这个问题已经完全解决了。
但是,从至少能够自动测试此功能的角度来看,我通过 onMessage
处理程序实现了这一点。我只是在每条消息上查找我的测试频道 projectCenter
,然后重置所有用户和对话状态属性。
我不喜欢这个,因为它是一段专门用于测试的代码,而且它每次都会覆盖状态,这是一种不好的做法,但到目前为止我还找不到更好的方法来获取信息我需要在用户状态下才能坚持通过我的所有测试。我仍然希望有人能想出更好的解决方案来解决这个问题……也就是说,这至少对我的目的有用,所以我想在这里把它作为一个答案。
我有一组自动化测试,适用于我的“基本案例”。我为通过某些 URL 访问机器人的用户显示了一些不同的默认值(例如升级联系人)。这通过在用户连接到机器人时在用户 and/or 对话状态中设置值来实现。我可以在 Emulator 中伪造这些值来测试不同的情况。这一切都适用于手动测试。
但是,当我尝试使用 TestAdapter 通过 Mocha 进行测试时,似乎没有保留用户状态。我可以在第一步中看到,我正在根据我在 activity 中的 channelId 值获取欺骗状态值。但是,当我发送第二个 activity 时,状态值已恢复为空。
我认为这是由于 processActivity
函数总是创建一个新的 TurnContext,尽管我有点不清楚为什么它至少不保留用户状态。
所以问题是,我该如何修改这个测试,或者我是否可以采用不同的测试方法,以便我可以在所有活动中保留我在用户状态中设置的值?如果需要,我可以提供 escalationActivity
文件,但它只是一个包含测试用例和测试步骤的对象,这样我就不必在我的 test.js 文件中定义它们(这样我就有可能为其他测试重用相同的框架)。
这是我的 test.js
完整文件。
const { TestAdapter, ActivityTypes, TurnContext, ConversationState, MemoryStorage, UserState } = require('botbuilder');
const { DispatchBot } = require('../../bots/dispatchBot');
const assert = require('assert');
const nock = require('nock');
require('dotenv').config({ path: './.env' });
const { escalationActivity } = require('../testData/escalationDialogTestDataPC');
const memoryStorage = new MemoryStorage();
const userState = new UserState(memoryStorage);
var userDialogStateAccessor = userState.createProperty('userDialogStateProperty');
const conversationState = new ConversationState(memoryStorage);
var dialogState = conversationState.createProperty('dialogState');
const appInsights = require('applicationinsights');
appInsights.setup('dummyKey').start();
const appInsightsClient = appInsights.defaultClient;
// Static texts
const myEatonMessage = `For more information on products and orders, please go to [My.Eaton.com](https://my.eaton.com). If you do not have a My.Eaton account, you can click "Request Access" at the top right.`;
describe('Project Center', async () => {
describe('Escalation', async () => {
const testAdapter = new TestAdapter();
async function processActivity(activity, bot) {
const context = new TurnContext(testAdapter, activity);
await bot.run(context);
}
let bot = new DispatchBot(new ConversationState(memoryStorage), new UserState(memoryStorage), appInsightsClient);
it('Welcome message', async () => {
const conversationUpdateActivity = {
type: ActivityTypes.ConversationUpdate,
channelId: 'projectCenter',
conversation: {
id: 'someId'
},
membersAdded: [
{ id: 'theUser' }
],
from: { id: 'theBot' },
recipient: { id: 'theUser' }
};
await processActivity(conversationUpdateActivity, bot);
let reply = testAdapter.activityBuffer.shift();
assert.strictEqual(reply.attachments[0].content.id, 'menuCard', 'Reply does not match.')
});
// BOT IS LOSING USER STATE ON SUBSEQUENT STEPS
Object.keys(escalationActivity).map((key) => {
describe(key, async () => {
let conversationData = escalationActivity[key].conversation;
//let channel = escalationActivity[key].channel;
//let intent = escalationActivity[key].intialOptions.topIntent;
conversationData.map((interaction, idx) => {
it(idx + '. ' + interaction.type, async () => {
// Create message activity
const messageActivity = {
type: ActivityTypes.Message,
channelId: 'projectCenter',
conversation: {
id: 'someId'
},
from: { id: 'theUser' },
recipient: { id: 'theBot' },
text: interaction.input
};
// Send the conversation update activity to the bot.
await processActivity(messageActivity, bot);
let reply = testAdapter.activityBuffer.shift();
if (idx == 0) { // First index has two extra activities that need to be skipped
reply = testAdapter.activityBuffer.shift();
reply = testAdapter.activityBuffer.shift();
}
assert.strictEqual(reply.text, interaction.reply, 'Reply does not match.');
//assertStrictEqual(1,1);
});
});
});
});
});
});
这并不是一个真正的答案,但我能够通过每次“重新欺骗”我的 projectCenter
频道来使测试工作。对于实际的 bot 功能,此信息通过直接线路中的 webchat/join
事件在 onEvent
中设置,或在所有其他渠道的 onMembersAdded
中设置。正如我的问题中提到的,user/conversation 状态 在我第一次 Mocha 测试后没有被保留 。我还没有解决这个问题,因此我不认为这个问题已经完全解决了。
但是,从至少能够自动测试此功能的角度来看,我通过 onMessage
处理程序实现了这一点。我只是在每条消息上查找我的测试频道 projectCenter
,然后重置所有用户和对话状态属性。
我不喜欢这个,因为它是一段专门用于测试的代码,而且它每次都会覆盖状态,这是一种不好的做法,但到目前为止我还找不到更好的方法来获取信息我需要在用户状态下才能坚持通过我的所有测试。我仍然希望有人能想出更好的解决方案来解决这个问题……也就是说,这至少对我的目的有用,所以我想在这里把它作为一个答案。