SpecSmash

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2025 License: MIT Imports: 15 Imported by: 0

README

SpecSmash

Property-based testing for OpenAPI 3.0 specifications in Go

Ever wanted to destroy your validator? Were you too lazy to write proper unit tests for your validation?

Say No More

SpecSmash generates random test data that conforms to your OpenAPI 3.0 schemas. Inspired by hypothesis-jsonschema but for Go.

Features

  • Automatic Test Data Generation - Generates realistic test data from OpenAPI 3.0 schemas
  • Schema Validation - Ensures generated data validates against your spec
  • Property-Based Testing - Leverages pgregory.net/rapid for exhaustive edge case discovery
  • Comprehensive Coverage - Supports complex schemas including:
    • All primitive types (string, number, integer, boolean)
    • String formats (uuid, date-time, email, byte, etc.)
    • Objects with nested properties
    • Arrays with various item types
    • oneOf, anyOf, allOf compositions
    • Nullable fields
    • Min/max constraints, enums
    • Additional properties
  • Custom Pattern Generators - Provide your own pattern matching functions for regex patterns and string formats

Installation

go get github.com/djosh34/specsmash

Quick Start

package main

import (
    "testing"
    "github.com/djosh34/specsmash"
    "pgregory.net/rapid"
)

func TestMyAPI(t *testing.T) {
    // Load your OpenAPI spec
    spec, err := SpecSmash.ReadSpec("testdata/openapi.yaml")
    if err != nil {
        t.Fatal(err)
    }

    // Generate and validate test data
    rapid.Check(t, func(t *rapid.T) {
        // Get the schema you want to test
        schema := spec.Components.Schemas["User"].Value
        
        // Generate data conforming to the schema
        generator := SpecSmash.GenFromSchema(schema)
        data := generator.Draw(t, "user-data")
        
        // Use the generated data to test your API
        // ... your test logic here
    })
}

Pattern Matching

SpecSmash requires you to provide a custom pattern function for schemas that use pattern constraints or certain string formats (email, hostname, ipv4, ipv6, uri, uri-reference). This is because ECMA regex patterns are not natively supported.

Using Pattern Functions
import (
    "testing"
    "github.com/djosh34/specsmash"
    "pgregory.net/rapid"
)

func TestWithPatterns(t *testing.T) {
    spec, err := SpecSmash.ReadSpec("testdata/openapi.yaml")
    if err != nil {
        t.Fatal(err)
    }

    // Create generation options with a custom pattern function
    opts := SpecSmash.NewGenerationOptions().WithPatternFunc(
        func(pattern string, format string, minLength int, maxLength int, t *rapid.T) string {
            // Use rapid.StringMatching or your own implementation
            // NOTE: rapid.StringMatching uses RE2 syntax, not ECMA
            return rapid.StringMatching(pattern).Draw(t, "pattern-"+format)
        },
    )

    rapid.Check(t, func(t *rapid.T) {
        schema := spec.Components.Schemas["User"].Value
        
        // Use the custom options
        generator := opts.GenFromSchema(schema)
        data := generator.Draw(t, "user-data")
        
        // ... your test logic here
    })
}

The pattern function receives:

  • pattern - The regex pattern from the schema (or a suggested pattern for formats)
  • format - The string format (e.g., "email", "ipv4", or empty string for custom patterns)
  • minLength - Minimum string length constraint from the schema
  • maxLength - Maximum string length constraint from the schema (-1 if not set)
  • t - The rapid.T instance for drawing values

Important: If your schema contains patterns or certain string formats and you don't provide a PatternFunc, the generator will panic with a helpful error message.

Limitations

  • multipleOf is not fully supported due to implementation errors (in this version). It will generate valid multipleOfs most of the time, unless you have very small multipliers that will cause precision issues
  • anyOf when both have a shared property, the generator will error (in this version)
  • Pattern matching requires a user-provided function due to ECMA regex incompatibility

How It Works

SpecSmash uses kin-openapi to parse OpenAPI specifications and rapid for property-based test generation. It intelligently creates generators that respect all schema constraints including types, formats, ranges, patterns, and compositions.

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenFromSchema

func GenFromSchema(schema *openapi3.Schema) *rapid.Generator[json.RawMessage]

GenFromSchema is a public wrapper that creates default options and generates from schema

func GetSchema

func GetSchema(op *openapi3.Operation) (*openapi3.SchemaRef, bool)

func ReadSpec

func ReadSpec(specPath string) (*openapi3.T, error)

func ReadSpecFromReader

func ReadSpecFromReader(b io.Reader) (*openapi3.T, error)

func ValidatePayload

func ValidatePayload(ctx context.Context, payload []byte, p string, op *openapi3.Operation) error

Types

type GenerationOptions

type GenerationOptions struct {
	MaxDepth                int
	AdditionalPropertiesMax int
	PatternFunc             PatternFunc
	// contains filtered or unexported fields
}

GenerationOptions holds configuration for schema generation

func NewGenerationOptions

func NewGenerationOptions() *GenerationOptions

NewGenerationOptions creates a new GenerationOptions instance with default values

func (*GenerationOptions) GenFromSchema

func (opts *GenerationOptions) GenFromSchema(schema *openapi3.Schema) *rapid.Generator[json.RawMessage]

func (*GenerationOptions) WithPatternFunc

func (opts *GenerationOptions) WithPatternFunc(f PatternFunc) *GenerationOptions

WithPatternFunc sets a custom pattern generator function. The pattern function will be called for any schema that has a pattern constraint.

type PatternFunc

type PatternFunc func(pattern string, format string, minLength int, maxLength int, t *rapid.T) string

PatternFunc is a function that generates strings matching a pattern. It receives the pattern, format, minLength, maxLength, and *rapid.T. Users should provide this function to handle custom patterns.

Jump to

Keyboard shortcuts

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