Property-Based Testing

VerifiedSafe

Property-based testing using fast-check to validate business logic invariants by generating random inputs. It helps ensure correctness for edge cases that manual tests might miss, especially for mathematical calculations, inventory invariants, and state transitions.

Sby Skills Guide Bot
TestingIntermediate
1106/2/2026
Claude Code
#property-testing#fast-check#business-logic#invariants

Recommended for

Our review

This skill teaches property-based testing with fast-check to validate invariants in business logic.

Strengths

  • Exhaustive coverage of possible inputs
  • Catches edge cases and side effects
  • Verifies critical business invariants
  • Seamless integration with Vitest

Limitations

  • Learning curve to define meaningful properties
  • Does not replace example-based tests for simple deterministic logic
  • Can be slower than example-based tests
When to use it

When you need to ensure a business invariant holds for all valid inputs.

When not to use it

For simple deterministic transformations without invariants, stick to example-based tests.

Security analysis

Safe
Quality score88/100

This skill is a purely instructional guide to property-based testing with fast-check. It contains no executable commands, destructive operations, exfiltration, or obfuscation.

No concerns found

Examples

Test FCR calculation
Write a property-based test for the FCR calculation function that takes feed and weight gain as inputs. The property should ensure that for any positive feed and weight gain, the FCR is positive and finite.
Test inventory invariant
Write a property-based test to verify the inventory invariant: current quantity equals initial quantity minus sum of mortalities minus sum of sales. Use fast-check to generate random initial quantities, mortalities, and sales, and ensure the calculated current quantity is non-negative and does not exceed the initial quantity.

name: Property Testing description: Property-based testing with fast-check for business logic validation

Property Testing

LivestockAI uses property-based testing (PBT) with fast-check to validate business logic invariants.

What is Property Testing?

Instead of testing specific examples, property tests verify that properties hold for ALL possible inputs:

// Example-based test
it('calculates FCR correctly', () => {
  expect(calculateFCR(150, 100)).toBe(1.5)
})

// Property-based test
it('FCR is always positive when inputs are positive', () => {
  fc.assert(
    fc.property(
      fc.float({ min: 0.1, max: 10000 }),
      fc.float({ min: 0.1, max: 10000 }),
      (feed, weight) => {
        const fcr = calculateFCR(feed, weight)
        return fcr === null || fcr > 0
      },
    ),
  )
})

fast-check Basics

import { describe, it, expect } from 'vitest'
import * as fc from 'fast-check'

describe('Property Tests', () => {
  it('property holds for all inputs', () => {
    fc.assert(
      fc.property(fc.integer({ min: 1, max: 100000 }), (quantity) => {
        // Property must return true or throw
        return quantity > 0
      }),
      { numRuns: 100 },
    )
  })
})

Common Arbitraries

// Integers
fc.integer({ min: 1, max: 100000 })
fc.nat() // Non-negative integer

// Floats
fc.float({ min: 0, max: 10000 })

// Strings
fc.string()
fc.uuid()

// Arrays
fc.array(fc.integer(), { minLength: 0, maxLength: 20 })

// Objects
fc.record({
  quantity: fc.integer({ min: 1, max: 1000 }),
  price: fc.float({ min: 0, max: 10000 }),
})

Inventory Invariant Example

From tests/features/batches/batches.property.test.ts:

/**
 * Property 4: Inventory Invariant
 * For any batch, current_quantity SHALL always equal:
 * initial_quantity - sum(mortality) - sum(sales)
 */
describe('Property 4: Inventory Invariant', () => {
  it('current_quantity equals initial - mortalities - sales', () => {
    fc.assert(
      fc.property(
        fc.integer({ min: 1, max: 100000 }),
        fc.array(fc.integer({ min: 1, max: 1000 })),
        fc.array(fc.integer({ min: 1, max: 1000 })),
        (initial, mortalities, sales) => {
          const { constrained } = constrainQuantities(
            initial,
            mortalities,
            sales,
          )
          const current = calculateCurrentQuantity(initial, constrained)

          expect(current).toBeGreaterThanOrEqual(0)
          expect(current).toBeLessThanOrEqual(initial)
        },
      ),
      { numRuns: 100 },
    )
  })
})

Linking to Requirements

Annotate tests with requirement links:

/**
 * **Validates: Requirements 3.2, 4.2, 8.2**
 */
it('inventory invariant holds', () => {
  // ...
})

When to Use Property Testing

  • Mathematical calculations (FCR, mortality rate, profit)
  • Invariants (quantity never negative, totals match)
  • State transitions (batch status changes)
  • Data transformations (currency conversion)

Related Skills

  • vitest-patterns - Unit testing basics
  • three-layer-architecture - Service layer testing
Related skills