Schema composition¶
OpenAPI supports schema composition through allOf, anyOf, and oneOf keywords. This page explains how the test generator processes composed schemas and generates test cases for them.
Composition keywords¶
| Keyword | OpenAPI Semantics | How Generator Handles It |
|---|---|---|
allOf | Instance must validate against all listed schemas | Merges all subschemas into a single unified schema |
anyOf | Instance must validate against at least one schema | Generates test cases for each subschema variant |
oneOf | Instance must validate against exactly one schema | Generates test cases for each subschema variant |
SchemaMerger¶
The SchemaMerger component (in example-value module) handles schema composition by flattening composed schemas into a single merged schema for validation and value generation.
Merge behavior¶
When merging schemas:
- Properties: Merged recursively; later schemas override earlier ones
- Required fields: Combined (union of all required arrays)
- Constraints: Tightest bounds win (e.g., higher
minLength, lowermaxLength) - Type: Must be compatible across all subschemas
- Enums: Intersection of allowed values
Example¶
Given this composed schema:
components:
schemas:
Pet:
allOf:
- $ref: '#/components/schemas/Animal'
- type: object
properties:
name:
type: string
minLength: 1
required:
- name
Animal:
type: object
properties:
species:
type: string
required:
- species
SchemaMerger produces a flattened schema equivalent to:
type: object
properties:
species:
type: string
name:
type: string
minLength: 1
required:
- species
- name
Test case generation for compositions¶
allOf schemas¶
For allOf compositions, the generator:
- Merges all subschemas into a unified schema
- Applies validation rules to the merged schema
- Generates negative test cases for constraint violations
Since allOf requires all constraints to be satisfied, only the merged schema's rules are tested.
anyOf and oneOf schemas¶
For anyOf and oneOf compositions, the generator:
- Identifies each subschema variant
- Generates test cases for each variant's validation rules
- Produces test cases that violate each variant's specific constraints
This can produce more test cases because each variant's unique constraints are tested.
Budget controls for composition¶
Composed schemas can lead to combinatorial explosion. Two budget settings control this:
| Setting | Description |
|---|---|
maxMergedSchemaDepth | Maximum recursion depth when merging composed schemas |
maxSchemaCombinations | Maximum schema combinations per parameter/property |
Defaults and types are documented in Distribution settings.
When budgets are exceeded¶
When a budget limit is reached:
- Generation for that schema/property stops
- A
GenerationErroris recorded with context (operation, field path, limit type) - Other schemas in the same operation continue processing (unless using
FAIL_FASTmode)
Configuration¶
testGenerationSettings:
maxMergedSchemaDepth: 75 # Increase for deeply nested compositions
maxSchemaCombinations: 200 # Increase for complex anyOf/oneOf
See Budget controls for more details on tuning these limits.
Cycle detection¶
Composed schemas can contain circular references (e.g., a schema that references itself through allOf). The generator handles cycles through:
- Schema reference tracking:
visitedSchemaRefstracks$refpaths during traversal - Structural hashing:
SchemaStructureHasherdetects structurally equivalent schemas - Depth limiting:
maxSchemaDepthprevents infinite recursion
When a cycle is detected, the generator stops traversal for that path and continues with other properties.
Limitations¶
Unsupported patterns¶
Some complex composition patterns may not generate complete test coverage:
- Discriminator-based polymorphism: The generator processes subschemas but may not generate tests for all discriminator values
- Conditional schemas (if/then/else): Not currently supported
- Complex nested compositions: Deep nesting of
anyOfinsideoneOfmay hit budget limits
Best practices¶
For optimal test generation with composed schemas:
- Keep compositions shallow: Prefer flat schemas over deeply nested compositions
- Use
allOffor inheritance: Simpler merge semantics produce more predictable tests - Limit
anyOf/oneOfvariants: Each variant multiplies test cases - Use ignore rules: Skip problematic paths if generation budgets are exceeded
testGenerationSettings:
ignoreTestCases:
"/complex-endpoint":
"POST": "*" # Skip tests for endpoints with complex compositions
Related docs¶
- Budget controls - Tuning composition limits
- Architecture - SchemaMerger in the value generation stack
- Error handling - How budget violations are reported