JS
GO

JavaScript to Go

10 lessons

Progress0%
1Variables & Types2Functions3Objects → Structs4Async → Goroutines5Errors & Panic6Interfaces7Slices and Maps8Packages and Modules9Testing10Standard Library
All Mirror Courses
JS
GO
Testing
MirrorLesson 9 of 10
Lesson 9

Testing

Go's built-in testing package and table-driven tests

Introduction

In this lesson, you'll learn about testing in Go. Coming from JavaScript, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
JS
From JavaScript:

In JavaScript, you're familiar with go's built-in testing package and table-driven tests.

GO
In Go:

Go has its own approach to go's built-in testing package and table-driven tests, which we'll explore step by step.

The Go Way

Let's see how Go handles this concept. Here's a typical example:

GO
Go Example
// math_test.go (same package, _test.go suffix)
package math

import "testing"

func TestAdd(t *testing.T) {
    if got := Add(1, 2); got != 3 {
        t.Errorf("Add(1,2) = %d; want 3", got)
    }
}

// Table-driven test (idiomatic Go)
func TestDivide(t *testing.T) {
    tests := []struct {
        name    string
        a, b    float64
        want    float64
        wantErr bool
    }{
        {"normal", 6, 3, 2, false},
        {"zero dividend", 0, 5, 0, false},
        {"divide by zero", 1, 0, 0, true},
    }

    for _, tc := range tests {
        t.Run(tc.name, func(t *testing.T) {
            got, err := Divide(tc.a, tc.b)
            if tc.wantErr {
                if err == nil { t.Error("expected error, got nil") }
                return
            }
            if err != nil { t.Fatalf("unexpected error: %v", err) }
            if got != tc.want { t.Errorf("got %v; want %v", got, tc.want) }
        })
    }
}

// Benchmark
func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(1, 2)
    }
}

// Run: go test ./...
// Run with coverage: go test -cover ./...
// Run benchmark: go test -bench=. ./...

Comparing to JavaScript

Here's how you might have written similar code in JavaScript:

JS
JavaScript (What you know)
// math.test.js
import { add, divide } from "./math";

describe("math", () => {
  test("add returns sum", () => {
    expect(add(1, 2)).toBe(3);
    expect(add(-1, 1)).toBe(0);
  });

  test.each([
    [2, 1, 2],
    [6, 3, 2],
    [0, 5, 0],
  ])("divide(%i, %i) = %i", (a, b, expected) => {
    expect(divide(a, b)).toBe(expected);
  });

  test("divide by zero throws", () => {
    expect(() => divide(1, 0)).toThrow("division by zero");
  });
});

// Run: npx jest
Mirror Card
JS
From JavaScript:

You may be used to different syntax or behavior.

GO
In Go:

Test files end in _test.go; test functions are TestXxx(t *testing.T)

Mirror Card
JS
From JavaScript:

You may be used to different syntax or behavior.

GO
In Go:

No test runner framework needed — 'go test' is built into the toolchain

Mirror Card
JS
From JavaScript:

You may be used to different syntax or behavior.

GO
In Go:

t.Run() creates sub-tests; table-driven tests are idiomatic Go

Mirror Card
JS
From JavaScript:

You may be used to different syntax or behavior.

GO
In Go:

t.Error/Errorf continues the test; t.Fatal/Fatalf stops immediately

Mirror Card
JS
From JavaScript:

You may be used to different syntax or behavior.

GO
In Go:

Benchmarks are BenchmarkXxx(b *testing.B); run with -bench flag

Step-by-Step Breakdown

1. Test File Convention

Go test files end in _test.go and live in the same package (or package_test for black-box testing). No separate test runner needed.

JS
JavaScript
// math.test.js — external file, Jest runner
GO
Go
// math_test.go — same directory as math.go
package math  // or: package math_test for black-box

import "testing"

2. Table-Driven Tests

Table-driven tests are the Go idiom for parametrized tests. Define test cases in a slice of structs, then loop with t.Run().

JS
JavaScript
test.each([[1,2,3],[4,5,9]])("add",([a,b,c])=>expect(add(a,b)).toBe(c))
GO
Go
tests := []struct{ a,b,want int }{
    {1,2,3}, {4,5,9},
}
for _, tc := range tests {
    t.Run(fmt.Sprintf("%d+%d",tc.a,tc.b), func(t *testing.T){
        if got := Add(tc.a,tc.b); got != tc.want {
            t.Errorf("got %d; want %d", got, tc.want)
        }
    })
}

3. Error vs Fatal

t.Error marks a test failed but continues. t.Fatal marks failed and stops. Use Fatal when subsequent assertions would be meaningless after failure.

JS
JavaScript
expect(result).toBe(expected); // Jest stops on first failure
GO
Go
result, err := DoThing()
if err != nil { t.Fatalf("DoThing failed: %v", err) } // stop here
if result != expected { t.Errorf("got %v; want %v", result, expected) }

4. Benchmarks

Benchmark functions let you measure performance. The testing framework adjusts b.N to get stable results.

JS
JavaScript
// No built-in benchmark in Jest; use console.time or benchmark.js
GO
Go
func BenchmarkSort(b *testing.B) {
    data := generateData()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        sort.Ints(data)
    }
}
// go test -bench=BenchmarkSort -benchmem
Rule of Thumb
Call b.ResetTimer() after expensive setup so setup time isn't counted in the benchmark.

Common Mistakes

When coming from JavaScript, developers often make these mistakes:

  • Test files end in _test.go; test functions are TestXxx(t *testing.T)
  • No test runner framework needed — 'go test' is built into the toolchain
  • t.Run() creates sub-tests; table-driven tests are idiomatic Go
Common Pitfall
Don't assume Go works exactly like JavaScript. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • Test files end in _test.go; functions are TestXxx(t *testing.T) — no framework needed
  • Table-driven tests: slice of structs + range + t.Run() is the Go idiom
  • t.Error continues after failure; t.Fatal stops — use Fatal when remaining checks are meaningless
  • go test -cover shows coverage; -bench runs benchmarks; -run=TestName filters tests
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your JavaScript code in Go to practice these concepts.
PreviousNext