Integrationstest mit Bot Framework und DirectLine (1)

· 4 Min. Lesezeit

Da ich für kurze Zeit in einem Unternehmen gearbeitet habe, wurde ich mit der Arbeit am Integrationstest für das Bot Framework beauftragt.

Meine Arbeit in der Gruppe besteht darin, den Bot so stabil wie möglich zu machen, aber zuerst: Was ist Bot Framework?

Erstellen, verbinden, bereitstellen und verwalten Sie intelligente Bots, um auf natürliche Weise mit Ihren Benutzern auf einer Website, einer App, Cortana, Microsoft Teams, Skype, Slack, Facebook Messenger und mehr zu interagieren. Beginnen Sie schnell mit einer vollständigen Bot-Building-Umgebung und zahlen Sie nur für das, was Sie nutzen.

Weitere Informationen zum Bot Framework finden Sie hier (https://dev.botframework.com/).

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.

Warum brauche ich einen Integrationstest?

Integrationstests sind erforderlich, da jedes Mal, wenn einer meiner Kollegen einen Fix, eine neue Funktion oder sogar einen neuen Fehler veröffentlicht, diese Tests ausgeführt werden, bevor der Code in die Produktion übertragen wird. Wenn einer der Tests fehlschlägt, geht der Code nicht in die Produktion, was bedeutet, dass der Endbenutzer den Fehler nicht hat.

Integrationstest in Bots?

Ich glaube, dass bei Bots der Integrationstest ziemlich wichtig ist. Sie können keinen Bot haben, bei dem einige Menüs nicht funktionieren oder einige Funktionen nichts zurückgeben.

Unternehmen setzen Bots für ihre Kunden ein, weil sie nicht wollen, dass die Leute mit ihren Problemen beschäftigt sind. Wenn ein Bot einem Benutzer helfen kann, können die anderen Mitarbeiter ihre Zeit für etwas Wichtigeres nutzen.

Übersicht über die Lösung.

Damit dies funktioniert, habe ich ein Testprojekt in Visual Studio verwendet, das WebClient für den API-Rest und eine JSON-Datei verwendet, in der wir unsere Fälle speichern.

JSON-Datei

{
  "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"
    }
  ]
}

Wie Sie sehen können, haben wir:

  • Directline-Geheimnis -> Geheimnis des veröffentlichten Bots – Directline-Token-Generierungsendpunkt -> Endpunkt, um das Token mithilfe des Geheimnisses abzurufen
  • Directline-Konversationsendpunkt -> Endpunkt, um mit der Konversation zu spielen
  • Eintrag -> der Testfall
    • Anfrage -> was wir an das Gespräch senden
    • Antwort -> was wir erwarten
    • Behaupten -> was vergleichen wir

Deserialisierung

Wir haben die JSON-Datei perfekt formatiert, jetzt müssen wir sie in die Lösung laden, also werden wir JSON.NET und einige Klassen verwenden. Zuerst haben wir die Eintragssammlung, die alles enthält, und dann haben wir für jede Sammlung eine Liste von Einträgen.

    /// <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; }
    }

Und das ist das Objekt, das den Namen, die Anfrage, die Antwort und die Behauptung für den Testfall hat.


    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; }
    }

Parsen von JSON zum Objekt im Testfall

Da wir die Klassen für das Parsing-Objekt haben, ist es recht einfach, da wir es als Objekt lesen müssen.

// Load entries from file
var path = System.IO.File.ReadAllText(@"C:\data.json");

// Deserialize to object
var data = JsonConvert.DeserializeObject<TestEntriesCollection>(path);

Mit dieser Sammlung können wir nun eine Schleife durchlaufen und die Informationen beispielsweise mithilfe eines foreach abrufen.

 foreach (TestEntry entry in data.Entries)
    {
      ....
    }

Und das ist alles für diesen Teil, der nächste Teil wird die Autorisierung für DirectLine beinhalten. Denken Sie daran, dass der gesamte Code in meinem Github in diesem-Repository gespeichert ist.