Configuration
isa.yml configuration structure and settings
SpecFormula uses the isa.yml configuration file to define the test framework's runtime specifications, including API Spec, Entity Spec, and instruction mappings.
Project Structure
isa.yml is placed at the root of the test resources directory, alongside Spec files and test files:
src/test/resources/
├── isa.yml # ISA configuration
├── specs/
│ ├── api/
│ │ └── api-spec.yml # API Spec (OpenAPI 3.0)
│ └── data/
│ ├── schema.sql # DDL definition
│ └── entity_to_table_mapping.yml # Entity mapping
└── features/
└── todo.feature # Gherkin test fileComplete Example
config:
api:
resource_path: specs/api
project_path: my-project/src/test/resources/specs/api
time_format: ISO
data:
source:
- name: default
resource_path: specs/data
project_path: my-project/src/test/resources/specs/data
db_type: postgresql
instructions:
- name: Time control
format: ^current time is "(?P<time>.+)"$
instruction_type: time_control
- name: Data preparation
format: ^prepare a (?P<entity>[\w\s]+), with table:$
instruction_type: entity_setup
- name: API call
format: ^\((?:No Actor|UID="(?P<userId>\$[\w.]+)")\) (?P<summary>.+?), call table:$
instruction_type: api_call
- name: API call (JSON)
format: ^\((?:No Actor|UID="(?P<userId>\$[\w.]+)")\) (?P<summary>.+?), call JSON:$
instruction_type: api_call
data_format: json
- name: Response validation
format: ^(?P<summary>.+?)\((?P<status_code>\d{3})\) response,?\s*with table:$
instruction_type: response_validate
- name: Response validation (JSON)
format: ^(?P<summary>.+?)\((?P<status_code>\d{3})\) response,?\s*with JSON:$
instruction_type: response_validate
data_format: json
- name: Database validation
format: ^should exist a (?P<entity>[\w\s]+), with table:$
instruction_type: entity_validate
- name: Database validation (JSON)
format: ^should exist a (?P<entity>[\w\s]+), with json:$
instruction_type: entity_validate
data_format: json
- name: Database non-existence validation
format: ^should not exist a (?P<entity>[\w\s]+), with table:$
instruction_type: entity_non_existence_validate
- name: Data preparation (JSON)
format: ^prepare a (?P<entity>[\w\s]+), with json:$
instruction_type: entity_setup
data_format: jsonAPI Configuration
config.api sets the location of the API Spec file:
| Field | Description | Default |
|---|---|---|
resource_path | API Spec path in classpath (required) | — |
project_path | API Spec path in project, for Lint (required) | — |
time_format | Output format for time expressions | ISO |
resource_path: The classpath used at test runtime — the framework reads Spec files from this pathproject_path: The file path in source code — used by Lint tools to locate files and report error positions
Time Formats
| Value | Output Example |
|---|---|
ISO (default) | "2025-12-25T14:30:00+08:00" |
TIMESTAMP | 1766735400000 (Unix milliseconds) |
EPOCH | 1766735400 (Unix seconds) |
DATE_ONLY | "2025-12-25" |
TIME_ONLY | "14:30:00" |
Database Configuration
config.data sets the location of database spec files, supporting multiple data sources:
| Field | Description | Default |
|---|---|---|
permission | Data source permission isolation mode | isolated |
reuse | Whether to reuse Testcontainer containers | false |
source | List of data sources | — |
permission: isolated: DataSources are permission-isolated from each other and cannot access each other's tablespermission: shared: DataSources share permissions and can access each other's tablesreuse: true: Reuse Testcontainer containers to avoid restarting for every test, speeding up execution
Fields for each source item:
| Field | Description | Default |
|---|---|---|
name | Data source name (required) | — |
resource_path | DDL and mapping file path in classpath (required) | — |
project_path | DDL and mapping file path in project, for Lint (required) | — |
db_type | Database type: embedded, postgresql, mysql, mssql. embedded is a framework-chooses-implementation alias (Java→H2, C#→sqlite-style, Python→DuckDB). | embedded |
schema | Default schema for the DataSource connection (optional) | Database default |
Schema Configuration
The schema field is for enterprise multi-schema architectures, specifying the default schema for a DataSource connection:
config:
data:
source:
- name: default
resource_path: specs/data
db_type: postgresql
schema: app_schema # optionalDatabase-specific behavior:
| db_type | Schema Behavior | Default Schema |
|---|---|---|
postgresql | Sets search_path to "<schema>", public | public |
mssql | Sets connection DEFAULT_SCHEMA | dbo |
mysql / mariadb | Ignored (schema = database, set via connection URL) | N/A |
embedded | Ignored (embedded test database, no multi-schema routing; Java implementation uses H2) | PUBLIC |
DDL CREATE TABLE statements may include schema prefixes (e.g., CREATE TABLE dbo.users (...)). The framework extracts and preserves schema prefixes, using fully-qualified names (schema.table) in generated SQL.
Folder Structure
specs/data/
├── schema.sql # DDL definition
└── entity_to_table_mapping.yml # Entity to Table mappingEntity Mapping
Defines the mapping between business names used in Gherkin and database tables:
entity_to_table_mapping:
- user: users
- todo: todosUsage:
Given prepare a user, with table:
| name | email |
| Alice | alice@example.com |Instruction Mapping
instructions defines the mapping between Gherkin Step text and ISA instructions:
| Field | Description |
|---|---|
name | Instruction name (for identification and error messages) |
format | Regular expression to match Gherkin Steps |
instruction_type | Corresponding ISA instruction type |
data_format | Step payload format: none, data_table, json, text. If omitted, the default depends on instruction_type. |
data_format payload contract
data_format describes whether a Step has a DataTable or DocString payload, and how DocString content is parsed. This is a shared contract between ISA and every language runtime.
| data_format | Payload | Usage |
|---|---|---|
none | No payload | Instructions without DataTable / DocString; custom defaults to none. |
data_table | Gherkin DataTable | Table-based data setup, API call, response validation, and entity validation. |
json | JSON DocString | JSON body, JSON response expectation, or JSON entity payload. |
text | Text DocString | Plain-text payload; if a Step uses a text DocString, set data_format: text explicitly. |
Default rules:
- Built-in ISA instructions default to
data_tablewhendata_formatis omitted. instruction_type: customdefaults tononewhendata_formatis omitted; the user-defined Step Definition owns the behavior and the ISA runtime does not parse a payload.- JSON DocString steps must set
data_format: json. - Plain-text DocString steps must set
data_format: textto avoid being treated as no-payload or JSON.
Example:
instructions:
- name: Custom log message
format: ^log message:$
instruction_type: custom
data_format: text
- name: Custom checkpoint
format: ^mark checkpoint (?P<name>.+)$
instruction_type: custom
# data_format omitted; custom defaults to noneInstruction Type Reference
| instruction_type | Corresponding Instruction |
|---|---|
time_control | TimeControl |
entity_setup | EntitySetup |
api_call | ApiCall |
response_validate | ResponseValidate |
entity_validate | EntityValidate |
entity_non_existence_validate | EntityNonExistenceValidate |
custom | Custom Instructions |
Regex to Gherkin Mapping
ISA instruction mapping does not support Cucumber Expressions (e.g. {int}, {string}).
The format field must be a regular expression that matches the full Gherkin Step text, and captures parameters via named capture groups.
- Python-style named groups:
(?P<name>...) - Java/JVM-style named groups:
(?<name>...)
For example, with api_call:
Gherkin: (UID="$Alice.id") create todo, call table:
Regex (Python): ^\((?:No Actor|UID="(?P<userId>...)")\) (?P<summary>.+?), call table:$
Regex (Java): ^\((?:No Actor|UID="(?<userId>...)")\) (?<summary>.+?), call table:$
Captured: userId = $Alice.id summary = create todoCapture Group Reference
| instruction_type | Required Groups |
|---|---|
time_control | time |
entity_setup | entity |
api_call | summary, userId (optional) |
response_validate | summary, status_code |
entity_validate | entity |
entity_non_existence_validate | entity |
custom | (depends on user-defined Step Definition) |