runn
runn ( means "Run N" ) is a package/tool for running operations following a scenario.
Key features of runn are:
- As a tool for scenario testing.
- As a test helper package for the Go language.
- As a tool for automation.
Usage
runn can run a multi-step scenario following a runbook written in YAML format.
runn can run one or more runbooks.
$ runn list path/to/**/*.yml
Desc Path
-----------------------------------------------------
Login and get projects. path/to/books/login.yml
Login and logout. path/to/books/logout.yml
New project. path/to/books/new.yml
$ runn run path/to/**/*.yml
Login and get projects. ... ok
Login and logout. ... ok
New project. ... ok
3 scenarios, 0 failures
As a test helper package for the Go language.
runn can also behave as a test helper for the Go language.
Run N runbooks using httptest.Server
func TestRouter(t *testing.T) {
ctx := context.Background()
db, err := sql.Open("postgres", "user=root password=root host=localhost dbname=test sslmode=disable")
if err != nil {
log.Fatal(err)
}
ts := httptest.NewServer(NewRouter(db))
t.Cleanup(func() {
ts.Close()
db.Close()
})
o, err := runn.Load("testdata/books/**/*.yml", runn.T(t), runn.Runner("req", ts.URL), runn.DBRunner("db", db))
if err != nil {
t.Fatal(err)
}
if err := o.RunN(ctx); err != nil {
t.Fatal(err)
}
}
Run single runbook using httptest.Server
func TestRouter(t *testing.T) {
ctx := context.Background()
db, err := sql.Open("postgres", "user=root password=root host=localhost dbname=test sslmode=disable")
if err != nil {
log.Fatal(err)
}
ts := httptest.NewServer(NewRouter(db))
t.Cleanup(func() {
ts.Close()
db.Close()
})
o, err := runn.New(runn.T(t), runn.Book("testdata/books/login.yml"), runn.Runner("req", ts.URL), runn.DBRunner("db", db))
if err != nil {
t.Fatal(err)
}
if err := o.Run(ctx); err != nil {
t.Fatal(err)
}
}
Run N runbooks with http.Handler
func TestRouter(t *testing.T) {
ctx := context.Background()
db, err := sql.Open("postgres", "user=root password=root host=localhost dbname=test sslmode=disable")
if err != nil {
log.Fatal(err)
}
t.Cleanup(func() {
db.Close()
})
o, err := runn.Load("testdata/books/**/*.yml", runn.T(t), runn.HTTPRunnerWithHandler("req", NewRouter(db)), runn.DBRunner("db", db))
if err != nil {
t.Fatal(err)
}
if err := o.RunN(ctx); err != nil {
t.Fatal(err)
}
}
Runbook
The runbook file has the following format.
desc: Login and get projects.
runners:
req: https://example.com/api/v1
db: mysql://root:mypass@localhost:3306/testdb
vars:
username: alice
steps:
-
db:
query: SELECT * FROM users WHERE name = '{{ vars.username }}'
-
req:
/login:
post:
body:
application/json:
email: "{{ steps[0].rows[0].email }}"
password: "{{ steps[0].rows[0].password }}"
-
test: steps[1].res.status == 200
-
req:
/projects:
get:
headers:
Authorization: "token {{ steps[1].res.body.session_token }}"
body: null
-
test: steps[3].res.status == 200
-
test: len(steps[3].res.body.projects) > 0

desc
Description of runbook.
runners
Mapping of runners that run steps: of runbook.
In the steps: section, call the runner with the key specified in the runners: section.
Built-in runners such as test runner do not need to be specified in this section.
runners:
ghapi: ${GITHUB_API_ENDPOINT}
idp: https://auth.example.com
db: my:dbuser:${DB_PASS}@hostname:3306/dbname
In the example, each runner can be called by ghapi:, idp: or db: in steps:.
vars
Mapping of variables available in the steps: of runbook.
vars:
username: alice@example.com
token: ${SECRET_TOKEN}
In the example, each variable can be used in {{ vars.username }} or {{ vars.token }} in steps:.
debug
Enable debug output for runn.
debug: true
steps
Steps to run in runbook.
The steps are invoked in order from top to bottom.
Any return values are recorded for each step.
Recorded values can be retrieved with {{ steps[*].* }}.
steps:
-
db:
query: SELECT * FROM users WHERE name = '{{ vars.username }}'
-
req:
/users/{{ steps[0].rows[0].id }}:
get:
body: null
Runner
HTTP Runner: Do HTTP request
Use https:// or http:// scheme to specify HTTP Runner.
When the step is invoked, it sends the specified HTTP Request and records the response.
runners:
ghapi: https://api.github.com
DB Runner: Query a database
Use dsn (Data Source Name) to specify DB Runner.
When step is executed, it executes the specified query the database.
If the query is a SELECT clause, it records the selected rows, otherwise it records last_insert_id and rows_affected .
Support Databases
PostgreSQL:
runners:
mydb: postgres://dbuser:dbpass@hostname:5432/dbname
runners:
db: pg://dbuser:dbpass@hostname:5432/dbname
MySQL:
runners:
testdb: mysql://dbuser:dbpass@hostname:3306/dbname
runners:
db: my://dbuser:dbpass@hostname:3306/dbname
SQLite3:
runners:
db: sqlite:///path/to/dbname.db
runners:
local: sq://dbname.db
Exec Runner: execute command
The exec runner is a built-in runner, so there is no need to specify it in the runners: section.
It execute command using command: and stdin:
-
exec:
command: grep error
stdin: '{{ steps[3].res.rawBody }}'
Test Runner: test using recorded values
The test runner is a built-in runner, so there is no need to specify it in the runners: section.
It evaluates the conditional expression using the recorded values.
-
test: steps[3].res.status == 200
Dump Runner: dump recorded values
The dump runner is a built-in runner, so there is no need to specify it in the runners: section.
It dumps the specified recorded values.
-
dump: steps[4].rows
Include Runner: include other runbook
The include runner is a built-in runner, so there is no need to specify it in the runners: section.
Include runner reads and runs the runbook in the specified path.
Recorded values are nested.
-
include: path/to/get_token.yml
Install
deb:
Use dpkg-i-from-url
$ export RUNN_VERSION=X.X.X
$ curl -L https://git.io/dpkg-i-from-url | bash -s -- https://github.com/k1LoW/runn/releases/download/v$RUNN_VERSION/runn_$RUNN_VERSION-1_amd64.deb
RPM:
$ export RUNN_VERSION=X.X.X
$ yum install https://github.com/k1LoW/runn/releases/download/v$RUNN_VERSION/runn_$RUNN_VERSION-1_amd64.rpm
apk:
Use apk-add-from-url
$ export RUNN_VERSION=X.X.X
$ curl -L https://git.io/apk-add-from-url | sh -s -- https://github.com/k1LoW/runn/releases/download/v$RUNN_VERSION/runn_$RUNN_VERSION-1_amd64.apk
homebrew tap:
$ brew install k1LoW/tap/runn
manually:
Download binary from releases page
docker:
$ docker pull ghcr.io/k1low/runn:latest
go install:
$ go install github.com/k1LoW/runn/cmd/runn@latest
As test helper
$ go get github.com/k1LoW/runn
Alternatives