Skip to content
Talk to our solutions team

Getting Started

Testing ships in kis: kis test <command> runs the test.svc binary, so every command on the CLI Reference page is available through kis test. Check it is present with:

Terminal window
kis test version

Create a test directory with a test file and an env file:

tests/users.yaml
tests:
- name: list-users
tags: [smoke]
steps:
- name: get-users
http:
url: "{{baseurl}}/users"
method: GET
response:
variables:
first_id: "jq: .response[0].id" # extract for the next step
assertions:
- status_code == 200
- response.length > 0
- duration_ms < 2000
- name: fetch-first-user
http:
url: "{{baseurl}}/users/{{first_id}}"
method: GET
assertions:
- status_code == 200
- response.id == first_id # RHS references the scope variable
- name: create-user
steps:
- name: create
http:
url: "{{baseurl}}/users"
method: POST
headers:
Content-Type: application/json
body:
type: raw
payload: '{"name": "Ada Lovelace", "username": "ada", "email": "[email protected]"}'
assertions:
- status_code == 201
- response.id != null
- response.name == "Ada Lovelace"
tests/env.yaml
baseurl: https://jsonplaceholder.typicode.com

Run it:

Terminal window
kis test run -t tests/
auto-discovered env file: tests/env.yaml
• kis test run started (run-id: 57ab053badb098487fd390b2)
▾ tests
✓ get-users 88ms GET https://jsonplaceholder.typicode.com/users → 200
✓ fetch-first-user 100ms GET https://jsonplaceholder.typicode.com/users/1 → 200
✓ create 312ms POST https://jsonplaceholder.typicode.com/users → 201
────────────────────────────────────────────────────────────
2 tests │ 2 passed │ 501ms
────────────────────────────────────────────────────────────

The env file is auto-discovered (env.local.yaml → env.yaml → env.<name>.yaml); results stream to the console; exit code is 0 if everything passed, 1 otherwise. No files are written unless you ask:

Terminal window
kis test run -t tests/ --junit .kis/test/junit.xml --db .kis/test/results.db
kis test run -t tests/ --html .kis/test/report.html --artifacts .kis/test/artifacts

Useful variations:

Terminal window
kis test run -t tests/ --tags smoke # filter by tag
kis test run -t tests/ -v baseurl=http://localhost:8080 # override a variable
kis test run -t tests/ -e tests/env.yaml -n staging # multi-env file, pick one
kis test run -t tests/ --dry-run # validate without calling anything

assertions: belongs to the step, lined up with http:, not indented inside it. Loading is strict, so a misplaced key fails the load and tells you where it belongs, rather than being dropped and leaving a test that asserts nothing:

line 9: field assertions not found in type types.HTTPConfig
"assertions" belongs at step level — unindent it to line up with "http:", not inside it

Next steps:

  • The full YAML schema (HTTP, gRPC, database, CLI, stream, browser and script steps; group steps; hooks; suites): Test definitions
  • Assertion syntax, variable chaining, suite/run shared memory: Assertions and variables
  • Table-driven tests, including rows fetched at runtime: Data-driven tests
  • Script steps and the task namespaces (shell, db, http, csv, llm, …): Scripting

The suite you just wrote is the workload: there is no second format. Point a profile at it:

# load.yaml, beside your tests (the suite loader skips profile files)
profiles:
smoke:
phases:
- type: ramp_up
duration: 15s
start_users: 1
end_users: 10
- type: constant
duration: 30s
users: 10
thresholds:
- metric: p95_latency_ms
operator: lt
value: 500
- metric: error_rate
operator: lt
value: 0.01
Terminal window
kis test load -t tests/ --profiles load.yaml --profile smoke
iterations 5579 failed 169 peak VUs 10 rps 619.7
error rate 3.03%
latency ms min 2.2 avg 11.0 p50 9.5 p90 22.4 p95 28.5 p99 33.5 max 35.7
✓ pass p95_latency_ms lt 500 — actual 28.453
✗ FAIL error_rate lt 0.01 — actual 0.030

A missed threshold exits 1, which is what makes this a CI gate rather than a report. While it runs you get a progress line every second; when it finishes you get a failure breakdown naming what broke.

If the suite authenticates in before_all, that runs once and the token reaches every iteration: load testing an authenticated API needs nothing extra.

Read Load testing before sizing real runs, especially the difference between closed-loop phases (users:, a fixed population) and open-loop ones (rate:, a target RPS you actually hold), and how to spread a run across several machines.

You want to…Use
Write functional tests (HTTP, gRPC, database, CLI, streams, browser, script)kis test run: Test definitions
Load test the same suiteskis test load: Load testing
Run suites written in the plan/scenario/case hierarchy formatkis test tests: CLI Reference
Spread functional or load runs across machines--orchestrator with test.svc orchestrator and test.svc agent: Server modes