gosert

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2018 License: MIT Imports: 10 Imported by: 0

README

logo
Gosert

A structured assertion library based on gomega.

The gosert library is an attempt to make assertions on structured objects nice and clean. This project is influenced by the golden file idea.

Goals include:

  • Simplicity. Dead simple API.

  • Flexibility. Allow the user to express constraints on fields (not just hard-coded values).

  • Presentation agnostic. Assume a minimal set of base data types, and use parser interface to work over the data (so JSON, YAML etc all work).

Overview

The library allows the user to define golden files that looks largely the same as the actual data, with gomega like DSL for defining constraints.

Example:

# Actual JSON
{
  "userId": "0001",
  "name": "Ethan Hunt",
  "age": 36,
  "interestes": ["climbing", "jogging", "marshal arts"],
  "address": ["IMF", "New York", "US"]
  "connections": [
    {
      "id": "0002",
      "name": "Julia Meade",
      "relationship": "ex"
    },
    {
      "id": "0003",
      "name": "Ilsa Faust",
      "relationship": "unclear"
    }
  ],
  "updatedAt": "2018-10-05T12:13:14.123Z"
}

# Golden File
{
  "userId": "0001",
  "name": "Ethan Hunt",
  "age": 36,
  "interestes": ["climbing", "marshal arts", "jogging"], // By default order doesn't matter
  "address": "{{Not(BeEmpty())}}", // Assert the array is not empty
  "connections": [
    {
      "_gst_id": "id=0002", // Match element containing "id": "0002"
      "id": "0002",
      "name": "Julia Meade",
      "relationship": "ex"
    },
    {
      "_gst_id": "id=0003",
      "id": "0003",
      "name": "Ilsa Faust",
      "relationship": "unclear"
    }
  ],
  "updatedAt": "{{BeTimestamp(2018-10-05T12:13:14.000Z, 5000)}}" // This means 2018-10-05T12:13:14.000Z +/- 5 seconds
}

Code example:

import (
  . "github.com/onsi/gomega"
  . "github.com/mina-akimi/gosert"
)

var _ = It("Test", func() {
    actual := `
    {
      "userId": "0001",
      "name": "Ethan Hunt",
      "age": 36,
      "interestes": ["climbing", "jogging", "marshal arts"],
      "address": ["IMF", "New York", "US"]
      "connections": [
        {
          "id": "0002",
          "name": "Julia Meade",
          "relationship": "ex"
        },
        {
          "id": "0003",
          "name": "Ilsa Faust",
          "relationship": "unclear"
        }
      ],
      "updatedAt": "2018-10-05T12:13:14.123Z"
    }
    `
    Expect(actual).To(MustMatcher(NewJSONMatcherFromFile("path/to/file", nil)))
})

Data Types

The following base types are supported

  • String
  • Number (including integers, floats)
  • Boolean
  • Object
  • Array

Functions

Functions are string values enclosed in {{}}.

Function Applicable Data Type Meaning Example
{{BeEmpty()}} String, Array The object is empty or the key is not present. These will all match: * "" * [] * The key is missing
{{Not(BeEmpty())}} String, Array The object is not empty
{{BeNumerically(<comparator>, <values>)}} Number See here {{BeNumerically(~, 123, 0.01)}}
{{BeTimestamp(<time>, <delta>)}} String * <time> must be of RFC3339 format * <delta> is number of milliseconds {{BeTimestamp(2018-10-05T12:13:14.000Z, 5000)}}

Advanced Usage

Variable Substitution

Variables can be defined in golden files in the form ${{MY_VAR}}. When creating a matcher, the user must supply a map[string]string mapping the variable names to values.

If any variable is not defined in the value map, an error is returned.

Array Assertion

By default, ordering is ignored.

For base type array, the expected value can be an array of base values.

For object array, the expected values must contain a field called _gst_id with value <key_name>=<value> (see example above).

One requirement is that all expected objects in the same array must define the same <key_name>, otherwise an error occurs.

Multipart File

You can define multiple objects (both fixture and expected objects) in a single file.

Example golden file:

### key=my_fixture, my fixture
{
    "foo": "bar",
    "baz": "${{MY_VAR}}",
    "quux": "${{NOW}}"
}

### key=my_matcher, my awesome matcher
{
    "foo": "bar",
    "baz": "{{Not(BeEmpty())}}",
    "quux": "{{BeTimestamp(${{NOW}}, 5000)}}"
}

Note each object must be preceded by a line like this:

### key=<object_name>, <my comments>

The the object can be read using MultipartReader:

r := MustReader(NewMultipartReaderFromFile(
    file,
    map[string]string{
        "MY_VAR": "baz",
        "NOW":    "2018-10-05T12:13:14.123Z",
    },
    matcher.JSONParserInstance,
))

Expect(r.GetData("my_fixture")).To(r.MustGetMatcher("my_matcher"))

Comments

Any line starting with # (note the space after hash) is a comment and will be ignored by the reader.

Examples

See https://github.com/mina-akimi/gosert/blob/master/matcher/dsl_test.go for more examples.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MustRead

func MustRead(path string, vars map[string]string) []byte

MustRead panics if error occurs.

func Read

func Read(path string, vars map[string]string) ([]byte, error)

Read reads a file with variables replaced.

Types

type Matcher

type Matcher struct {
	// contains filtered or unexported fields
}

Matcher implements types.GomegaMatcher

func MustMatcher

func MustMatcher(m *Matcher, err error) *Matcher

MustMatcher can be used with create matcher functions. This panics if the create function returns err != nil.

func NewJSONMatcher

func NewJSONMatcher(data []byte, vars map[string]string) (*Matcher, error)

NewJSONMatcher returns a new matcher.

func NewJSONMatcherFromFile

func NewJSONMatcherFromFile(path string, vars map[string]string) (*Matcher, error)

NewJSONMatcherFromFile returns a new matcher.

func NewMatcher

func NewMatcher(data []byte, vars map[string]string, parser matcher.Parser) (*Matcher, error)

NewMatcher returns a new matcher. vars is used to replace variables in data.

func NewMatcherFromFile

func NewMatcherFromFile(path string, vars map[string]string, parser matcher.Parser) (*Matcher, error)

NewMatcher returns a new matcher. The expected value is read from path. vars is used to replace variables in data.

func (*Matcher) FailureMessage

func (m *Matcher) FailureMessage(actual interface{}) string

FailureMessage returns failure message.

func (*Matcher) Match

func (m *Matcher) Match(actual interface{}) (bool, error)

Match matches a `*datatype.Timestamp`.

func (*Matcher) NegatedFailureMessage

func (m *Matcher) NegatedFailureMessage(actual interface{}) string

NegatedFailureMessage returns negated failure message.

type MultipartReader

type MultipartReader struct {
	// contains filtered or unexported fields
}

MultipartReader represents a read for file containing multiple objects (some as fixtures and some as expected values)

Example:

### key=my_fixture, my fixture
{
  "foo": "bar",
  "baz": "${{MY_VAR}}",
  "quux": "${{NOW}}"
}

# This is a comment.  Any line starting with `# ` is a comment and is ignored (note the space after hash).
### key=my_matcher, my awesome matcher
{
  "foo": "bar",
  "baz": "{{Not(BeEmpty())}}",
  "quux": "{{BeTimestamp(${{NOW}}, 5000)}}"
}

func MustReader

func MustReader(r *MultipartReader, err error) *MultipartReader

MustReader panics if an error occurs.

func NewMultipartReader

func NewMultipartReader(data []byte, vars map[string]string, parser matcher.Parser) (*MultipartReader, error)

NewMultipartReader returns a new reader.

func NewMultipartReaderFromFile

func NewMultipartReaderFromFile(path string, vars map[string]string, parser matcher.Parser) (*MultipartReader, error)

NewMultipartReader returns a new reader.

func (*MultipartReader) GetData

func (r *MultipartReader) GetData(key string) []byte

GetData returns data with variables substituted.

func (*MultipartReader) GetMatcher

func (r *MultipartReader) GetMatcher(key string) (*Matcher, error)

GetData returns *Matcher with variables substituted.

func (*MultipartReader) MustGetMatcher

func (r *MultipartReader) MustGetMatcher(key string) *Matcher

MustGetMatcher panics if an error occurs.

func (*MultipartReader) UpdateVars

func (r *MultipartReader) UpdateVars(vars map[string]string) error

UpdateVars updates r's variable substitution. New matchers must be generated to take effect.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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