mamund/tram

test runner for assertion manifests

JavaScript

4

110 commits

updated Sep 4, 2026

See the code

See what people are saying (1)

README

TRAM

TRAM (Test Runner for Assertion Manifests) is a framework for creating executable behavioral models of HTTP APIs. It validates those models and gathers evidence from running APIs to verify that observable behavior matches the intended design.

Rather than focusing on implementation details, TRAM focuses on what can be observed at the API surface: the resources, actions, workflows, and rules that define how a system behaves. Assertions are organized into progressively richer layers, moving from endpoint availability and response structure to business behavior, workflows, and governance constraints. This allows teams to express operational intent as a durable behavioral model that remains valuable even as implementations evolve.

TRAM (Test Runner for Assertion Manifests)
TRAM screenshot of test run

Documentation

TRAM combines:

  • a manifest-driven test format
  • a reusable assertion engine
  • a portable HTTP test runner
  • stable runtime interpolation support
  • native type assertions
  • optional property assertions
  • object-map and collection assertions
  • layered behavioral modeling
  • workflow-oriented behavioral validation
  • an AI Coaching workflow focused on learning and augmentation rather than pure automation

What's New in Manifest 0.2

Manifest version 0.2 introduces response capture.

Capture allows a test to extract values from an HTTP response (such as resource identifiers or hypermedia links) and reuse those values in subsequent requests. This makes it possible to write behavioral tests for APIs that generate identifiers dynamically or expose navigational affordances.

Earlier (0.1) manifests remain supported and continue to execute without modification.


Output artifacts

A TRAM run can produce several complementary artifacts.

ArtifactPurpose
ManifestDefines the expected API behavior.
HTTP TranscriptRecords the observed HTTP request/response conversation.
ReportEvaluates the observed behavior against the manifest.
EvidenceThe complete collection of artifacts from a test run.

The transcript and report serve different purposes.

The HTTP Transcript records what happened during execution. The Report evaluates whether the observed behavior satisfied the behavioral expectations expressed in the manifest.


Smallest complete TRAM manifest

{
  "name": "Smallest TRAM manifest",
  "config": {
    "baseUrl": "http://localhost:3000"
  },
  "tests": [
    {
      "name": "GET /tasks returns 200",
      "method": "GET",
      "path": "/tasks",
      "expect": {
        "status": 200
      }
    }
  ]
}

This is the smallest useful complete TRAM manifest:

  • one manifest
  • one test
  • one request
  • one behavioral assertion

Capturing Values

The capture property records values observed in an HTTP response and makes them available to later requests.

{
  "id": "task-create",
  "method": "POST",
  "path": "/tasks",
  "bodyType": "json",
  "body": "$data.task.capture.valid",
  "expect": {
    "status": 201
  },
  "capture": {
    "createdTaskId": "body.id"
  }
}

Later tests can reference the captured value:

{
  "id": "task-get",
  "method": "GET",
  "path": "/tasks/${capture.createdTaskId}",
  "expect": {
    "status": 200
  }
}

Capture works with response bodies, headers, and other observable response values. See the Manifest Specification for the complete syntax.


Why TRAM exists

TRAM explores a narrow problem:

How do we make behavioral expectations directly visible, portable, executable, and reviewable?

The core artifact is the manifest:

api-tests.json

The manifest defines:

  • requests
  • request bodies
  • assertions
  • expected behaviors
  • shared test data
  • runtime interpolation values

Assertions become directly inspectable operational statements.

Simple behavioral assertion:

{
  "path": "$.status",
  "equals": "active"
}

Meaning:

The resource status must be "active".

Optional property assertion for evolving representations:

{
  "path": "$",
  "each": {
    "property": "description",
    "optional": true,
    "type": "string"
  }
}

Meaning:

"description" may be absent.
If present, it must be a string.

Hypermedia affordance assertion:

{
  "path": "$._links",
  "eachProperty": {
    "hasProperties": ["href", "method"]
  }
}

Meaning:

Every affordance must define both a target URL and an HTTP method.

Collection behavioral assertion:

{
  "path": "$",
  "each": {
    "property": "status",
    "oneOf": ["active", "pending", "completed"]
  }
}

Meaning:

Every returned resource must have a recognized workflow state.

Nested affordance traversal assertion:

{
  "path": "$",
  "each": {
    "path": "$._links",
    "eachProperty": {
      "hasProperties": ["href", "method"]
    }
  }
}

Meaning:

Every returned resource must expose affordances
that define both a target URL and an HTTP method.

TRAM supports partial and evolving representations while preserving explicit behavioral validation.


Behavioral layering

TRAM organizes behavioral testing into six progressive layers.

LevelFocusQuestion
0SurfaceCan the API be reached?
1ShapeDo resources and affordances appear correctly?
2Safe behaviorDo navigation, lookup, filtering, and query interactions behave correctly?
3Unsafe behaviorDo isolated state-changing actions behave correctly?
4WorkflowCan meaningful operational narratives be completed successfully?
5GovernanceAre policies, constraints, and semantic rules enforced correctly?
TRAM Testing Maturity Pyramid

The layers are additive rather than replacement-oriented. Each layer narrows debugging scope while preserving readable behavioral intent.


Project goals

TRAM is designed around several principles:

  • behavioral tests over implementation tests
  • portable manifests over framework lock-in
  • readable intent over clever abstractions
  • explicitness over hidden runtime behavior
  • low-noise reporting
  • augmentation and learning over one-shot generation

The long-term direction is an AI Coach that helps users learn behavioral API testing while collaboratively constructing executable manifests.


Current implementation

Current implementation includes:

  • manifest specification (api-tests.json)
  • dependency-free assertion engine
  • dependency-free HTTP runner
  • body/header/status assertions
  • collection assertions (each)
  • object-map assertions (eachProperty)
  • native type assertions (type)
  • optional property assertions (optional)
  • range assertions (range)
  • stable run-scoped variables
  • runtime interpolation (${data.*})
  • object injection ($data.*)
  • capture values from responses and reuse them in later requests
  • happy-path and sad-path testing
  • JSON, form, and text request body support
  • workflow-oriented behavioral modeling
  • machine-readable reporting
  • real API validation against a sample CRUD-style task API
  • HTTP transcript generation

Project structure

.
├── README.md
├── package.json
├── api-tests.json
├── bin/
│   └── tram
├── lib/
│   └── assertions.js
├── docs/
└── sample-api/

CLI usage

tram <manifest-file> [options]

Options:

-v, --verbose              Print passing assertion details
-r, --report <file>        Write behavioral report (JSON)
-t, --transcript <file>    Write HTTP transcript
--validate                 Validate the manifest without making HTTP requests
-h, --help                 Show help

CLI installation

Local development setup

Clone the repository:

git clone https://github.com/mamund/2026-05-tram.git
cd 2026-05-tram

macOS/Linux:

chmod +x bin/tram
npm link

Windows:

npm link

Then run:

tram api-tests.json

Validate the manifest without contacting the sample API:

tram api-tests.json --validate

This performs structural validation of the manifest and exits without sending any HTTP requests.


Core concepts

Manifest-driven testing

Tests are defined declaratively in a manifest:

{
  "name": "Create task",
  "method": "POST",
  "path": "/tasks/${data.stableId}",
  "body": "$data.task.valid",
  "expect": {
    "status": 201,
    "body": [
      {
        "path": "$.status",
        "equals": "active"
      }
    ]
  }
}

The manifest acts as both:

  • executable configuration
  • behavioral operational artifact

Shared runtime data

The data section stores reusable request and runtime values.

Example:

{
  "data": {
    "stableId": "${randomId}"
  }
}

The generated value remains stable throughout the current test run.

Later requests can reference the same value:

{
  "path": "/tasks/${data.stableId}"
}

TRAM also supports response capture.

Values observed in one response may be reused later in the same test run.

Example:

"capture": {
  "taskId": "body.id"
}

Later requests can reference the captured value:

"path": "/tasks/${capture.taskId}"

This enables coordinated multi-step behavioral flows without introducing custom scripting.


Runtime interpolation semantics

Use:

"$data.someObject"

when injecting structured runtime objects.

Use:

"${data.someValue}"

when interpolating values inside strings.

Examples:

Correct object injection:

"body": "$data.createTask"

Correct string interpolation:

"path": "/tasks/${data.knownTaskId}"

Captured response values use:

"${capture.taskId}"

These values are populated during test execution from earlier HTTP responses.

Capture Example

The repository includes a dedicated capture example that demonstrates creating a resource, capturing values from the response, and using those values in subsequent requests.

The repository includes a dedicated capture example:

examples/api-tests-capture.json

The example demonstrates:

  • creating a resource
  • capturing values from the response
  • reusing those values in subsequent requests
  • following captured hypermedia links

Assertion engine

The assertion library currently supports:

exists
equals
contains
oneOf
type
range
isArray
hasProperties
length
minLength (deprecated)
each
eachProperty

Native type assertions support:

string
number
boolean
array
object
null

Example native type assertion:

{
  "path": "$.priority",
  "type": "number"
}

Example optional property assertion:

{
  "path": "$",
  "each": {
    "property": "description",
    "optional": true,
    "type": "string"
  }
}

This assertion means:

"description" may be absent
if present, it must still validate as a string

Traversal semantics

TRAM distinguishes between arrays and object maps.

Use:

  • each for arrays
  • eachProperty for object maps

Examples:

[
  {...},
  {...}
]
=> each
{
  "self": {...},
  "edit": {...}
}
=> eachProperty

TRAM also distinguishes between:

  • path for structural traversal
  • property for scalar leaf checks

Example structural traversal:

{
  "path": "$",
  "each": {
    "path": "$._links",
    "eachProperty": {
      "hasProperties": ["href", "method"]
    }
  }
}

Example scalar leaf assertion:

{
  "path": "$",
  "each": {
    "property": "status",
    "equals": "active"
  }
}

The assertion model supports:

  • collection traversal
  • nested traversal
  • object-map iteration
  • native value validation
  • optional property validation
  • hypermedia affordance validation

while remaining declarative and inspectable.

TRAM intentionally limits type assertions to native value categories.

The following are currently out of scope:

uuid
email
uri
date-time
schema validation

Workflow-oriented behavioral modeling

TRAM manifests can model operational workflows rather than isolated endpoint checks.

TRAM models workflows through declarative sequencing rather than embedded scripting.

A workflow manifest may:

  • create resources
  • retrieve intermediate state
  • apply mutations
  • verify accumulated final state

This allows manifests to function as executable operational narratives.

Example workflow sequence:

create
read after create
edit
update status
assign user
set due date
read final accumulated state

Header assertion semantics

Header assertions use:

{
  "name": "content-type",
  "contains": "application/json"
}

Do not use path for header assertions.


Request body support

TRAM supports multiple request body encodings:

json
form
text

Example:

{
  "method": "PUT",
  "path": "/tasks/task-1/status",
  "bodyType": "form",
  "body": "$data.task.updateStatus"
}

Running the sample project

Start the sample API:

node sample-api/index.js

Run the test suite:

tram api-tests.json

Verbose mode:

tram api-tests.json --verbose

Generate an HTTP transcript:

tram api-tests.json --transcript transcript.http

Generate a machine-readable report:

tram api-tests.json --report report.json

Generate both artifacts:

tram api-tests.json \
    --report report.json \
    --transcript transcript.http

Documentation

Quick Start

Practical walkthrough for:

  • running the sample project
  • inspecting manifests
  • understanding assertions
  • understanding runtime interpolation
  • exploring behavioral API testing workflows

Manifest Specification

Authoritative executable manifest model.

Defines:

  • manifest structure
  • request configuration
  • assertion syntax
  • optional property assertions
  • traversal behavior
  • runtime interpolation
  • stable run-scoped variables
  • collection assertions
  • object-map assertions
  • native type assertions
  • body handling

Explainer

Architectural discussion of:

  • behavioral assertions
  • operational artifacts
  • hypermedia-oriented testing
  • generated systems
  • workflow-oriented behavioral modeling
  • AI-assisted workflows

Validation pipeline

TRAM validates manifests before executing HTTP requests. Validation may also be invoked directly from the command line using the --validate option.

Validation currently includes:

  • manifest file existence
  • manifest JSON parsing
  • top-level manifest structure
  • required test fields
  • supported HTTP methods
  • supported request body types
  • duplicate test IDs
  • capture declarations
  • capture path syntax
  • capture identifier syntax

Example:

tram api-tests.json --validate

If the manifest is valid, TRAM reports success and exits without executing any requests. If validation fails, TRAM reports the validation errors and exits with a non-zero status.

Invalid manifests fail before execution begins.

TRAM reports multiple manifest validation problems in a single pass when possible.

TRAM distinguishes between:

  • manifest authoring failures
  • request/runtime failures
  • behavioral assertion failures

Reporting philosophy

TRAM can produce several complementary views of a test run.

  • concise console output
  • HTTP transcript of the observed conversation
  • machine-readable behavioral report

The transcript records the observed HTTP conversation.

The report evaluates that conversation against the behavioral expectations expressed in the manifest.

Manifest validation is treated as a first-class operation, allowing behavioral models to be reviewed independently of execution.


Design philosophy

TRAM is intentionally conservative.

Current releases avoid:

  • framework dependencies
  • custom scripting
  • setup/teardown orchestration
  • schema engines
  • plugin systems
  • hidden runtime behavior

The current emphasis is:

  • clarity
  • predictability
  • behavior visibility
  • manifest ergonomics
  • reviewability

AI Coaching direction

The AI Coaching direction includes:

  • layered manifest generation
  • traversal-aware assertion guidance
  • workflow modeling support
  • governance distinction guidance
  • collaborative review cycles
  • behavioral decomposition assistance

The eventual AI Coach layer will:

  1. inspect server.js and/or API Story documents
  2. identify API behaviors
  3. propose candidate tests
  4. distinguish happy and sad paths
  5. review assertions collaboratively
  6. generate plausible first-pass manifests

The goal is not automatic test generation alone.

The goal is helping users understand behavioral API testing while collaboratively constructing executable manifests.


Example layer progression

Typical TRAM progression:

Level 0 — endpoint availability
Level 1 — representation structure
Level 2 — lookup and filtering behavior
Level 3 — isolated mutation behavior
Level 4 — workflow continuity
Level 5 — governance and constraints

TRAM draws inspiration from:

  • behavioral testing
  • executable specifications
  • hypermedia-oriented design
  • affordance-centric APIs
  • augmentation-oriented AI systems
  • coaching-based human/machine collaboration

Status

Early experimental project.

Interfaces and manifest formats will evolve during v0.x development.

Project repository:

https://github.com/mamund/tram

Contributors

mamund

110 commits

mamund/tram

test runner for assertion manifests

JavaScript

4

110 commits

updated Sep 4, 2026

See the code

See what people are saying (1)

README

TRAM

TRAM (Test Runner for Assertion Manifests) is a framework for creating executable behavioral models of HTTP APIs. It validates those models and gathers evidence from running APIs to verify that observable behavior matches the intended design.

Rather than focusing on implementation details, TRAM focuses on what can be observed at the API surface: the resources, actions, workflows, and rules that define how a system behaves. Assertions are organized into progressively richer layers, moving from endpoint availability and response structure to business behavior, workflows, and governance constraints. This allows teams to express operational intent as a durable behavioral model that remains valuable even as implementations evolve.

TRAM (Test Runner for Assertion Manifests)
TRAM screenshot of test run

Documentation

TRAM combines:

  • a manifest-driven test format
  • a reusable assertion engine
  • a portable HTTP test runner
  • stable runtime interpolation support
  • native type assertions
  • optional property assertions
  • object-map and collection assertions
  • layered behavioral modeling
  • workflow-oriented behavioral validation
  • an AI Coaching workflow focused on learning and augmentation rather than pure automation

What's New in Manifest 0.2

Manifest version 0.2 introduces response capture.

Capture allows a test to extract values from an HTTP response (such as resource identifiers or hypermedia links) and reuse those values in subsequent requests. This makes it possible to write behavioral tests for APIs that generate identifiers dynamically or expose navigational affordances.

Earlier (0.1) manifests remain supported and continue to execute without modification.


Output artifacts

A TRAM run can produce several complementary artifacts.

ArtifactPurpose
ManifestDefines the expected API behavior.
HTTP TranscriptRecords the observed HTTP request/response conversation.
ReportEvaluates the observed behavior against the manifest.
EvidenceThe complete collection of artifacts from a test run.

The transcript and report serve different purposes.

The HTTP Transcript records what happened during execution. The Report evaluates whether the observed behavior satisfied the behavioral expectations expressed in the manifest.


Smallest complete TRAM manifest

{
  "name": "Smallest TRAM manifest",
  "config": {
    "baseUrl": "http://localhost:3000"
  },
  "tests": [
    {
      "name": "GET /tasks returns 200",
      "method": "GET",
      "path": "/tasks",
      "expect": {
        "status": 200
      }
    }
  ]
}

This is the smallest useful complete TRAM manifest:

  • one manifest
  • one test
  • one request
  • one behavioral assertion

Capturing Values

The capture property records values observed in an HTTP response and makes them available to later requests.

{
  "id": "task-create",
  "method": "POST",
  "path": "/tasks",
  "bodyType": "json",
  "body": "$data.task.capture.valid",
  "expect": {
    "status": 201
  },
  "capture": {
    "createdTaskId": "body.id"
  }
}

Later tests can reference the captured value:

{
  "id": "task-get",
  "method": "GET",
  "path": "/tasks/${capture.createdTaskId}",
  "expect": {
    "status": 200
  }
}

Capture works with response bodies, headers, and other observable response values. See the Manifest Specification for the complete syntax.


Why TRAM exists

TRAM explores a narrow problem:

How do we make behavioral expectations directly visible, portable, executable, and reviewable?

The core artifact is the manifest:

api-tests.json

The manifest defines:

  • requests
  • request bodies
  • assertions
  • expected behaviors
  • shared test data
  • runtime interpolation values

Assertions become directly inspectable operational statements.

Simple behavioral assertion:

{
  "path": "$.status",
  "equals": "active"
}

Meaning:

The resource status must be "active".

Optional property assertion for evolving representations:

{
  "path": "$",
  "each": {
    "property": "description",
    "optional": true,
    "type": "string"
  }
}

Meaning:

"description" may be absent.
If present, it must be a string.

Hypermedia affordance assertion:

{
  "path": "$._links",
  "eachProperty": {
    "hasProperties": ["href", "method"]
  }
}

Meaning:

Every affordance must define both a target URL and an HTTP method.

Collection behavioral assertion:

{
  "path": "$",
  "each": {
    "property": "status",
    "oneOf": ["active", "pending", "completed"]
  }
}

Meaning:

Every returned resource must have a recognized workflow state.

Nested affordance traversal assertion:

{
  "path": "$",
  "each": {
    "path": "$._links",
    "eachProperty": {
      "hasProperties": ["href", "method"]
    }
  }
}

Meaning:

Every returned resource must expose affordances
that define both a target URL and an HTTP method.

TRAM supports partial and evolving representations while preserving explicit behavioral validation.


Behavioral layering

TRAM organizes behavioral testing into six progressive layers.

LevelFocusQuestion
0SurfaceCan the API be reached?
1ShapeDo resources and affordances appear correctly?
2Safe behaviorDo navigation, lookup, filtering, and query interactions behave correctly?
3Unsafe behaviorDo isolated state-changing actions behave correctly?
4WorkflowCan meaningful operational narratives be completed successfully?
5GovernanceAre policies, constraints, and semantic rules enforced correctly?
TRAM Testing Maturity Pyramid

The layers are additive rather than replacement-oriented. Each layer narrows debugging scope while preserving readable behavioral intent.


Project goals

TRAM is designed around several principles:

  • behavioral tests over implementation tests
  • portable manifests over framework lock-in
  • readable intent over clever abstractions
  • explicitness over hidden runtime behavior
  • low-noise reporting
  • augmentation and learning over one-shot generation

The long-term direction is an AI Coach that helps users learn behavioral API testing while collaboratively constructing executable manifests.


Current implementation

Current implementation includes:

  • manifest specification (api-tests.json)
  • dependency-free assertion engine
  • dependency-free HTTP runner
  • body/header/status assertions
  • collection assertions (each)
  • object-map assertions (eachProperty)
  • native type assertions (type)
  • optional property assertions (optional)
  • range assertions (range)
  • stable run-scoped variables
  • runtime interpolation (${data.*})
  • object injection ($data.*)
  • capture values from responses and reuse them in later requests
  • happy-path and sad-path testing
  • JSON, form, and text request body support
  • workflow-oriented behavioral modeling
  • machine-readable reporting
  • real API validation against a sample CRUD-style task API
  • HTTP transcript generation

Project structure

.
├── README.md
├── package.json
├── api-tests.json
├── bin/
│   └── tram
├── lib/
│   └── assertions.js
├── docs/
└── sample-api/

CLI usage

tram <manifest-file> [options]

Options:

-v, --verbose              Print passing assertion details
-r, --report <file>        Write behavioral report (JSON)
-t, --transcript <file>    Write HTTP transcript
--validate                 Validate the manifest without making HTTP requests
-h, --help                 Show help

CLI installation

Local development setup

Clone the repository:

git clone https://github.com/mamund/2026-05-tram.git
cd 2026-05-tram

macOS/Linux:

chmod +x bin/tram
npm link

Windows:

npm link

Then run:

tram api-tests.json

Validate the manifest without contacting the sample API:

tram api-tests.json --validate

This performs structural validation of the manifest and exits without sending any HTTP requests.


Core concepts

Manifest-driven testing

Tests are defined declaratively in a manifest:

{
  "name": "Create task",
  "method": "POST",
  "path": "/tasks/${data.stableId}",
  "body": "$data.task.valid",
  "expect": {
    "status": 201,
    "body": [
      {
        "path": "$.status",
        "equals": "active"
      }
    ]
  }
}

The manifest acts as both:

  • executable configuration
  • behavioral operational artifact

Shared runtime data

The data section stores reusable request and runtime values.

Example:

{
  "data": {
    "stableId": "${randomId}"
  }
}

The generated value remains stable throughout the current test run.

Later requests can reference the same value:

{
  "path": "/tasks/${data.stableId}"
}

TRAM also supports response capture.

Values observed in one response may be reused later in the same test run.

Example:

"capture": {
  "taskId": "body.id"
}

Later requests can reference the captured value:

"path": "/tasks/${capture.taskId}"

This enables coordinated multi-step behavioral flows without introducing custom scripting.


Runtime interpolation semantics

Use:

"$data.someObject"

when injecting structured runtime objects.

Use:

"${data.someValue}"

when interpolating values inside strings.

Examples:

Correct object injection:

"body": "$data.createTask"

Correct string interpolation:

"path": "/tasks/${data.knownTaskId}"

Captured response values use:

"${capture.taskId}"

These values are populated during test execution from earlier HTTP responses.

Capture Example

The repository includes a dedicated capture example that demonstrates creating a resource, capturing values from the response, and using those values in subsequent requests.

The repository includes a dedicated capture example:

examples/api-tests-capture.json

The example demonstrates:

  • creating a resource
  • capturing values from the response
  • reusing those values in subsequent requests
  • following captured hypermedia links

Assertion engine

The assertion library currently supports:

exists
equals
contains
oneOf
type
range
isArray
hasProperties
length
minLength (deprecated)
each
eachProperty

Native type assertions support:

string
number
boolean
array
object
null

Example native type assertion:

{
  "path": "$.priority",
  "type": "number"
}

Example optional property assertion:

{
  "path": "$",
  "each": {
    "property": "description",
    "optional": true,
    "type": "string"
  }
}

This assertion means:

"description" may be absent
if present, it must still validate as a string

Traversal semantics

TRAM distinguishes between arrays and object maps.

Use:

  • each for arrays
  • eachProperty for object maps

Examples:

[
  {...},
  {...}
]
=> each
{
  "self": {...},
  "edit": {...}
}
=> eachProperty

TRAM also distinguishes between:

  • path for structural traversal
  • property for scalar leaf checks

Example structural traversal:

{
  "path": "$",
  "each": {
    "path": "$._links",
    "eachProperty": {
      "hasProperties": ["href", "method"]
    }
  }
}

Example scalar leaf assertion:

{
  "path": "$",
  "each": {
    "property": "status",
    "equals": "active"
  }
}

The assertion model supports:

  • collection traversal
  • nested traversal
  • object-map iteration
  • native value validation
  • optional property validation
  • hypermedia affordance validation

while remaining declarative and inspectable.

TRAM intentionally limits type assertions to native value categories.

The following are currently out of scope:

uuid
email
uri
date-time
schema validation

Workflow-oriented behavioral modeling

TRAM manifests can model operational workflows rather than isolated endpoint checks.

TRAM models workflows through declarative sequencing rather than embedded scripting.

A workflow manifest may:

  • create resources
  • retrieve intermediate state
  • apply mutations
  • verify accumulated final state

This allows manifests to function as executable operational narratives.

Example workflow sequence:

create
read after create
edit
update status
assign user
set due date
read final accumulated state

Header assertion semantics

Header assertions use:

{
  "name": "content-type",
  "contains": "application/json"
}

Do not use path for header assertions.


Request body support

TRAM supports multiple request body encodings:

json
form
text

Example:

{
  "method": "PUT",
  "path": "/tasks/task-1/status",
  "bodyType": "form",
  "body": "$data.task.updateStatus"
}

Running the sample project

Start the sample API:

node sample-api/index.js

Run the test suite:

tram api-tests.json

Verbose mode:

tram api-tests.json --verbose

Generate an HTTP transcript:

tram api-tests.json --transcript transcript.http

Generate a machine-readable report:

tram api-tests.json --report report.json

Generate both artifacts:

tram api-tests.json \
    --report report.json \
    --transcript transcript.http

Documentation

Quick Start

Practical walkthrough for:

  • running the sample project
  • inspecting manifests
  • understanding assertions
  • understanding runtime interpolation
  • exploring behavioral API testing workflows

Manifest Specification

Authoritative executable manifest model.

Defines:

  • manifest structure
  • request configuration
  • assertion syntax
  • optional property assertions
  • traversal behavior
  • runtime interpolation
  • stable run-scoped variables
  • collection assertions
  • object-map assertions
  • native type assertions
  • body handling

Explainer

Architectural discussion of:

  • behavioral assertions
  • operational artifacts
  • hypermedia-oriented testing
  • generated systems
  • workflow-oriented behavioral modeling
  • AI-assisted workflows

Validation pipeline

TRAM validates manifests before executing HTTP requests. Validation may also be invoked directly from the command line using the --validate option.

Validation currently includes:

  • manifest file existence
  • manifest JSON parsing
  • top-level manifest structure
  • required test fields
  • supported HTTP methods
  • supported request body types
  • duplicate test IDs
  • capture declarations
  • capture path syntax
  • capture identifier syntax

Example:

tram api-tests.json --validate

If the manifest is valid, TRAM reports success and exits without executing any requests. If validation fails, TRAM reports the validation errors and exits with a non-zero status.

Invalid manifests fail before execution begins.

TRAM reports multiple manifest validation problems in a single pass when possible.

TRAM distinguishes between:

  • manifest authoring failures
  • request/runtime failures
  • behavioral assertion failures

Reporting philosophy

TRAM can produce several complementary views of a test run.

  • concise console output
  • HTTP transcript of the observed conversation
  • machine-readable behavioral report

The transcript records the observed HTTP conversation.

The report evaluates that conversation against the behavioral expectations expressed in the manifest.

Manifest validation is treated as a first-class operation, allowing behavioral models to be reviewed independently of execution.


Design philosophy

TRAM is intentionally conservative.

Current releases avoid:

  • framework dependencies
  • custom scripting
  • setup/teardown orchestration
  • schema engines
  • plugin systems
  • hidden runtime behavior

The current emphasis is:

  • clarity
  • predictability
  • behavior visibility
  • manifest ergonomics
  • reviewability

AI Coaching direction

The AI Coaching direction includes:

  • layered manifest generation
  • traversal-aware assertion guidance
  • workflow modeling support
  • governance distinction guidance
  • collaborative review cycles
  • behavioral decomposition assistance

The eventual AI Coach layer will:

  1. inspect server.js and/or API Story documents
  2. identify API behaviors
  3. propose candidate tests
  4. distinguish happy and sad paths
  5. review assertions collaboratively
  6. generate plausible first-pass manifests

The goal is not automatic test generation alone.

The goal is helping users understand behavioral API testing while collaboratively constructing executable manifests.


Example layer progression

Typical TRAM progression:

Level 0 — endpoint availability
Level 1 — representation structure
Level 2 — lookup and filtering behavior
Level 3 — isolated mutation behavior
Level 4 — workflow continuity
Level 5 — governance and constraints

TRAM draws inspiration from:

  • behavioral testing
  • executable specifications
  • hypermedia-oriented design
  • affordance-centric APIs
  • augmentation-oriented AI systems
  • coaching-based human/machine collaboration

Status

Early experimental project.

Interfaces and manifest formats will evolve during v0.x development.

Project repository:

https://github.com/mamund/tram

Contributors

mamund

110 commits

Languages

JavaScript

100.0%