Getting Started
Install
Section titled “Install”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:
kis test versionYour first API test (v2 runner)
Section titled “Your first API test (v2 runner)”Create a test directory with a test file and an env file:
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 assertions: - status_code == 201 - response.id != null - response.name == "Ada Lovelace"baseurl: https://jsonplaceholder.typicode.comRun it:
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:
kis test run -t tests/ --junit .kis/test/junit.xml --db .kis/test/results.dbkis test run -t tests/ --html .kis/test/report.html --artifacts .kis/test/artifactsUseful variations:
kis test run -t tests/ --tags smoke # filter by tagkis test run -t tests/ -v baseurl=http://localhost:8080 # override a variablekis test run -t tests/ -e tests/env.yaml -n staging # multi-env file, pick onekis test run -t tests/ --dry-run # validate without calling anythingOne thing that trips up new suites
Section titled “One thing that trips up new suites”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 itNext 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
Your first load test
Section titled “Your first load test”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.01kis 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.030A 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.
Which runner should I use?
Section titled “Which runner should I use?”| You want to… | Use |
|---|---|
| Write functional tests (HTTP, gRPC, database, CLI, streams, browser, script) | kis test run: Test definitions |
| Load test the same suites | kis test load: Load testing |
| Run suites written in the plan/scenario/case hierarchy format | kis test tests: CLI Reference |
| Spread functional or load runs across machines | --orchestrator with test.svc orchestrator and test.svc agent: Server modes |