Teste de integração usando Bot Framework e DirectLine (1)
Como comecei a trabalhar em uma empresa por um curto período de tempo, fui designado para trabalhar em testes de integração do Bot Framework.
Meu trabalho no grupo é fazer com que o bot fique o mais estável possível, mas primeiro, o que é Bot Framework?
Crie, conecte, implante e gerencie bots inteligentes para interagir naturalmente com seus usuários em um site, aplicativo, Cortana, Microsoft Teams, Skype, Slack, Facebook Messenger e muito mais. Comece rapidamente com um ambiente completo de criação de bots, pagando apenas pelo que usar.
Você pode encontrar mais informações sobre o Bot Framework diretamente aqui.
A explicação a seguir não cobrirá todas as informações básicas de como funciona o Bot Framework. Se você não entender, consulte a documentação oficial.
Por que preciso de teste de integração?
Os testes de integração são necessários porque toda vez que um dos meus colegas de trabalho envia uma correção, um novo recurso ou até mesmo um novo bug, esses testes serão executados antes de enviar o código para produção e se algum dos testes falhar, o código não irá para produção, o que significa que o usuário final não terá o bug.
Teste de integração em bots?
Acredito que em bots os testes de integração são muito importantes. Você não pode ter um bot onde alguns de seus menus não estejam funcionando ou alguns dos recursos não retornem nada.
As empresas estão usando bots para seus clientes porque não querem que as pessoas fiquem ocupadas com seus problemas. Se um bot puder ajudar um usuário, os outros trabalhadores poderão usar seu tempo para fazer algo mais importante.
Visão geral da solução.
Para fazer isso funcionar, utilizei um projeto de Teste no Visual Studio, que utilizará WebClient para API Rest e um arquivo Json, onde armazenaremos nossos cases.
arquivo JSON
{
"secret": "direct-line-secret",
"directlineGenerateTokenEndpoint": "https://directline.botframework.com/v3/directline/tokens/generate",
"directlineConversationEndpoint": "https://directline.botframework.com/v3/directline/conversations/",
"entries": [
{
"name": "DecirHola",
"request": {
"type": "message",
"text": "Hola",
"from": {
"id": "default-user",
"name": "User"
},
"locale": "es",
"textFormat": "plain",
"timestamp": "2018-04-09T08:04:37.195Z",
"channelData": {
"clientActivityId": "1523261059363.6264723268323733.0"
},
"entities": [
{
"type": "ClientCapabilities",
"requiresBotState": true,
"supportsTts": true,
"supportsListening": true
}
],
"id": "61hacck8j6jg"
},
"response": {
"type": "message",
"timestamp": "2018-04-09T08:04:37.901Z",
"localTimestamp": "2018-04-09T09:04:37+01:00",
"serviceUrl": "http://localhost:50629",
"channelId": "emulator",
"from": {
"id": "j98bbdf097a",
"name": "Bot"
},
"conversation": {
"id": "eabcie4be8ak"
},
"recipient": {
"id": "default-user"
},
"locale": "es",
"text": "No tengo respuesta para eso.",
"attachments": [],
"entities": [],
"replyToId": "61hacck8j6jg",
"id": "47me557ikbf7"
},
"assert": "Request.Text == Response.Text"
}
]
}
Como você pode ver, temos:
- Segredo da linha direta -> segredo do bot publicado
- Endpoint de geração de token Directline -> endpoint para obter o token usando o segredo
- Endpoint de conversação direta -> endpoint para brincar com a conversa
- Entrada -> o caso de teste
- Solicitar -> o que enviamos para a conversa
- Resposta -> o que esperamos obter
- Afirmar -> o que estamos comparando
Desserialização
Temos o arquivo json perfeitamente formatado, agora temos que carregá-lo na solução, então usaremos JSON.NET e algumas classes. Primeiro temos a coleção de entradas, que tem tudo, e depois temos, para cada coleção uma lista de entradas.
/// <summary>
/// Object to parse from the file
/// </summary>
public class TestEntriesCollection
{
/// <summary>
/// DirectLine Secret
/// </summary>
[JsonProperty("secret")]
public string Secret { get; set; }
/// <summary>
/// Endpoint to get the token using the secret for DirectLine
/// </summary>
[JsonProperty("directlineGenerateTokenEndpoint")]
public string DirectLineGenerateTokenEndpoint { get; set; }
/// <summary>
/// Endpoint for a conversation in DirectLine
/// </summary>
[JsonProperty("directlineConversationEndpoint")]
public string DirectLineConversationEndpoint { get; set; }
/// <summary>
/// Entries list
/// </summary>
[JsonProperty("entries")]
public List<TestEntry> Entries { get; set; }
}
E este é o objeto que possui o nome, solicitação, resposta e afirmação do caso de teste.
public class TestEntry
{
/// <summary>
/// Entry name
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// Activity requested by the entry
/// </summary>
[JsonProperty("request")]
public Activity Request { get; set; }
/// <summary>
/// Activity response expected by the entry
/// </summary>
[JsonProperty("response")]
public Activity Response { get; set; }
/// <summary>
/// Assert value in string
/// </summary>
[JsonProperty("assert")]
public string Assert { get; set; }
}
Análise de JSON para objeto no caso de teste
Tendo as classes para o objeto de análise, é muito fácil, pois precisamos ler como o objeto.
// Load entries from file
var path = System.IO.File.ReadAllText(@"C:\data.json");
// Deserialize to object
var data = JsonConvert.DeserializeObject<TestEntriesCollection>(path);
Agora com esta coleção, poderemos percorrê-la e obter as informações usando, por exemplo, um foreach.
foreach (TestEntry entry in data.Entries)
{
....
}
E isso é tudo por esta parte, a próxima parte incluirá a autorização para DirectLine, lembre-se que todo o código está armazenado no meu github no repositório this.