main.yml Specification
The main.yml file is the central workspace configuration manifest. It configures the required Testform version, state storage backend, external providers, artifact scopes, and custom metadata fields schema.
Schema Overview
Section titled “Schema Overview”testform: required_version: ">= 1.0.0" backend: local: path: "testform.state"
# 1. Provider Configuration (GitHub, Jira, GitLab, Local)provider: github: owner: "my-organization" repository: "my-application" project_number: 12 token_env: "GITHUB_TOKEN"
# 2. Input Variables and Local Valuesvariable: app_url: type: string description: "Base application URL" default: "https://www.saucedemo.com" environment: type: string default: "dev"
locals: base_url: "${var.app_url}" api_health: "${local.base_url}/health"
# 3. Test Resources Declaration (resource)# Strictly allows: testcase, testrun, testplan (and global)resource: global: scaffold: directory: "tests" fields: - name: priority source: "tag" enum: ["@low", "@medium", "@high", "@critical"] default: "@medium" testcase: match: "*.case.feature" scaffold: directory: "tests/features" filename: "{slug}.case.feature" fields: - name: module source: "step" required: true testrun: match: "*.run.feature" scaffold: directory: "tests/runs" filename: "{slug}.run.feature" fields: - name: environment source: "step" default: "qa" testplan: match: "*.plan.feature" scaffold: directory: "tests/plans" filename: "{slug}.plan.feature"Compilation and Configuration Processing Pipeline
Section titled “Compilation and Configuration Processing Pipeline”Testform compiles and resolves all configuration layers via a sequential in-memory pipeline:
┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ main.yml │ │ variables.yml │ │ resource.yml │ └───────┬────────┘ └───────┬────────┘ └───────┬────────┘ │ │ │ ▼ ▼ ▼ [PHASE 1: IN-MEMORY DISCOVERY & SYMBOL SCHEMA MERGE] │ ▼ [PHASE 2: VALUE INGESTION & PRECEDENCE (*.vars.yml, CLI)] │ ▼ [PHASE 3: STATIC TYPE & AST VALIDATION (enum, condition)] │ ▼ [PHASE 4: LOCALS & HCL FUNCTION EVALUATION] │ ▼ [PHASE 5: INJECTION INTO GHERKIN RESOURCES (*.case.feature) + DAG] │ ▼ [PHASE 6: RECONCILIATION DIFF AGAINST testform.state (plan / apply)]1. backend Block
Section titled “1. backend Block”Defines where the state ledger (testform.state) resides and how distributed mutex locks are acquired:
Type (type) |
Description | Required Parameters |
|---|---|---|
local |
Local file storage (intended for solo development and testing). | path |
oci |
Oracle Cloud Infrastructure Object Storage with ETag conditional locking. | namespace, bucket, object_name, tenancy_id |
s3 |
Amazon S3 with distributed mutex locking via Amazon DynamoDB. | bucket, key, dynamodb_table, region |
azure |
Azure Blob Storage with exclusive lease locking. | storage_account, container, blob_name |
gcs |
Google Cloud Storage with object generation preconditions. | bucket, prefix |
2. resource Block: Gherkin Resource Governance
Section titled “2. resource Block: Gherkin Resource Governance”In Testform, the managed testing artifacts (testcase, testrun, testplan) are Resources, following Terraform architecture. To prevent misconfigurations, Testform strictly validates that only authorized resource types are declared: testcase, testrun, testplan (and global for common inherited rules).
To prevent main.yml from becoming bloated, Testform supports declaring the resource: block directly in main.yml or inside an independent modular file resource.yml (or resource.yaml).
Data Flow: From Gherkin to resource.ts and the Remote Provider
Section titled “Data Flow: From Gherkin to resource.ts and the Remote Provider”The declared fields are not direct API attributes, but the quality contract for the Gherkin author. The resource.ts adapter maps and extracts those fields to feed the remote Provider:
Gherkin (.feature) resource.yml resource.ts Provider (GitHub/Jira) ┌──────────────────────┐ ┌────────────────────────┐ ┌───────────────────────┐ ┌──────────────────────┐ │ @high @tc-login-001 │ │ resource: │ │ resource.registry({ │ │ GitHub Project V2 │ │ Scenario: Login │ │ global: │ │ fields: [ │ │ Status: "Done" │ │ * field module = │ ──► │ fields: [module, │ ──► │ custom_fields: │ ──► │ Project: "HT 360" │ │ "auth" │ │ priority, │ │ s.custom.fields │ │ Module: "auth" │ │ │ │ Status] │ │ ] │ │ Priority: "high" │ └──────────────────────┘ └────────────────────────┘ └───────────────────────┘ └──────────────────────┘Modular Structure in resource.yml
Section titled “Modular Structure in resource.yml”resource: # 1. Workspace-wide rules inherited by ALL resources global: scaffold: filename: "{YYYYMMDD}_{HHmmss}" fields: - name: project source: step required: true default: "Hirent Talent 360" - name: assignees source: step required: true default: "fromeroc9" - name: priority source: tag enum: ["@low", "@medium", "@high"] default: "@medium" - name: Status source: step required: true default: "Done"
# 2. testcase Resource (*.case.feature) testcase: match: "*.case.feature" identity: "tc-*" fields: - name: module source: step required: true - name: functional source: step required: true
# 3. testrun Resource (*.run.feature) testrun: match: "*.run.feature" identity: "tr-*" fields: - name: startDate source: step - name: endDate source: step
# 4. testplan Resource (*.plan.feature) testplan: match: "*.plan.feature" identity: "tp-*" fields: []3. fields Declaration: source and enum
Section titled “3. fields Declaration: source and enum”In Testform, custom fields are declared within scopes.<scope>.fields or scopes.global.fields. They are configured using the following core properties:
source(Extraction Origin): Instructs Testform where to read the field value from:tag: Extracted from scenario or feature tags (e.g.,@high-> fieldprioritygets"@high").step: Defined via a Gherkin step using the* field <name> = <value>directive (e.g.,* field module = auth).
enum(Allowed Values): Closed list of valid values for the field (e.g.,["@low", "@medium", "@high"]).required(Mandatory): Boolean flag requiring the scenario to provide a value (or have a default). If missing,testform validateraises a policy violation.default(Default Value): Value automatically assigned when not explicitly provided in the scenario.
4. Provider Configuration (provider)
Section titled “4. Provider Configuration (provider)”Testform supports remote issue trackers (such as GitHub and GitLab) as well as a completely offline local provider (local).
Local Provider (provider: local)
Section titled “Local Provider (provider: local)”The local provider allows managing testcases, runs, and plans without relying on any external cloud service or network credentials. All simulated issues, comments, and project fields are saved locally into .testform/cache/data.json.
This is ideal for offline development, air-gapped environments, or solo verification:
# Direct scalar modeprovider: localOr using dictionary syntax:
provider: local: {}When using provider: local, testform plan and testform apply assign local IDs prefixed with local:<number> (such as local:1, local:2), guaranteeing complete offline reproducibility.
GitHub Provider (provider.github)
Section titled “GitHub Provider (provider.github)”Synchronizes test resources as issues and project items in GitHub Projects V2. Testform supports both human-readable project numbers (projectId: 12) and GraphQL node IDs (projectId: "PVT_kwDOB12345").
provider: github: owner: "my-organization" repository: "my-application" projectId: 12 token_env: "GITHUB_TOKEN"| Parameter | Description | Required |
|---|---|---|
owner |
GitHub organization or username owning the repository. | Yes |
repository |
GitHub repository name. | Yes |
projectId |
Numeric or GraphQL project ID in GitHub Projects V2. | No |
token_env |
Environment variable name providing the personal access token (default GITHUB_TOKEN). |
No |
Authentication tokens are securely injected via the GITHUB_TOKEN environment variable or the custom variable designated in token_env.
GitLab Provider (provider.gitlab)
Section titled “GitLab Provider (provider.gitlab)”Synchronizes test resources with issues in GitLab projects:
provider: gitlab: projectId: 12345678 token_env: "GITLAB_TOKEN"5. Input Variables (variable:) and Local Values (locals:)
Section titled “5. Input Variables (variable:) and Local Values (locals:)”Testform allows parameterizing both Gherkin step texts and tag metadata through input variables and locally computed values:
variable:: Variable declaration with data type (string,number,boolean), description, allowed catalogenum: [...],validation:constraints, and default values.locals:: Computed values and derived expressions evaluated via the sandboxed AST engine (${var.name},${local.name},${lower()},${format()}).
For further information on precedence hierarchies and type rules, refer to the Variables and Types Guide.