Tag Archives: testing

Testing concurrent code in Golang

I wrote a package which tracks certain hashtags on twitter and part of the package is adding and removing hashtag from list of hashtags. Plan is that this can be done from different goroutines hence tracking/untracking is done by putting hashtag in channels. It looks like this:

var (
    trackChan   = make(chan string)
    untrackChan = make(chan string)
)

func Track(hs ...string) {
    for _, h := range hs {
        trackChan <- h
    }
}

func Untrack(hs ...string) {
    for _, h := range hs {
        untrackChan <- h
    }
}

var hashtags []string

func init() {
    go func() {
        for {
            select {
            case h := <-trackChan:
                if !sliceContains(h, hashtags) {
                    hashtags = append(hashtags, h)
                }
            case h := <-untrackChan:
                if sliceContains(h, hashtags) {
                    hashtags = sliceRemove(h, hashtags)
                }
            }
        }
    }()
}

sliceContains and sliceRemove are (probably) self-explanatory helper functions.

Since I write tests for my code I wrote three tests for this part: for track, untrack and combined scenario. At first you may write tests like this:

func TestTrack(t *testing.T) {
    h := "name"
    Track(h)
    assert.Contains(t, hashtags, h)
}

func TestUntrack(t *testing.T) {
    name := "name"
    hashtags = []string{name, "surname"}
    Untrack(name)
    assert.NotContains(t, hashtags, name)
}

func TestTrackUntrack(t *testing.T) {
    h := "name"

    Track(h)
    Untrack(h)

    assert.NotContains(t, hashtags, h)
}

But tests are not working! The main problem here is that we are dealing with concurrent code where we don't know when commands will finish with execution (concretely when slice hashtags will be updated).

Testing concurrent code in Go turns out to be easier after watching Testing Techniques by Andrew Gerrand.

Main idea here is inserting empty function (no-op) after interesting code which acts as a hook for testing purposes. In testing this function will push a value into the channel which was created in test. We receive this value in test code where we want to ensure that some logic is executed (basically blocking the code till something is executed).

So the solution to the above problem was defining empty function (e.g. doneFunc) and calling it after update to hashtags slice. And than in test creating a channel (e.g. doneChan) and redefining doneFunc so that a value is pushed to doneChan. ((It doesn't matter what value. Boolean is perfectly OK, but even better is an empty struct since it takes 0 bytes - boolean takes 1 byte.)). As a good practice at the end of the test we restore doneFunc to empty function.

Updated code:

var (
    trackChan   = make(chan string)
    untrackChan = make(chan string)
    doneFunc    = func() {}
)

func Track(hs ...string) {
    for _, h := range hs {
        trackChan <- h
    }
}

func Untrack(hs ...string) {
    for _, h := range hs {
        untrackChan <- h
    }
}

var hashtags []string

func init() {
    go func() {
        for {
            select {
            case h := <-trackChan:
                if !sliceContains(h, hashtags) {
                    hashtags = append(hashtags, h)
                    doneFunc()
                }
            case h := <-untrackChan:
                if sliceContains(h, hashtags) {
                    hashtags = sliceRemove(h, hashtags)
                    doneFunc()
                }
            }
        }
    }()
}

Updated tests:

func TestTrack(t *testing.T) {
    doneChan := make(chan struct{}, 1)
    doneFunc = func() { doneChan <- struct{}{} }
    defer func() {
        doneFunc = func() {}
    }()

    h := "name"

    Track(h)
    <-doneChan

    assert.Contains(t, hashtags, h)
}

func TestUntrack(t *testing.T) {
    doneChan := make(chan struct{}, 1)
    doneFunc = func() { doneChan <- struct{}{} }
    defer func() {
        doneFunc = func() {}
    }()

    name := "name"
    hashtags = []string{name, "surname"}

    Untrack(name)
    <-doneChan

    assert.NotContains(t, hashtags, name)
}

func TestTrackUntrack(t *testing.T) {
    doneChan := make(chan struct{}, 1)
    doneFunc = func() {
        doneChan <- struct{}{}
    }
    defer func() {
        doneFunc = func() {}
    }()
    h := "name"

    Track(h)
    <-doneChan
    Untrack(h)
    <-doneChan

    assert.NotContains(t, hashtags, h)
}

Testing React components

There are two aspect of testing React components: testing their structure (desired markup is displayed) and behaviour (e.g. when clicking on a button this function will be called or something different will appear in component’s markup).

Testing component structure is best done with shallow rendering since it renders only provided component and not its potential sub-components. It only renders one level deep. Unfortunately it doesn’t work with testing behaviour especially if you are using refs.

For testing component’s behaviour you need to render component in a different way and also DOM needs to be present. DOM can be real or emulated. You get a real DOM with running your tests with browser test runners like karma (which opens a browser and runs test suits in it) and fake with libraries like jsdom or domino. The way to go is with real DOM since with fake DOM you don’t account for browser differences. But fake DOM is quicker solution because setting right configuration for karma isn’t quite straightforward and waiting for browser to open and close also takes more time.

I noticed stateless components doesn’t work with latter method. But there is hack for this and requires you to wrap the stateless component with normal component (output of stateless component goes to render method).

You should always strive to test component in isolation. The way how I do it most of the time is passing all variables and callbacks to component via props so while testing I can create fake callbacks (spies) and assert they have been called when specific event has occurred.

I use Mocha for my test runner and my assertion library of choice is unexpected with unexpected-react which simplifies asserting that component’s JSX is presented in rendered component. Previously I used expect with expect-jsx but it is not as powerful since component’s output is simply converted into string. With unexpected-react you can leave tags’ className and children out and still get a green test. On the other side expect also comes with methods for creating spies and stubs while with unexpected you have to rely on external library for doing that (like sinon).

All necessary methods for rendering, simulating event and finding elements in rendered component are provided by React team in form of react-addons-test-utils package.

Testing React components personally took quite a time to figure it out and to get comfortable with it but now I’m practising it and improving my testing techniques almost on daily basis and it’s fun.