typetui 0.2.1

A terminal-based typing test.
Documentation
package main

import (
    "errors"
    "fmt"
    "testing"
    "time"
)

func Add(a, b int) int {
    return a + b
}

func Divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}

type Calculator struct {
    operations int
}

func (c *Calculator) Add(a, b int) int {
    c.operations++
    return a + b
}

func (c *Calculator) GetOperations() int {
    return c.operations
}

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

func TestDivide(t *testing.T) {
    tests := []struct {
        name     string
        a, b     float64
        expected float64
        wantErr  bool
    }{
        {"valid division", 10, 2, 5, false},
        {"division by zero", 10, 0, 0, true},
        {"decimal result", 7, 2, 3.5, false},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result, err := Divide(tt.a, tt.b)
            if (err != nil) != tt.wantErr {
                t.Errorf("Divide() error = %v, wantErr %v", err, tt.wantErr)
                return
            }
            if !tt.wantErr && result != tt.expected {
                t.Errorf("Divide() = %v, want %v", result, tt.expected)
            }
        })
    }
}

func TestCalculator(t *testing.T) {
    calc := &Calculator{}

    result := calc.Add(5, 3)
    if result != 8 {
        t.Errorf("Add(5, 3) = %d; want 8", result)
    }

    if calc.GetOperations() != 1 {
        t.Errorf("Operations = %d; want 1", calc.GetOperations())
    }
}

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

func BenchmarkCalculator(b *testing.B) {
    calc := &Calculator{}
    b.ResetTimer()

    for i := 0; i < b.N; i++ {
        calc.Add(i, i+1)
    }
}

func ExampleAdd() {
    fmt.Println(Add(2, 3))
}

func FuzzAdd(f *testing.F) {
    f.Add(1, 2)
    f.Add(0, 0)
    f.Add(-5, 10)

    f.Fuzz(func(t *testing.T, a, b int) {
        result := Add(a, b)
        expected := a + b
        if result != expected {
            t.Errorf("Add(%d, %d) = %d; want %d", a, b, result, expected)
        }
    })
}

type MockDatabase struct {
    data map[string]string
}

func NewMockDatabase() *MockDatabase {
    return &MockDatabase{
        data: make(map[string]string),
    }
}

func (m *MockDatabase) Get(key string) (string, bool) {
    val, ok := m.data[key]
    return val, ok
}

func (m *MockDatabase) Set(key, value string) {
    m.data[key] = value
}

type Service struct {
    db Database
}

type Database interface {
    Get(string) (string, bool)
    Set(string, string)
}

func NewService(db Database) *Service {
    return &Service{db: db}
}

func (s *Service) GetUser(id string) (string, bool) {
    return s.db.Get("user:" + id)
}

func TestServiceWithMock(t *testing.T) {
    mock := NewMockDatabase()
    mock.Set("user:1", "Alice")

    service := NewService(mock)

    user, ok := service.GetUser("1")
    if !ok {
        t.Error("Expected user to exist")
    }
    if user != "Alice" {
        t.Errorf("Expected Alice, got %s", user)
    }
}

func TestWithTimeout(t *testing.T) {
    done := make(chan bool)

    go func() {
        time.Sleep(100 * time.Millisecond)
        done <- true
    }()

    select {
    case <-done:
    case <-time.After(1 * time.Second):
        t.Error("Test timed out")
    }
}

func TestParallel(t *testing.T) {
    tests := []struct {
        name string
        a, b int
        want int
    }{
        {"small", 1, 2, 3},
        {"medium", 10, 20, 30},
        {"large", 100, 200, 300},
    }

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

func TestCleanup(t *testing.T) {
    resource := "opened"

    t.Cleanup(func() {
        resource = "closed"
        t.Log("Resource cleaned up")
    })

    t.Logf("Resource is %s", resource)
}

func TestSkip(t *testing.T) {
    if testing.Short() {
        t.Skip("Skipping in short mode")
    }

    t.Log("This test only runs when -short is not set")
}

func main() {
    fmt.Println("Run tests with: go test -v")
}