Giter Club home page Giter Club logo

slack-test's Introduction

slacktest

Build Status

This is a very basic golang library for testing your slack RTM chatbots

Depending on your mechanism for building slackbots in go and how broken out your message parsing logic is, you can normally test that part pretty cleanly. However testing your bots RESPONSES are a bit harder.

This library attempts to make that a tad bit easier but in a slightly opinionated way.

The current most popular slack library for golang is nlopes/slack. Conviently the author has made overriding the slack API endpoint a feature. This allows us to use our fake slack server to inspect the chat process.

Limitations

Right now the test server is VERY limited. It currently handles the following API endpoints

  • rtm.start
  • chat.postMessage
  • channels.list
  • groups.list
  • users.info
  • bots.info

Additional endpoints are welcome.

Example usage

You can see an example in the examples directory of how to you might test it

If you just want to play around:

package main

import (
    "log"
    slacktest "github.com/lusis/slack-test"
    slackbot "github.com/lusis/go-slackbot"
    slack "github.com/nlopes/slack"
)

func globalMessageHandler(ctx context.Context, bot *slackbot.Bot, evt *slack.MessageEvent) {
    bot.Reply(evt, "I see your message", slackbot.WithoutTyping)
}

func main() {
    // Setup our test server
    s := slacktest.NewTestServer()
    // Set a custom name for our bot
    s.SetBotName("MyBotName")
    // ensure that anything using the slack api library uses our custom server
    slack.SLACK_API = "http://" + s.ServerAddr + "/"
    // start the test server
    go s.Start()
    // create a new slackbot. Token is irrelevant here
    bot := slackbot.New("ABCEDFG")
    // add a message handler
    bot.Hear("this is a channel message").MessageHandler(globalMessageHandler)
    // start the bot
    go bot.Run()
    //send a message to a channel
    s.SendMessageToChannel("#random", "this is a channel message")
    for m := range s.SeenFeed {
        log.Printf("saw message in slack: %s", m)
    }
}

Output:

# go run main.go
2017/09/26 10:53:49 {"type":"message","channel":"#random","text":"this is a channel message","ts":"1506437629","pinned_to":null}
2017/09/26 10:53:49 {"id":1,"channel":"#random","text":"I see your message","type":"message"}
#

You can see that our bot handled the message correctly.

Usage in tests

Currently it's not as ergonomic as I'd like. So much depends on how modular your bot code is in being able to run the same message handling code against a test instance. In the examples directory there are a couple of test cases.

Additionally, you definitely need to call time.Sleep for now in your test code to give time for the messages to work through the various channels and populate. I'd like to add a safer subscription mechanism in the future with a proper timeout mechanism.

If you want to, you can test the existing example in examples/go-slackbot:

# cd examples/go-slackbot
# go test -v
=== RUN   TestGlobalMessageHandler
--- PASS: TestGlobalMessageHandler (2.00s)
=== RUN   TestHelloMessageHandler
--- PASS: TestHelloMessageHandler (2.00s)
PASS
ok      github.com/lusis/slack-test/examples/go-slackbot        4.005s
#

testing an actual RTM session

This gets tricky. You can look at the existing rtm_test.go but here's a documented example:

package foo
import (
    "testing"
    "time"
    "github.com/nlopes/slack"
    "github.com/stretchr/testify/assert"
)

func TestRTMDirectMessage(t *testing.T) {
    // Let's skip this when we want short/quick tests
    if testing.Short() {
        t.Skip("skipping timered test")
    }
    // how long should we wait for this test to finish?
    maxWait := 5 * time.Second
    // start our test server
    s := NewTestServer()
    go s.Start()
    // set our slack API to the mock server
    slack.SLACK_API = s.GetAPIURL()
    api := slack.New("ABCDEFG")
    // rtm instance
    rtm := api.NewRTM()
    go rtm.ManageConnection()
    // create a channel to pass our results from the next goroutine
    // that is a goroutine doing the normal range over rtm.IncomingEvents
    messageChan := make(chan (*slack.MessageEvent), 1)
    go func() {
        for msg := range rtm.IncomingEvents {
            switch ev := msg.Data.(type) {
            case *slack.MessageEvent:
                messageChan <- ev
            }
        }
    }()
    // since we want to test direct messages, let's send one to the bot
    s.SendDirectMessageToBot(t.Name())
    // now we block this test
    select {
    // if we get a slack.MessageEvent, perform some assertions
    case m := <-messageChan:
        assert.Equal(t, "D024BE91L", m.Channel)
        assert.Equal(t, t.Name(), m.Text)
        break
    // if we hit our timeout, fail the test
    case <-time.After(maxWait):
        assert.FailNow(t, "did not get direct message in time")
    }
}

slack-test's People

Contributors

lusis avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.