aloe

package module
v0.0.0-...-af4311f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2019 License: Apache-2.0 Imports: 8 Imported by: 1

README

Aloe

Build Status Coverage Status GoDoc Go Report Card

Aloe is a declarative API test framework based on ginkgo, gomega and yaml. It aims to help write and read API test cases simpler.

DISCLAIMER:

  • only json API is supported now
  • avoid using Aloe for extremely complex test, use ginkgo directly instead

Terminology

There are two important concepts in aloe:

  • case: case means a test case, for example, get an endpoint and verify its output.
  • context: to simply put, a context is a group of cases. Usually, context is used to init data in database, so that all test cases will be tested in a determined context.

Getting Started

Following is a getting started example for using Aloe. First, create a directory to put context and case yaml files.

mkdir -p test/testdata

Then, define your context in context.yaml.

# test/testdata/context.yaml
summary: "CRUD Test example"
flow:
- description: "Init a product"
  request:
    api: POST /products
    headers:
      "Content-Type": "application/json"
    body: |
      {
        "id": "1",
        "title": "test"
      }
  response:
    statusCode: 201
  definitions:
  - name: "testProductId"
    selector:
    - "id"

As mentioned above, a context is used to run a group of test cases in a determined environment. In the above example, we define a context which simply sends a POST request to /products with product name test; therefore, all test cases in this context will expect product test exists.

Now with context setup, we can start defining case. Here, we define a test case in test/testdata/get.yaml to get and verify product test.

# test/testdata/get.yaml
description: "Try to GET a product"
flow:
- description: "Get the product with title test"
  request:
    api: GET /products/%{testProductId}
    headers:
      "Content-Type": "application/json"
  response:
    statusCode: 200

Finally, some go codes should be written in test directory to run the test case:

func init() {
	aloe.Init(nil)
}

func RunTEST(t *testing.T) {
	aloe.AppendDataDirs("testdata")
	if err := aloe.Env("host", "localhost:8080"); err != nil {
		fmt.Printf("can't set env host: %v", err)
		os.Exit(1)
	}
	if err := aloe.RegisterCleaner(s); err != nil {
		fmt.Printf("can't register cleaner: %v", err)
		os.Exit(1)
	}
	aloe.Run(t)
}

var _ = ginkgo.BeforeSuite(func() {
    s.Register()
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        fmt.Println("can't begin server")
        os.Exit(1)
    }
    go http.Serve(listener, nil)
})

Usage

Variable

Variables can be defined to hold auto-generated value by server (e.g. id). For example:

flow:
- description: "Init a product"
  definitions:
  - name: "testProductId"
    selector:
    - "id"

A variable called testProductId will be defined. The value of testProductId is from the round trip response.

Variable can also be a json snippet.

response:
{
    "id": "111",
    "title": "test",
    "comments":[
        "aaa",
        "bbb"
    ]
}

// id will select value of string
["id"] => 111(without quote)

// empty selector will select whole body
[] => {
    "id": "111",
    "title": "test",
    "comments":[
        "aaa",
        "bbb"
    ]
}

// comments will select partial body
["comments"] => [
    "aaa",
    "bbb"
]

// comments.0 will select first element of array
["comments", "0"] => aaa

If a variables is defined, it can be used in round trip with format %{name}.

Body validator

Body validator is used to validate response fields. Some special validators are predefined, e.g. $regexp

flow:
- description: "Create a product"
  response:
    # validate that id format matches regexp
    # validate that password field is not returned
    body: |
      {
        "id": {
          "$regexp": "[a-zA-Z][a-zA-Z0-9-]{11}"
        },
        "password": {
          "$exists": false,
        },
      }

Now only $regexp and $exists is supported (more special validator will be added in the future).

Cleaner

Cleaner can be used to clean context after all cases in the context are finished.

type Cleaner interface {
    // Name defines cleaner name
    Name() string

    // Clean will be called after all of the cases in the context are
    // finished
    Clean(variables map[string]jsonutil.Variable) error
}

Users can implement their own cleaners and call RegisterCleaner in framework. Then cleaners can be used in context file.

# test/testdata/get.yaml
summary: "Create a product"
flow:
- description: "Create a product"
  request:
    api: POST /products
  response:
    statusCode: 201
cleaner: "productCleaner"
Presetter

Presetter can be used to preset all RoundTrips in the context.

// Presetter defines presetter
type Presetter interface {
    // Name defines name of presetter
    Name() string

    // Preset parse args and set roundtrip template
    Preset(rt *types.RoundTrip, args map[string]string) (*types.RoundTrip,
    error)
}

Users can implement their own presetters and call RegisterPresetter in framework. Then presetters can be used in context file.

# test/testdata/get.yaml
summary: "Create a product"
presetter:
- name: "header"
  args:
    content-type: application/json
flow:
- description: "Create a product"
  request:
    api: POST /products
  response:
    statusCode: 201
Nested context

Context can be nested just like directory. Child context will see all setup in parent context.

tests
└── testdata
    ├── _context.yaml
    ├── basic
    │   ├── _context.yaml
    │   ├── create.yaml
    │   └── update.yaml
    ├── failure
    │   ├── _context.yaml
    │   └── create.yaml
    └── list
        ├── _context.yaml
        └── list_all.yaml

Examples

For more examples, see:

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppendDataDirs

func AppendDataDirs(dataDirs ...string)

AppendDataDirs adds data dirs to the default framework

func CustomizeClient

func CustomizeClient(name string, client *http.Client)

CustomizeClient config http client of default framework

func Env

func Env(key, value string) error

Env sets the env of the default framework

func Init

func Init(defaultConfig *config.Config)

Init inits framework

func RegisterCleaner

func RegisterCleaner(cs ...cleaner.Cleaner) error

RegisterCleaner registers cleaner to the default framework

func RegisterPresetter

func RegisterPresetter(ps ...preset.Presetter) error

RegisterPresetter registers prestter to the default framework

func Run

func Run(t *testing.T)

Run will run the default framework

Types

This section is empty.

Directories

Path Synopsis
examples
Package types defines types used by aloe TODO(liubog2008): split runtime object types and static config object types
Package types defines types used by aloe TODO(liubog2008): split runtime object types and static config object types
utils

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL