testutils

package module
v0.4.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2025 License: MIT Imports: 8 Imported by: 0

README

testutils Build Status Go Report Card Coverage Status Go Reference

Package testutils provides useful test helpers.

Details

Capture Utilities
  • CaptureStdout: Captures stdout output from the provided function
  • CaptureStderr: Captures stderr output from the provided function
  • CaptureStdoutAndStderr: Captures both stdout and stderr from the provided function

These capture utilities are useful for testing functions that write directly to stdout/stderr. They redirect the standard outputs to a buffer and return the captured content as a string.

Important Note: The capture functions are not thread-safe if used in parallel tests. For concurrent tests, it's better to pass a custom io.Writer to the function under test instead.

File Utilities
  • WriteTestFile: Creates a temporary file with specified content and returns its path. The file is automatically cleaned up after the test completes.
HTTP Test Utilities
  • MockHTTPServer: Creates a test HTTP server with the given handler. Returns the server URL and a cleanup function.
  • HTTPRequestCaptor: Returns a request captor and an HTTP handler that captures and records HTTP requests for later inspection.
Test Containers

The containers package provides several test containers for integration testing:

  • SSHTestContainer: SSH server container for testing SSH connections with file operations (upload, download, list, delete)
  • FTPTestContainer: FTP server container for testing FTP file operations (upload, download, list, delete)
  • PostgresTestContainer: PostgreSQL database container with automatic database creation
  • MySQLTestContainer: MySQL database container with automatic database creation
  • MongoTestContainer: MongoDB container with support for multiple versions (5, 6, 7)
  • LocalstackTestContainer: LocalStack container with S3 service for AWS testing, including file operations (upload, download, list, delete)

Install and update

go get -u github.com/go-pkgz/testutils

Example Usage

Capture Functions
// Capture stdout
func TestMyFunction(t *testing.T) {
    output := testutils.CaptureStdout(t, func() {
        fmt.Println("Hello, World!")
    })
    
    assert.Equal(t, "Hello, World!\n", output)
}

// Capture stderr
func TestErrorOutput(t *testing.T) {
    errOutput := testutils.CaptureStderr(t, func() {
        fmt.Fprintln(os.Stderr, "Error message")
    })
    
    assert.Equal(t, "Error message\n", errOutput)
}

// Capture both stdout and stderr
func TestBothOutputs(t *testing.T) {
    stdout, stderr := testutils.CaptureStdoutAndStderr(t, func() {
        fmt.Println("Standard output")
        fmt.Fprintln(os.Stderr, "Error output")
    })
    
    assert.Equal(t, "Standard output\n", stdout)
    assert.Equal(t, "Error output\n", stderr)
}
File Utilities
// Create a temporary test file
func TestWithTempFile(t *testing.T) {
    content := "test file content"
    filePath := testutils.WriteTestFile(t, content)
    
    // Use the file in your test
    data, err := os.ReadFile(filePath)
    require.NoError(t, err)
    assert.Equal(t, content, string(data))
    
    // No need to clean up - it happens automatically when the test ends
}
HTTP Test Utilities
// Create a mock HTTP server
func TestWithMockServer(t *testing.T) {
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("response"))
    })
    
    serverURL, _ := testutils.MockHTTPServer(t, handler)
    
    // Make requests to the server
    resp, err := http.Get(serverURL + "/path")
    require.NoError(t, err)
    defer resp.Body.Close()
    
    assert.Equal(t, http.StatusOK, resp.StatusCode)
}

// Capture and inspect HTTP requests
func TestWithRequestCaptor(t *testing.T) {
    // Create a request captor
    captor, handler := testutils.HTTPRequestCaptor(t, nil)
    
    // Create a server with the capturing handler
    serverURL, _ := testutils.MockHTTPServer(t, handler)
    
    // Make a request
    http.Post(serverURL+"/api", "application/json", 
              strings.NewReader(`{"key":"value"}`))
    
    // Inspect the captured request
    req, _ := captor.GetRequest(0)
    assert.Equal(t, http.MethodPost, req.Method)
    assert.Equal(t, "/api", req.Path)
    assert.Equal(t, `{"key":"value"}`, string(req.Body))
}
Test Containers
// PostgreSQL test container
func TestWithPostgres(t *testing.T) {
    ctx := context.Background()
    pg := containers.NewPostgresTestContainer(ctx, t)
    defer pg.Close(ctx)
    
    db, err := sql.Open("postgres", pg.ConnectionString())
    require.NoError(t, err)
    defer db.Close()
    
    // run your tests with the database
}

// MySQL test container
func TestWithMySQL(t *testing.T) {
    ctx := context.Background()
    mysql := containers.NewMySQLTestContainer(ctx, t)
    defer mysql.Close(ctx)
    
    db, err := sql.Open("mysql", mysql.DSN())
    require.NoError(t, err)
    defer db.Close()
    
    // run your tests with the database
}

// MongoDB test container
func TestWithMongo(t *testing.T) {
    ctx := context.Background()
    mongo := containers.NewMongoTestContainer(ctx, t, 7) // version 7
    defer mongo.Close(ctx)
    
    coll := mongo.Collection("test_db")
    _, err := coll.InsertOne(ctx, bson.M{"test": "value"})
    require.NoError(t, err)
}

// SSH test container
func TestWithSSH(t *testing.T) {
    ctx := context.Background()
    ssh := containers.NewSSHTestContainer(ctx, t)
    defer ssh.Close(ctx)
    
    // use ssh.Address() to get host:port
    // default user is "test"
    sshAddr := ssh.Address()
    
    // Upload a file to the SSH server
    localFile := "/path/to/local/file.txt"
    remotePath := "/config/file.txt"
    err := ssh.SaveFile(ctx, localFile, remotePath)
    require.NoError(t, err)
    
    // Download a file from the SSH server
    downloadPath := "/path/to/download/location.txt"
    err = ssh.GetFile(ctx, remotePath, downloadPath)
    require.NoError(t, err)
    
    // List files on the SSH server
    files, err := ssh.ListFiles(ctx, "/config")
    require.NoError(t, err)
    for _, file := range files {
        fmt.Println(file.Name(), file.Mode(), file.Size())
    }
    
    // Delete a file from the SSH server
    err = ssh.DeleteFile(ctx, remotePath)
    require.NoError(t, err)
}

// Localstack (S3) test container
func TestWithS3(t *testing.T) {
    ctx := context.Background()
    ls := containers.NewLocalstackTestContainer(ctx, t)
    defer ls.Close(ctx)
    
    s3Client, bucketName := ls.MakeS3Connection(ctx, t)
    
    // put object example (using direct S3 API)
    _, err := s3Client.PutObject(ctx, &s3.PutObjectInput{
        Bucket: aws.String(bucketName),
        Key:    aws.String("test-key"),
        Body:   strings.NewReader("test content"),
    })
    require.NoError(t, err)
    
    // File operations using higher-level container methods
    
    // Upload a file to S3
    localFile := "/path/to/local/file.txt"
    objectKey := "documents/file.txt"
    err = ls.SaveFile(ctx, localFile, bucketName, objectKey)
    require.NoError(t, err)
    
    // Download a file from S3
    downloadPath := "/path/to/download/location.txt"
    err = ls.GetFile(ctx, bucketName, objectKey, downloadPath)
    require.NoError(t, err)
    
    // List objects in bucket (optionally with prefix)
    objects, err := ls.ListFiles(ctx, bucketName, "documents/")
    require.NoError(t, err)
    for _, obj := range objects {
        fmt.Println(*obj.Key, *obj.Size)
    }
    
    // Delete an object from S3
    err = ls.DeleteFile(ctx, bucketName, objectKey)
    require.NoError(t, err)
}

// FTP test container
func TestWithFTP(t *testing.T) {
    ctx := context.Background()
    ftpContainer := containers.NewFTPTestContainer(ctx, t)
    defer ftpContainer.Close(ctx)
    
    // Connection details
    ftpHost := ftpContainer.GetIP()        // Container host
    ftpPort := ftpContainer.GetPort()      // Container port (default: 2121)
    ftpUser := ftpContainer.GetUser()      // Default: "ftpuser"
    ftpPassword := ftpContainer.GetPassword() // Default: "ftppass"
    
    // Upload a file
    localFile := "/path/to/local/file.txt" 
    remotePath := "file.txt"
    err := ftpContainer.SaveFile(ctx, localFile, remotePath)
    require.NoError(t, err)
    
    // Download a file
    downloadPath := "/path/to/download/location.txt"
    err = ftpContainer.GetFile(ctx, remotePath, downloadPath)
    require.NoError(t, err)
    
    // List files
    entries, err := ftpContainer.ListFiles(ctx, "/")
    require.NoError(t, err)
    for _, entry := range entries {
        fmt.Println(entry.Name, entry.Type) // Type: 0 for file, 1 for directory
    }
    
    // Delete a file
    err = ftpContainer.DeleteFile(ctx, remotePath)
    require.NoError(t, err)
}

Documentation

Overview

Package testutils provides utilities for testing Go applications

Package testutils provides a collection of utilities for testing Go applications including stdout/stderr capture, file handling, HTTP test helpers, and test containers.

It consists of several main components:

Capture Utilities:

  • CaptureStdout, CaptureStderr, CaptureStdoutAndStderr: Functions to capture output from standard streams during test execution. These are useful for testing functions that write directly to stdout/stderr. Note: These functions are not thread-safe for parallel tests.

File Utilities:

  • WriteTestFile: Creates a temporary file with specified content for testing purposes, with automatic cleanup after the test completes.

HTTP Utilities:

  • MockHTTPServer: Creates a test HTTP server with the provided handler
  • HTTPRequestCaptor: Captures and records HTTP requests for later inspection

Test Containers: The 'containers' subpackage provides Docker containers for integration testing:

  • SSHTestContainer: SSH server container with file operation support (upload, download, list, delete)
  • FTPTestContainer: FTP server container with file operation support
  • PostgresTestContainer: PostgreSQL database container with automatic DB creation
  • MySQLTestContainer: MySQL database container with automatic DB creation
  • MongoTestContainer: MongoDB container with support for multiple versions
  • LocalstackTestContainer: LocalStack container with S3 service for AWS testing

All container implementations support a common pattern:

  • Container creation with NewXXXTestContainer
  • Automatic port mapping and connection configuration
  • Graceful shutdown with the Close method
  • File operations where applicable (SaveFile, GetFile, ListFiles, DeleteFile)

These utilities help simplify test setup, improve test reliability, and reduce boilerplate code in test suites, especially for integration tests.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CaptureStderr

func CaptureStderr(t *testing.T, f func()) string

CaptureStderr captures os.Stderr output from the provided function.

func CaptureStdout

func CaptureStdout(t *testing.T, f func()) string

CaptureStdout captures os.Stdout output from the provided function.

func CaptureStdoutAndStderr

func CaptureStdoutAndStderr(t *testing.T, f func()) (stdout, stderr string)

CaptureStdoutAndStderr captures os.Stdout and os.Stderr output from the provided function.

func MockHTTPServer added in v0.2.0

func MockHTTPServer(t *testing.T, handler http.Handler) (serverURL string, cleanup func())

MockHTTPServer creates a test HTTP server with the given handler. Returns the server URL and a function to close it.

func WriteTestFile added in v0.2.0

func WriteTestFile(t *testing.T, content string) string

WriteTestFile creates a temporary file with the given content and returns its path. The file is automatically cleaned up after the test completes.

Types

type RequestCaptor added in v0.2.0

type RequestCaptor struct {
	// contains filtered or unexported fields
}

RequestCaptor captures HTTP requests for inspection in tests

func HTTPRequestCaptor added in v0.2.0

func HTTPRequestCaptor(t *testing.T, next http.Handler) (*RequestCaptor, http.Handler)

HTTPRequestCaptor returns a request captor and HTTP handler that captures requests The returned handler will forward requests to the provided next handler if not nil

func (*RequestCaptor) GetRequest added in v0.2.0

func (c *RequestCaptor) GetRequest(idx int) (RequestRecord, bool)

GetRequest returns the request at the specified index

func (*RequestCaptor) GetRequests added in v0.2.0

func (c *RequestCaptor) GetRequests() []RequestRecord

GetRequests returns all captured requests

func (*RequestCaptor) Len added in v0.2.0

func (c *RequestCaptor) Len() int

Len returns the number of captured requests

func (*RequestCaptor) Reset added in v0.2.0

func (c *RequestCaptor) Reset()

Reset clears all captured requests

type RequestRecord added in v0.2.0

type RequestRecord struct {
	Method  string
	Path    string
	Headers http.Header
	Body    []byte
}

RequestRecord holds information about a captured HTTP request

Directories

Path Synopsis
Package containers implements various test containers for integration testing
Package containers implements various test containers for integration testing

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL