Integrationstest mit Bot Framework und DirectLine (3)
Dies ist der neueste Teil des Leitfadens. In diesem Teil werden wir den Text aus der Behauptung im JSON auswerten.
Nachdem wir nun den request verwendet und als activity an den Bot gesendet haben, haben wir den response erhalten und müssen den assert im JSON (die Antwort, die wir im JSON gespeichert haben, dies ist die erwartete Antwort) mit der Antwort vergleichen, die wir vom Bot erhalten haben.
Die folgende Erklärung deckt nicht alle grundlegenden Informationen zur Funktionsweise des Bot Frameworks ab. Wenn Sie es nicht verstehen, schauen Sie sich bitte die offizielle Dokumentation an.
Hinzufügen von Microsoft.CodeAnalysis zur Lösung
Zunächst müssen wir CodeAnalysis als NuGet-Paket einbinden.
Denken Sie nach der Installation daran, das Paket zur Datei .cs hinzuzufügen.
using Microsoft.CodeAnalysis.CSharp.Scripting;
Erstellen eines Globals-Objekts
Zur Auswertung müssen wir die Parameter an den Auswerter übergeben. Dieser Evaluator benötigt eine Konfigurationsdatei.
/// <summary>
/// Object to pass parameters to Roslyn compiler
/// </summary>
public class Globals
{
/// <summary>
/// ExpectedResponse
/// </summary>
public Activity Request;
/// <summary>
/// ReceivedResponse
/// </summary>
public Activity Response;
}
Dieser Teil ist sehr wichtig. In dieser Konfigurationsdatei werden wir angeben, welche Objekte wir vergleichen werden. Daher müssen wir ihm die erwartete Antwort und die erhaltene Antwort übergeben.
Mit diesen Informationen wird das assert in der JSON-Datei verwendet und ausgewertet, was gesagt wird.
/// 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));
Das EvaluateAsync<T> wertet T aus und gibt es zurück. In unserem Fall übergeben wir das auszuwertende string und das globals, das die Daten enthält, in denen es ausgewertet wird.
Ich werde versuchen, dies anhand eines Beispiels zu erklären, indem ich einen Eintrag verwende (der einen Namen, eine Anfrage, eine Antwort und eine Behauptung enthält).
{
"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"
}
Lassen Sie uns die wichtigen Dinge aus diesem Eintrag herausholen, zuerst die Behauptung "assert": "Request.Text == Response.Text", das bedeutet, dass sie den Request.Text mit dem Response.Text vergleicht und den Wert als booleschen Wert zurückgibt.
Aber wenn wir die Funktion await CSharpScript.EvaluateAsync<bool>(entry.Assert, globals: globals) aufrufen, übergeben wir zwei Parameter:
stringauszuwertende Zeichenfolge ->"Request.Text == Response.Text"globalsDaten für den Bewerter -> in diesem Fall müssen wir einenRequestund einenResponseangeben, die Anfrage ist unsere erwartete Antwort und die Antwort ist die erhaltene Antwort.
Während wir die Daten in den Evaluator füllen, können wir jetzt die Zeichenfolge verwenden und auswerten, sodass true oder false zurückgegeben wird.
Fertig
Wir sind fertig, hier sehen Sie das fertige TestMethod
[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;
}
Diagramm
Hier ist ein Diagramm des gesamten Ablaufs, dem wir gefolgt sind, um an diesen Punkt zu gelangen. Wenn Sie etwas nicht verstanden haben, wird es hoffentlich geklärt.
Und das ist alles, dies wird für einzelne Fälle durchgeführt, bei denen der Fall 1-zu-1 ist, der Benutzer einen activity sendet und der Bot einen weiteren einzelnen activity zurückgibt.
Ich hoffe, es hat Ihnen gefallen. Als nächstes werden die Testablauffälle mit mehr als einer Antwort behandelt.
Denken Sie daran, dass der gesamte Code in meinem Github in diesem-Repository gespeichert ist.


