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 you need to ensure a business invariant holds for all valid inputs.
For simple deterministic transformations without invariants, stick to example-based tests.
Security analysis
SafeThis 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
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.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 basicsthree-layer-architecture- Service layer testing
TDD Red-Green-Refactor
Testing
Skill that guides Claude through the complete TDD cycle.
Web Accessibility Audit
Testing
Performs a comprehensive web accessibility audit following WCAG standards.
UAT Test Case Generator
Testing
Generates structured and comprehensive user acceptance test cases.