Test d'intégration avec Bot Framework et DirectLine (3)
Ceci est la dernière partie du guide, dans cette partie, nous évaluerons le texte de l’assertion dans le json.
Maintenant que nous avons utilisé le request et envoyé comme activity au bot, nous avons obtenu le response et nous devons comparer ce que le assert dans le json (la réponse que nous avons stockée dans le json, c’est la réponse attendue) avec la réponse que nous avons obtenue du bot.
** L’explication suivante ne couvrira pas toutes les informations de base sur le fonctionnement du Bot Framework. Si vous ne comprenez pas, veuillez consulter la documentation officielle. **
Ajout de Microsoft.CodeAnalysis à la solution
Tout d’abord, nous devons inclure CodeAnalysis en tant que package NuGet.
Après l’installation, n’oubliez pas d’ajouter le pacakge au fichier .cs.
using Microsoft.CodeAnalysis.CSharp.Scripting;
Création d’un objet Globals
Afin d’évaluer, nous devons transmettre les paramètres à l’évaluateur. Cet évaluateur a besoin d’un fichier de configuration.
/// <summary>
/// Object to pass parameters to Roslyn compiler
/// </summary>
public class Globals
{
/// <summary>
/// ExpectedResponse
/// </summary>
public Activity Request;
/// <summary>
/// ReceivedResponse
/// </summary>
public Activity Response;
}
Cette partie est très importante, dans ce fichier de configuration, nous inclurons les objets que nous comparerons, donc pour nous, nous devons lui transmettre la réponse attendue et la réponse reçue.
Avec ces informations, il utilisera le assert dans le fichier json et évaluera ce qui est dit.
/// Arrange with new values
var globals = new Objects.Globals { Request = entry.Response, Response = latestResponse };
/// Assert
Assert.IsTrue(await CSharpScript.EvaluateAsync<bool>(entry.Assert, globals: globals));
Le EvaluateAsync<T> évalue et renvoie T, dans notre cas, nous transmettons le string à évaluer et globals, qui contient les données où il sera évalué.
Je vais essayer d’expliquer cela avec un exemple, en utilisant une entrée (qui a un nom, une requête, une réponse et une assertion).
{
"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"
}
Obtenons les éléments importants de cette entrée, d’abord l’assertion "assert": "Request.Text == Response.Text", cela signifie qu’il comparera le Request.Text avec le Response.Text, et renverra la valeur sous forme booléenne.
Mais lorsque nous appelons la fonction await CSharpScript.EvaluateAsync<bool>(entry.Assert, globals: globals) nous passons 2 paramètres :
stringchaîne à évaluer ->"Request.Text == Response.Text"globalsdonnées pour l’évaluateur -> dans ce cas, nous devons donner unRequestet unResponse, la demande est notre réponse attendue et la réponse est la réponse reçue.
Pendant que nous remplissons les données dans l’évaluateur, nous pouvons maintenant utiliser la chaîne et évaluer, elle renverra donc true ou false.
Terminé
Nous avons terminé, vous pouvez voir ici le TestMethod terminé
[TestMethod]
public async Task ShouldTestSingleCases()
{
// Load entries from file
var path = System.IO.File.ReadAllText(@"C:\data.json");
// Deserialize to object
var data = JsonConvert.DeserializeObject<TestEntriesCollection>(path);
/// Flow: Arrange -> Act -> arrange -> assert
foreach (TestEntry entry in data.Entries)
{
/// Arrange with current requested values
string token, newToken, conversationId;
if (entry.Request.Type == ActivityTypes.Message)
{
/// Act
/// 1 - Get token using secret from DirectLine in BotFramework panel
token = Utils.uploadString<DirectLineAuth>(data.Secret, data.DirectLineGenerateTokenEndpoint, "").token;
/// 2 -Create a new conversation
var createdConversation = Utils.uploadString<DirectLineAuth>(token, data.DirectLineConversationEndpoint, "");
// This returns a new token and a conversationId
newToken = createdConversation.token;
conversationId = createdConversation.conversationId;
/// 3 - Send an activity to the conversation with new token and conversationId
string directlineConversationActivitiesEndpoint = data.DirectLineConversationEndpoint + conversationId + "/activities";
Utils.uploadString<DirectLineAuth>(newToken, directlineConversationActivitiesEndpoint, JsonConvert.SerializeObject(entry.Request));
/// 4 - Get all activities, we get a List<activity> and a watermark
var getLastActivity = Utils.downloadString<ActivityResponse>(newToken, directlineConversationActivitiesEndpoint);
/// 5 - Get the latest activity which is the response we should be expecting
var latestResponse = getLastActivity.activities[Int32.Parse(getLastActivity.watermark)];
/// Arrange with new values
var globals = new Objects.Globals { Request = entry.Response, Response = latestResponse };
/// Assert
Assert.IsTrue(await CSharpScript.EvaluateAsync<bool>(entry.Assert, globals: globals));
}
}
await Task.CompletedTask;
}
Diagramme
Voici un diagramme de tout le flux que nous avons suivi pour arriver à ce point, j’espère que si vous n’avez pas compris quelque chose, cela clarifie les choses.
Et c’est tout, cela est fait pour des cas uniques où le cas est 1 pour 1, l’utilisateur envoie un activity et le bot renvoie un autre simple activity.
J’espère que vous l’avez aimé, le prochain sera les cas de flux de tests avec plus d’une réponse.
N’oubliez pas que tout le code est stocké dans mon github dans le référentiel this.


