
silk
Markdown based document-driven web API testing.
PROJECT STATUS: Looking for BETA testers.

Markdown API
Tests are made up of documents written in Markdown.
# Group - Top level headings represent groups of requests
## GET /path - Second level headings represent a request
- Code blocks with three back tics represent bodies
* Field: value - Lists describe headers and assertions
* ?param=value - Request parameters
=== seperators break requests from responses
- Comments (starting with
//) are ignored
- Plain text is ignored to allow you to add documentation
- Inline back tics are ignored and are available for formatting
Document structure
A document is made up of:
- A request
=== seperator
- Assertions
Requests
A request starts with ## and must have an HTTP method, and a path:
## METHOD /path
Examples include:
## GET /people
## POST /people/1/comments
## DELETE /people/1/comments/2
Request body (optional)
To specify a request body (for example for POST requests) use a codeblock using backtics (```):
```
{"name": "Silk", "release_year": 2016}
```
You may specify request headers using lists (prefixed with *):
* Content-Type: "application/json"
* X-Custom-Header: "123"
Request parameters (optional)
Adding parameters to the path (like GET /path?q=something) can be tricky, especially when you consider escaping etc. To address this, Silk supports parameters like lists:
* ?param=value
The parameters will be correctly added to the URL path before the request is made.
Assertions
Following the === separator, you can specify assertions about the response. At a minimum, it is recommended that you assert the status code to ensure the request succeeded:
* Status: 200
You may also specify response headers in the same format as request headers:
* Content-Type: "application/json"
* X-MyServer-Version: "v1.0"
If any of the headers do not match, the test will fail.
Validating data
You can optionally include a verbatim body using ``` code blocks. If the response body does not exactly match, the test will fail:
```
{"id": 1, "name": "Silk", "release_year": 2016}
```
Alternatively, you can specify a list (using *) of data fields to assert accessible via the Data object:
* Status: 201
* Content-Type: "application/json"
* Data.name: "Silk"
* Data.release_year: 2016
* Data.tags[0]: "testing"
* Data.tags[1]: "markdown"
- NOTE: Currenly this feature is only supported for JSON APIs.
Regex
Values may be regex, if they begin and end with a forward slash: /. The assertion will pass if the value (after being turned into a string) matches the regex.
* Status: /^2.{2}$/
* Content-Type: /application/json/
The above will assert that:
- The status beings with
2, and
- The
Content-Type contains application/json
Command line
The silk command runs tests against an HTTP endpoint.
Usage:
silk -url="{endpoint}" {testfiles}
{url} the endpoint URL (e.g. http://localhost:8080)
{testfiles} path to test files (e.g. ./testfiles)
Notes:
- Omit trailing slash from
url
{testfiles} can include a pattern (e.g. /path/*.silk.md)
Golang
Silk is written in Go and integrates seamlessly into existing testing tools and frameworks. Import the runner package and use RunGlob to match many test files:
package project_test
import (
"testing"
"github.com/matryer/silk/runner"
)
func TestAPIEndpoint(t *testing.T) {
// start a server
s := httptest.NewServer(yourHandler)
defer s.Close()
// run all test files
runner.New(t, s.URL).RunGlob(filepath.Glob("../testfiles/failure/*.silk.md"))
}