Voy a dedicar este segundo artículo dedicado a la construcción de un chatbot a comentar una cuestión importante que se quedó en el tintero en el artículo anterior. Se trata de explicarte cómo puedes plantear pruebas unitarias para no perder el control del invento. En el caso de los chatbots esta cuestión es tremendamente importante, como verás a continuación.
Desarrolla usando TDD
El Desarrollo Guiado por Pruebas (TDD) es especialmente útil en este tipo de software, ya que los chatbots generalmente requieren aplicar iteraciones muy cortas y rápidas de refactorización. De lo contrario, a medida que vayamos añadiendo o quitando partes de nuestro flujo de conversación nos irá quedando un montón de código descolgado, inútil y «spaguetti».
Necesitamos tener mucho control en el código para no acabar escribiendo más de lo que realmente se necesita y sobre todo debemos ser capaces de detectar fallos cada vez que cambiamos algo en el flujo de las conversaciones, pues es frecuente que un pequeño cambio influya en el funcionamiento de otra parte del programa.
Parece entonces bastante razonable escribir test unitarios para nuestro Chat Bot. Pues veamos la manera de hacerlo:
Opción 1: Botkit-Mock
Uno de los primeros problemas que nos podemos encontrar con BotKit es que depende demasiado de adaptadores con otras aplicaciones (Slack, Facebook, MS Teams, etc.). Por ello existe Botkit-Mock, que es una extensión de Botkit que pretende proporcionar una interfaz para aceptar mensajes de usuario a través de .usersInput.
Lamentablemente, la librería es demasiado nueva y en el momento de escribir este artículo sólo podremos utilizar Botkit-Mock con un adaptador para Slack, de modo que sólo te resultará útil si construyes un bot para Slack.
Para utilizarlo sólo tendremos que instalarlo en neustro proyecto:
1 | npm install --save botkit-mock |
e incluirlo en nuestro proyecto:
1 2 | const { BotMock } = require('botkit-mock'); const fileBeingTested = require("./indexController") |
Aquí tendrías un ejemplo de un test:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 'use strict'; const assert = require('assert'); const {BotMock, SlackApiMock} = require('../../../lib'); const {SlackAdapter, SlackMessageTypeMiddleware, SlackEventMiddleware} = require('botbuilder-adapter-slack'); const fileBeingTested = require('./dialog'); describe('create dialog in a thread', () => { const initController = () => { const adapter = new SlackAdapter({ clientSigningSecret: "some secret", botToken: "some token", debug: true, }); adapter.use(new SlackEventMiddleware()); adapter.use(new SlackMessageTypeMiddleware()); this.controller = new BotMock({ adapter: adapter, }); SlackApiMock.bindMockApi(this.controller); fileBeingTested(this.controller); }; beforeEach(() => { this.userInfo = { slackId: 'user123', channel: 'channel123', }; }); describe('create_service', () => { beforeEach(() => { initController(); }); it(`should reply in a correct sequence through message`, async () => { await this.controller.usersInput([ { type: 'message', user: this.userInfo.slackId, //user required for each direct message channel: this.userInfo.channel, // user channel required for direct message messages: [ { text: 'create_dialog_service', isAssertion: true, } ] } ]); assert.strictEqual(this.controller.detailed_answers[this.userInfo.channel][0].text, `Howdy!`); }); }); }); |
Opción 2: TestMyBot
Dadas las limitaciones de la opción anterior, te propongo otra. TestMyBot es un framework de automatización de prueba para chatbots. Es agnóstico respecto a las herramientas involucradas en tu desarrollo. Y además es gratis y de código abierto.
Las herramientas de captura y reproducción registrarán tus casos de prueba y se ejecutarán contra la implementación de tu chatbot automáticamente una y otra vez. Está planteado para que lo puedas usar en tu delivery pipeline.
Veamos como instalar TestMyBot para utilizarlo junto con la librería Jasmine (framework para desarrollo de test):
1 2 3 4 | npm install testmybot --save-dev npm install jasmine --save-dev ./node_modules/.bin/jasmine init/code> |
Añade un archivo spec/testmybot.spec.js con este contenido:
1 2 3 4 5 | const bot = require('testmybot'); const botHelper = require('testmybot/helper/jasmine'); botHelper.setupJasmineTestSuite(60000); |
Añade también un archivo testmybot.json a tu carpeta de proyecto:
1 2 3 4 5 | { "containermode": "local" } |
El archivo jasmine.js es precisamente el que se encarga de conectar el código de tu chatbot con el código de TestMyBot. Genera una conversación y un informe en XML.
TestMyBot viene con helpers integrados para Jasmine y Mocha, pero también se puede usar con otras librerías. Incluso cuando se usa con Docker, también se puede usar con proyectos de chatbot escritos en otros lenguajes de programación.
En general, nuestros casos de prueba no serán más que conversaciones que el chatbot debería poder manejar. La transcripción de la conversación debe ejecutarse automáticamente, y cualquier diferencia con respecto a la transcripción debe informarse como un error.
En general, estos casos de pruebas constituyen un conjunto de pruebas de regresión y nos garantiza, antes de desplegar después de cualquier cambio, que el chatbot todavía funciona correctamente después de que se cambió o se conectó con otro software.
Por tanto, debes escribir test que garanticen que cualquier cambio en tu chatbot no romperá sus flujos de conversación. Obviamente, esto implica que tendrás que plantear test para todos los flujos de conversación posibles.
TestMyBot IDE
Para interactuar con nuestro ChatBot, contaremos con una herramienta llamada TestMyBot IDE, que nos proporciona una interfaz en el navegador para registrar y organizar nuestros casos de prueba e interactuar con él.
Además, la conversación la guardará en un fichero de texto que posteriormente nos servirá para comprobar que todo ha ido según lo esperado. Por supuesto, cuenta también con herramientas de captura y reproducción que registran tus casos de prueba y pueden ejecutarse contra la implementación dl Chatbot en cualquier momento.
Línea de comandos
Si lo del entorno gráfico no te gusta, TestMyBot incluye una interfaz de línea de comandos para interactuar con tu chatbot. Es muy útil en entornos de servidor.
Veamos como funciona
1 2 3 4 | $ npm install testmybot --save-dev $ npm install testmybot-fbmock --save-dev $ npm install jasmine --save-dev $ ./node_modules/.bin/jasmine init |
Añade un archivo “testmybot.json” a la carpeta de tu proyecto. También será necesaria una configuración básica (la siguiente va sobre Docker):
1 2 3 4 5 6 7 8 9 10 11 12 | { "docker": { "container": { "testmybot-fbmock": { "env": { "TESTMYBOT_BOTKIT_WEBHOOKPORT": 3000, "TESTMYBOT_BOTKIT_WEBHOOKPATH": "webhook" } } } } } |
Imagina un chatbot muy simple que está programado para que cuando tú le digas “Hola” él te responda: «Mundo». El caso de prueba desarrollado con jasmine (pec/testmybot.spec.js) para este flujo conversacional sería el siguiente:
1 2 3 4 5 6 7 8 | describe('Hello World Bot', function() { beforeEach(function() { this.bot = require('testmybot').setup(); }); it('di hola', function() { expect(this.bot.hears('Hola').says().text())).toMatch(/mundo/); }); }); |
Tampoco te olvides de incluir el script en tu package.json.
1 2 3 4 5 | ... "scripts": { "start_testmybot": "node index.js", }, ... |
Como ves, se trata de un objeto que envía texto a tu chatbot (podría ser otro tipo de contenido), y recibe lo que tu bot responde .
Para ejecutar tus test con Jasmine:
1 | ./node_modules/.bin/jasmine init |
Deja un comentario