Skip to content

Latest commit

 

History

History
279 lines (229 loc) · 11.8 KB

BOT.md

File metadata and controls

279 lines (229 loc) · 11.8 KB

MILESTONE: Library BOT

Index

  1. Installation Steps
  2. Use Cases
  3. Bot Implementation
  4. Mocking
  5. Pupeteer Testing
  6. Screencast

INSTALLATION STEPS:

sudo apt-get update
sudo apt-get -y install python3-pip
pip3 install flask
pip3 install mattermostdriver
pip3 install -U PyYAML
pip3 install numpy
pip3 install pandas
pip3 install matplotlib
pip3 install seaborn
pip3 install mockito

PlotBot

  • This bot provides users with correct function and libraries from Seaborn through sample source code.
  • The user can also test the correctness of the plot by visualizing their data input on the plot generated by the bot.
  • The types of plots the bot can plot are:
    • Line graph
    • Histogram
    • Scatterplot
    • Box-plot
    • Bar chart with facets

USECASES

Below are refined use cases for PlotBot

Use Case 1: Give the user with code snippet for the required type of graph.

1 Preconditions
   User must have mattermost account.

2 Main Flow
  User provides the bot with the type of graph it requires [S1].
  Bot responds with a code snippet of the Seaborn library of that particular graph type[S2].
  Bot also returns a sample graph for user to visualize the data[S3].

3 Subflows
  [S1] User calls bot by a "sample" command and the graph type @graph_type. e.g. Histogram
  [S2] Bot returns a code snippet.
  [S3] Bot also returns a sample graph for the @graph type
  
4 Alternative Flows
  [E1] Requested graph type not available to plot.

Use Case2: Plot the graph for the user with their custom data.

1 Preconditions
   User must have mattermost account.
   User must give the data in the format required by the bot.

2 Main Flow
   User requests bot to generate a graph of a type for their data [S1].
   User uploads the data in that particular format with labels[S2].
   User also provides the labels, features it wants in the graph in a particular format[S3]
   Bot generates the graph and returns it to the user [S4].

3 Subflows
  [S1] User gives a "plot" command with @graph_type, ex. Scatterplot.
  [S2] User uploads data on MatterMost in a particular format, ex. csv
  [S3] User provides with X, Y labels as asked by the Bot
  [S4] Bot returns the generated graph.

4 Alternative Flows
  [E1] Incorrect data format. Requested data format to be provided
  [E2] Requested graph type not available.

Use Case3: Provide user with the ability to view all his plots.

1 Preconditions
   User must have mattermost account.

2 Main Flow
   User requests to provide all his plotted graphs using this bot[S1]
   User can also request the bot to provide with specific graphs within a time frame[S2]
   Bot returns the graphs according to the requirements

3 Subflows
  [S1] User asks the bot with a "retrieve" command to give all the plotted graphs.
  [S2] User can mention the name of the specific graph or the graphs between two Dates, ex. From DD/MM/YY to DD/MM/YY
  [S3] Bot will return the files according to the requirements

4 Alternative Flows
  [E1] No plots available.
  [E2] Incorrect data format

BOT IMPLEMENTATION

Bot Platform:

AWS instance creation, instance1 mattermost server - Deployable We created AWS instance for mattermost server. To make our bot independent of the server location of mattermost, we created another instance for out bot on AWS. Our bot is deployable and only requires a bot account token called PLOT_BOT_TOKEN from user after they make an account on MatterMost

Bot Integration:

The bot is integrated in a Flask framework which gets activated on certain trigger-words.

Flask Framework This python based application was used to make HTTP requests. The outgoing webhooks created on Mattermost were integrated with the responder functions of our basic chatbot.

Trigger words corresponding to different tasks

Run Commands: @plotbot - Activates the PlotBot sample - Covers usecase 1 plot - Covers usecase 2 retrieve - Covers usecase3

Example Usecase

@plotbot Hey!
sample [boxplot/scatterplot/barplot]
plot [scatterplot/boxplot/barplot] "iris.csv(upload file on Matternost)"
retrieve from:05/06/2018 to:08/07/2019 OR can be a particular file name the use wants(say iris.csv)

Puppeteer Testing

To test and automate our BOT, we used Pupeteer Node library for testing responses on headless Chromium. In order to run the tests:

  • Do npm install
  • Export your MATTERMOST_EMAIL and MATTERMOST_PWD
  • Do npm test. We add a total of 8 Test Cases covering our use cases.
  • Below we have shown code snippets for happy flows of our usecases and a screenshot of all testcases(happy and alternate flows) passing is provided.
Use Case 0: Basic conversation on @plotbot trigger
  it('It should greet back', async () => {
        var list = [,]

        await page.waitForSelector('#post_textbox');
        await page.focus('#post_textbox')
        await page.keyboard.type( "@plotbot hi" );
        await page.keyboard.press('Enter');
        let promise = new Promise((res, rej) => {
          setTimeout(() => res("Waiting for the Response!"), 10000)
        });
        let waiting = await promise;
        await page.waitForSelector('.post__body');
        const output = await page.evaluate(() => Array.from(
          document.getElementsByClassName('post__body'), e => e.innerText));
        var result = output[output.length-1];
        expect(result).to.match(/^Hi*/);

        await browser.close();
    });

Use Case 1: Bot provides sample code and graph when user requests
  it('Happy flow when users asks for sample scatter plot', async () => {
        await page.waitForSelector('#post_textbox');
        await page.focus('#post_textbox')
        await page.keyboard.type( "sample scatterplot" );
        await page.keyboard.press('Enter');
        let promise = new Promise((res, rej) => {
          setTimeout(() => res("Waiting for the Response!"), 5000)
        });
        let waiting = await promise;
        await page.waitForSelector('.post__body');
        const output = await page.evaluate(() => Array.from(
          document.getElementsByClassName('post__body'), e => e.innerText));
        var result = output[output.length-1];
        expect(result).to.match(/scatterplot_code\.png\n.*\nscatterplot_graph\.png/);

        await browser.close();
    });

Use Case 2: Bot plots a graph when user requests and provides dataset
it('Happy flow when user asks to plot a graph by giving dataset', async () => {
        await page.waitForSelector('#post_textbox');
        await page.focus('#post_textbox')
        await page.keyboard.type( "plot scatterplot" );

        const example = await page.$('#fileUploadButton');
        const attach = await page.evaluateHandle(el => el.nextElementSibling, example);
        await attach.uploadFile('test/dataset.csv')
        let promise1 = new Promise((res, rej) => {
          setTimeout(() => res("Waiting for the Response!"), 5000)
        });
        let waiting1 = await promise1;

        await page.keyboard.press('Enter');
        let promise = new Promise((res, rej) => {
          setTimeout(() => res("Waiting for the Response!"), 5000)
        });
        let waiting = await promise;

        await page.waitForSelector('.post__body');
        const output = await page.evaluate(() => Array.from(
          document.getElementsByClassName('post__body'), e => e.innerText));
        var result = output[output.length-1];
        expect(result).to.match(/\.png/);

        await browser.close();
    });

Use Case 3: Bot gives all the user plotted plots during a time period when user requests
it('Happy flow when user requests for his graphs plotted during a time period', async () => {
        await page.waitForSelector('#post_textbox');
        await page.focus('#post_textbox')
        await page.keyboard.type( "retrieve from:2019-10-19 13:0:0.0 to:2019-10-19 14:0:0.0" );
        await page.keyboard.press('Enter');
        let promise = new Promise((res, rej) => {
          setTimeout(() => res("Waiting for the Response!"), 5000)
        });
        let waiting = await promise;
        await page.waitForSelector('.post__body');
        const output = await page.evaluate(() => Array.from(
          document.getElementsByClassName('post__body'), e => e.innerText));
        var result = output[output.length-1];
        expect(result).to.match(/\.png/);

        await browser.close();
    });

The following screenshot shows that all testcases for happy and alternate flows for each use case pass.

Image all the testcases passing

Mocking Service Component

We implemented mock services for each use case and data to support service integration. The code for mock data is in, framework/mocking_agent For services' integration and end-to-end work-flows, we have mocked up responses to services' requests at following points.

Mock graphs are generated (from seaborn's built in dataset) and stored locally at begening to emulate DataBase of graphs.

Usecase Services required service API Mocked up mocking API
1 Provide code snippet for a type of plot service. sampler. retrieve_snippet Returns basic code snippet from local database mocking_agent. responseSnippet[plotType]
1 Provide graph snippet service. sampler. retrieve_snippet Returns basic snippet of graph from local database mocking_agent. responseSnippet[plotType]
2 For given data (dataset), generate plot service. plotter. load_dataset Uses seaborn built-in data set to plot mocking_agent. responseDataSet [plotType]
2 For given data (dataset), plot on particular variable service. plotter. fetchAxisInfo Uses axes info from seaborn built-in dataset to plot mocking_agent. responseAxisInfo[ plotType]
3 Retrieve particular plots from database service. retrieval. fetchplotfromDB Fetches a graph at random from mock graphs mocking_agent. responseRetrieve['plot']
3 Retrieve graphs from a particular time interval service. retrieval. fetchplotfromDBtimed Fetches a set of graphs at random from mock graphs mocking_agent. responseRetrieve['datetime']

Screencast

Link to screencast