Skip to content
axxbetadocs
GitHub

Quickstart

View .mdOpen in Claude

In this tutorial, we’ll install Axx, create a project, and write a scenario that tests a small web server running on your machine. We’ll run it and watch it pass, then break it on purpose to see what a failure looks like.

It takes about ten minutes. You’ll need a terminal, Go 1.27 or newer to install Axx, and Python 3, which we’ll use as the web server.

Install Axx with Go:

Terminal window
go install github.com/nimbusxr/axx/cmd/axx@latest

Check that your shell finds it:

Terminal window
axx version

Axx prints its version. If your shell says command not found, add Go’s bin directory to your PATH (export PATH="$PATH:$(go env GOPATH)/bin") and try again.

Make a directory for the project and let Axx set it up:

Terminal window
mkdir hello-axx
cd hello-axx
axx init
Terminal window
create axx.yaml
create axx-packs.yaml
create features/smoke.feature
create .github/workflows/acceptance.yml
create AGENTS.md
create .gitignore
next: edit apps in axx.yaml, then `axx doctor` and `axx run`

Axx created a configuration file, axx.yaml, and a first feature file, features/smoke.feature. We’ll change both. It also created axx-packs.yaml, the list of the packs of steps the project uses. It lists rest, whose steps send HTTP requests, and that’s all we need. We won’t need the other files in this tutorial.

Our web server will serve the files in this directory. Create a small JSON file for it:

Terminal window
echo '{"message": "Hello, axx"}' > hello.json

Open axx.yaml. At the bottom, replace the whole apps: section with this one:

axx.yaml
apps:
hello-axx:
command: python3 -m http.server 8000
ready:
http:
url: http://${sys:local.host}:8000/

Axx now knows how to start the server, and how to tell when it’s ready: when http://localhost:8000/ answers.

Replace everything in features/smoke.feature with:

features/smoke.feature
Feature: Hello axx
Background:
Given the hello-axx service with the following properties:
| url | http://${sys:local.host}:8000 |
Scenario: The service says hello
Given a GET request to /hello.json
When the request is executed
Then the response status code is 200
And the response payload property message is 'Hello, axx'

Every line is a step Axx already knows. The Background registers the server as a service named hello-axx. The scenario sends it a request and checks the answer.

Before running anything, ask Axx to check every line:

Terminal window
axx validate
Terminal window
axx: preparing rest (once; cached for later runs)
axx: ready in 31s
1 file, 1 scenario, 5 steps: ok

Axx matched each line to one of its steps, without starting the server. The first time, it also prepared itself with the project’s packs. It won’t need to do that again.

Terminal window
axx run
Terminal window
axx: starting hello-axx (logs: .axx/logs/apps.log)
Feature: Hello axx
Scenario: The service says hello # features/smoke.feature:7
✓ Given the hello-axx service with the following properties: (background)
| url | http://${sys:local.host}:8000 |
✓ Given a GET request to /hello.json
✓ When the request is executed
log: GET http://localhost:8000/hello.json -> 200 OK (4ms, 26 bytes)
attachment: response body (application/json, 26 B)
{"message": "Hello, axx"}
✓ Then the response status code is 200
✓ And the response payload property message is 'Hello, axx'
1 scenario (1 passed)
5 steps (5 passed)
Finished in 4ms

Notice what happened. Axx started the web server, waited until it answered, ran the scenario, and stopped the server again. Under the request step, the log: line shows the request Axx sent, and the attachment shows the response it got back.

Change the last line of features/smoke.feature so it expects a different message:

And the response payload property message is 'Hello, world'

Run it again:

Terminal window
axx run
Terminal window
axx: starting hello-axx (logs: .axx/logs/apps.log)
Feature: Hello axx
Scenario: The service says hello # features/smoke.feature:7
✓ Given the hello-axx service with the following properties: (background)
| url | http://${sys:local.host}:8000 |
✓ Given a GET request to /hello.json
✓ When the request is executed
log: GET http://localhost:8000/hello.json -> 200 OK (2ms, 26 bytes)
attachment: response body (application/json, 26 B)
{"message": "Hello, axx"}
✓ Then the response status code is 200
✗ And the response payload property message is 'Hello, world'
Response payload property message is not Hello, world
expected: "Hello, world"
actual: "Hello, axx"
Failed scenarios:
✗ The service says hello # features/smoke.feature:7
rerun: axx run features/smoke.feature:7
1 scenario (1 failed)
5 steps (1 failed, 4 passed)
Finished in 3ms

Axx marks the step that failed and shows what it expected next to what it got. It also prints a command that reruns only this scenario.

Change the line back to 'Hello, axx' and run axx run once more. The scenario passes again.

You installed Axx, told it how to start a service, wrote a scenario, ran it, and read a failure. That’s the loop you’ll use with every Axx suite.

Next, in Your first suite, we’ll test a real service with a database and a dependency it calls.