Testing Basics

Back

Loading concept...

πŸ§ͺ Go Testing: Your Code’s Safety Net

Imagine you’re a chef about to serve a dish. Before sending it out, you taste it first β€” that’s testing! In Go, testing is like having a team of taste-testers who check your code before it goes live.


🎯 The Big Picture

Testing in Go is built right in. No extra tools needed. It’s like Go comes with a recipe-tester included!

Our Analogy: Think of your code as a toy factory. Every toy (function) needs quality control (testing) before it leaves the factory. The testing package is your quality control team.


πŸ“¦ Meet testing.T β€” Your Test Helper

testing.T is like your clipboard-holding inspector. It helps you:

  • Report problems ❌
  • Log messages πŸ“
  • Mark tests as failed or passed βœ…
func TestAdd(t *testing.T) {
    result := Add(2, 3)
    if result != 5 {
        t.Errorf("Got %d, want 5", result)
    }
}

Key Methods of testing.T

Method What It Does
t.Error() Reports failure, keeps going
t.Errorf() Like Error, but with formatting
t.Fatal() Reports failure, STOPS test
t.Log() Prints a message
t.Skip() Skips the test

🎨 Test Patterns β€” The Right Way to Test

Pattern 1: Table-Driven Tests

Instead of writing 10 similar tests, put all cases in a table!

func TestMultiply(t *testing.T) {
    tests := []struct {
        a, b, want int
    }{
        {2, 3, 6},
        {0, 5, 0},
        {-1, 4, -4},
    }

    for _, tt := range tests {
        got := Multiply(tt.a, tt.b)
        if got != tt.want {
            t.Errorf("Multiply(%d,%d) = %d; want %d",
                tt.a, tt.b, got, tt.want)
        }
    }
}

Why? One test function, many cases. Clean and easy to add more!

Pattern 2: Subtests with t.Run()

Give each case a name β€” makes debugging easier!

func TestDivide(t *testing.T) {
    tests := map[string]struct {
        a, b, want int
    }{
        "positive": {10, 2, 5},
        "negative": {-10, 2, -5},
    }

    for name, tt := range tests {
        t.Run(name, func(t *testing.T) {
            got := Divide(tt.a, tt.b)
            if got != tt.want {
                t.Errorf("got %d, want %d", got, tt.want)
            }
        })
    }
}

⚑ Parallel Tests β€” Speed Things Up!

Want tests to run at the same time? Use t.Parallel()!

func TestSlowOperation(t *testing.T) {
    t.Parallel() // This test can run alongside others

    result := SlowOperation()
    if result != expected {
        t.Error("Failed!")
    }
}
graph TD A["Start Tests"] --> B["Test A"] A --> C["Test B"] A --> D["Test C"] B --> E["All Done!"] C --> E D --> E

⚠️ Warning: Parallel tests should NOT share data that changes!


πŸš€ The go test Command

Your magic spell to run tests!

Basic Commands

# Run all tests in current folder
go test

# Run with details (verbose)
go test -v

# Run a specific test
go test -run TestAdd

# Run tests in all subfolders
go test ./...

Helpful Flags

Flag What It Does
-v Show all test names and output
-run Name Run only matching tests
-count=1 Disable test caching
-timeout 30s Set max time for tests
-short Skip long-running tests

πŸ“Š Test Coverage β€” Did You Test Everything?

Coverage tells you: What percentage of your code has tests?

# See coverage percentage
go test -cover

# Generate detailed report
go test -coverprofile=coverage.out
go tool cover -html=coverage.out

Output example:

PASS
coverage: 85.7% of statements
graph TD A["Your Code"] --> B{Tested?} B -->|Yes| C["βœ… Covered"] B -->|No| D["❌ Not Covered"] C --> E["85% Coverage"] D --> E

Goal: Aim for 80%+ coverage, but 100% isn’t always needed!


⏱️ Benchmark Tests β€” How Fast Is Your Code?

Benchmarks measure speed and memory usage.

Meet testing.B

Just like testing.T is for tests, testing.B is for benchmarks!

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

The magic b.N: Go automatically finds the right number of iterations!

Running Benchmarks

# Run all benchmarks
go test -bench=.

# Run with memory stats
go test -bench=. -benchmem

Output example:

BenchmarkAdd-8   1000000000   0.29 ns/op   0 B/op   0 allocs/op
Part Meaning
1000000000 Iterations run
0.29 ns/op Time per operation
0 B/op Memory per operation
0 allocs/op Memory allocations

Key testing.B Methods

Method What It Does
b.ResetTimer() Restart the clock (after setup)
b.StopTimer() Pause timing
b.StartTimer() Resume timing
b.ReportAllocs() Include memory stats
func BenchmarkWithSetup(b *testing.B) {
    // Setup (not timed)
    data := prepareData()

    b.ResetTimer() // Start timing NOW

    for i := 0; i < b.N; i++ {
        ProcessData(data)
    }
}

πŸ“š Example Tests β€” Documentation That Tests Itself!

Example tests show how to use your code AND verify it works!

func ExampleAdd() {
    result := Add(2, 3)
    fmt.Println(result)
    // Output: 5
}

Magic: The // Output: comment tells Go what to expect!

Rules for Example Tests

  1. Function name starts with Example
  2. Must have // Output: comment
  3. Uses fmt.Println to show results
func ExampleGreet() {
    message := Greet("World")
    fmt.Println(message)
    // Output: Hello, World!
}

func ExampleCalculator_Add() {
    calc := NewCalculator()
    fmt.Println(calc.Add(1, 2))
    // Output: 3
}

Unordered Output

When order doesn’t matter:

func ExampleGetColors() {
    colors := GetColors()
    for _, c := range colors {
        fmt.Println(c)
    }
    // Unordered output:
    // red
    // blue
    // green
}

πŸ—ΊοΈ The Complete Testing Picture

graph TD A["Write Code"] --> B["Write Tests"] B --> C["go test"] C --> D{Pass?} D -->|No| E["Fix Code"] E --> C D -->|Yes| F["Check Coverage"] F --> G["Run Benchmarks"] G --> H["βœ… Ship It!"]

🎁 Quick Reference

Task Command/Code
Run tests go test
Verbose output go test -v
Check coverage go test -cover
Run benchmarks go test -bench=.
Run specific test go test -run TestName
Create test file *_test.go
Test function func TestXxx(t *testing.T)
Benchmark function func BenchmarkXxx(b *testing.B)
Example function func ExampleXxx()

🌟 You Did It!

Now you know:

  • βœ… How testing.T helps report test results
  • βœ… Table-driven tests and subtests patterns
  • βœ… Running tests in parallel with t.Parallel()
  • βœ… All the go test command tricks
  • βœ… Measuring code coverage
  • βœ… Writing benchmarks with testing.B
  • βœ… Creating self-documenting example tests

Your code is now protected by its very own quality control team! 🏭✨

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.