DEV Community

Alex Romanova
Alex Romanova

Posted on

About testing in Go

This post will be about my pull request that did some tests with Go.

Here's some backstory about why I chose this repo. I've been contributing to 7tv, but I'm also a member of their discord community. There I noticed a project that uses 7tv that was also written in Go. A small project from someone in the same community - likely to explain stuff and help out, shouldn't be too difficult of an app.

So I reached out. You can look at my previous post how that went. Long story short, I decided to try my newly acquired knowledge of testing in a different language. The one I'm really interested in - GO.

How to test?

I researched some basic stuff, official documentation got me started.

Some specific things I noticed:

  • To make a test file, you have to name it NAME_test.go, instead of NAME.test.js compared to JS.
  • Go has a built in testing package, which makes it simple and universal for any GO unit testing.
  • The most useful resource I found is (Go by example)[https://gobyexample.com/testing]. Really shows all you need to begin and make it work. Was even easier than JS, honestly. The table example was really useful too.

What I did

I followed author's advice and made tests for humanize. Those functions have simple string/int input and output. I was happy with how fast I figured things out.

I really a system of testing tables, it looks clean and structured.

You can see that I created variables in my test for arguments and the return value I expect. Then I made a table with those variables united in a single object. That way you can later loop through them and check if that combination works together.

Here's some more code.

  • Function to test:
func StringToSeconds(s string) (int, error) {
    if strings.HasSuffix(s, "m") {
        num := strings.TrimSuffix(s, "m")
        integer, err := strconv.Atoi(num)

        return integer * 60, err
    }

    if strings.HasSuffix(s, "s") {
        num := strings.TrimSuffix(s, "s")
        integer, err := strconv.Atoi(num)

        return integer, err
    }

    integer, err := strconv.Atoi(s)

    return integer, err
}
Enter fullscreen mode Exit fullscreen mode
  • The testing function itself:
func TestStringToSeconds(t *testing.T) {
    var tests = []struct {
        str string
        want int
    }{
        {"60s", 60},
        {"1m", 60},
        {"60m", 3600},//Big example
        {"22s", 22},//Basic example
        {"", 0},//Empty string
        {"10d", 0},//Invalid input
    }

    for _, tt := range tests{
        testname:=fmt.Sprintf("%s", tt.str)
        t.Run(testname, func(t *testing.T) {
            ans, err:=StringToSeconds(tt.str)
            if ans != tt.want {
                fmt.Printf("%s",err)
                t.Errorf("Got %d, want %d", ans, tt.want)
            }
        })
    }
}
Enter fullscreen mode Exit fullscreen mode

There was finally something I could fix through my testing. I figured out that when this following function returns a value with combined units (minutes and seconds), it returns it in a float format, adding a bunch of .000000. Not only it looked bad, it also wasn't consistent with other return values which were ints.

func SecondsToString(s int) string {
    if s < 60 {
        return fmt.Sprintf("%ds", s)
    }
    if s%60 == 0 {
        return fmt.Sprintf("%dm", s/60)
    }

    floored := math.Floor(float64(s) / 60)
    rest := float64(s) - (floored * 60)

    return fmt.Sprintf("%fm %fs", floored, rest)
}
Enter fullscreen mode Exit fullscreen mode

This is how it would look with combined values:

So I actually changed something in the original code to match the format!

...
    floored := int(math.Floor(float64(s) / 60))
    rest := int(float64(s)) - (floored * 60)

    return fmt.Sprintf("%dm %ds", floored, rest)
}
Enter fullscreen mode Exit fullscreen mode

Next level: Mocks?

I was content with myself. I did tests that actually worked. Maybe I can make tests for something more difficult?

So my next quest: How do I mock in go? I went to google. There was a problem. I couldn't find a clear and solid answer. So I went on to ask people who might know.

He showed me his repo where he made a bunch of tests, however I couldn't figure it out. So I went in voice to see what he'll explain..

What he showed was.. a lot. Fast. I couldn't follow. He'd jump from document to document, adding in words I didn't know, and I was really too confused to even form a question. Basically...

And then he went on to build his new chair that apparently had wrong instructions.

So I decided I'll postpone my learning about mocks in Go. After all, I had enough to make a PR where things didn't break yet. I still learned new things. Good enough for me.

YAY I DID SOMETHING NEW IN GO

Top comments (0)