A yaml data-driven testing format together with golang testing library

Specified

Yaml data-driven testing

Specified is a yaml data format for data-driven testing. This enforces separation between feature being tested the data used for testing.

It comes with a golang implementation for loading the data, checking its format, running your golang test boxes (called code boxed) and comparing the result with the expected one.

It supports using the FOCUS and SKIP flag in the data to run only part of the test data.

Overview

overview of the way the specified library works

Getting started

To get started, create a directory it/ and the three files it.go it_test.go and it_testdata.yaml. For each file, copy the content of linked section. Finally, run go test in the it/ directory.

mkdir it
cd it
touch it.go it_test.go it_testdata.yaml

Finally:

go mod init it
go mod tidy
go test

You should get an output like this one:

TestIt:
2 slab-s succeeded over 2. (0 failed)
PASS
ok      it

Yaml Data

The yaml data file looks like this:

content:
  -
    box: turn_page
    case:
      -
        flag: FOCUS
        input:
          book:
            title: aleph
            left_page: 0
            size: 90
          turn_page_count: 4
      -
        flag: SKIP
        input:
          book:
            title: aleph
            left_page: 0
            size: 90
          turn_page_count: 4
        output:
          title: aleph
          left_page: 8
          size: 90
        info:
          expected_left_page: 8
  -
    flag: FOCUS
    box: get_page
    case:
      -
        input:
          book:
            title: aleph
            left_page: 44
            size: 90
        output: 44

The input entry is required and must be a map. The info entry is optional but must be a map if present. Both the input map and the info map are passed to the test box. The output entry may be any value but it must only be present if the box returns a value. The flags are case insensitive, though it is recommanded to use UPPERCASE to make them more visible. The supported flags are FOCUS and SKIP. The flag entry may be present both at the slab level and at the case level.

Code box

A code box is an adapter between the parsed data and the library the code being tested. It takes as input the input map and the optional info map. A code box looks like this:

package it_test

import (
    "it"
    "testing"

    "github.com/ditrit/specified/go/specified"
)


func TestIt(t *testing.T) {
    specified.Run(
        t,
        []specified.File{
          specified.ReadLocalFile("it_testdata.yaml"),
        },
        specified.CodeboxSet(
            specified.NewCodebox("turn_page", turn_page_box),
            specified.NewCodebox("get_page", get_page_box),
        ),
    )
}

// what a code box can look like

func turn_page_box(s *specified.S, input map[string]interface{}, info map[string]interface{}) interface{} {
    book_data := input["book"].(map[string]interface{})
    book := it.Book{
        Title:    book_data["title"].(string),
        LeftPage: book_data["left_page"].(int),
        Size:     book_data["size"].(int),
    }
    book.TurnPage(input["turn_page_count"].(int))

    return map[string]interface{}{
        "title":     book.Title,
        "left_page": book.LeftPage,
        "size":      book.Size,
    }
}


// the output of a code box can be anything

func get_page_box(s *specified.S, input map[string]interface{}, info map[string]interface{}) interface{} {
    book_data := input["book"].(map[string]interface{})
    book := it.Book{
        Title:    book_data["title"].(string),
        LeftPage: book_data["left_page"].(int),
        Size:     book_data["size"].(int),
    }
    return book.GetPage()
}

// note: if no output comparison is expected by the box, the box must return nil

Example package code

package it

type Book struct {
	Title    string
	LeftPage int
	Size     int
}

func (b *Book) TurnPage(count int) {
	b.LeftPage += 2 * count

	if b.LeftPage < 0 {
		b.LeftPage = 0
	} else if b.LeftPage >= b.Size {
		b.LeftPage = b.Size - 1
	}
}

func (b *Book) GetPage() int {
	return b.LeftPage
}

Yaml Schema

The content of a yaml test data file must match lidy yaml the rule specified by the main rule:

main:
  _mapFacultative:
    flag: string # any test run flag associated with the file
    extra: any # any information you need to store. This can be used as a neutral place to store aliased data
  _map:
    content: {listOf: databox}
databox:
  _mapFacultative:
    name: string # the yaml name of the databox. It is mentioned in the error report if present
    flag: string # any test run flag associated with the databox
    extra: any
  _map:
    box: string # the name of the code box as declared in the code
    case: {_listOf: slab} # the data to be passed to the code box
slab:
  _mapFacultative:
    name: string
    flag: string
    info: {_mapOf: {string: any}}
    output: any
    extra: any
  _map:
    input: {_mapOf: {string: any}}

Several databoxes can contribute their case to the same code box, though each databox contributes only to one code box

Owner
Design it, Run it
DevOps for real IT
Design it, Run it
Similar Resources

A sample web API in GO (with GIn) under a domain driven architecture.

Golang Sample API Domain Driven Design Pattern 1. About This sample project presents a custom made domain driven API architecture in Golang using the

Jan 10, 2022

Event driven modular status-bar for dwm; written in Go & uses Unix sockets for signaling.

dwmstat A simple event-driven modular status-bar for dwm. It is written in Go & uses Unix sockets for signaling. The status bar is conceptualized as a

Dec 25, 2021

An event driven remote access trojan for experimental purposes.

erat An event driven remote access trojan for experimental purposes. This example is very simple and leverages ssh failed login events to trigger erat

Jan 16, 2022

Package event-driven makes it easy for you to drive events between services

Package event-driven makes it easy for you to drive events between services

Event-Driven Event-driven architecture is a software architecture and model for application design. With an event-driven system, the capture, communic

Apr 20, 2022

Generate CRUD gRPC backends from single YAML description.

Generate CRUD gRPC backends from single YAML description.

Pike Generate CRUD gRPC backends from single YAML description. Check out Playground! Pike generates: gRPC Protobuf service description with basic Crea

Dec 23, 2022

Fetches one or more DNS zones via AXFR and dumps in Unix hosts format for local use

axfr2hosts About axfr2hosts is a tool meant to do a DNS zone transfer in a form of AXFR transaction of one or more zones towards a single DNS server a

Aug 9, 2022

Microservice on IPv4: 3000 port without database. Upon request, returns the source JSON in the desired format

Microservice on IPv4: 3000 port without database. Upon request, returns the source JSON in the desired format

📜 Этапы V1.0 Микросервис на IPv4:3000 порту без базы данных. По запросу возвращ

Dec 22, 2021

A simple command-line tool to manage ADRs in markdown format

Architecture Decision Records A simple command-line tool to manage ADRs in markdown format. Usage adr init [path] Initialize the ADR path and create a

Feb 10, 2022

Jswhois - Whois lookup results in json format

jswhois -- whois lookup results in json format jswhois(1) is a tool to look up a

Nov 30, 2022
Related tags
Hetzner-dns-updater - A simple tool to update a DNS record via Hetzner DNS API. Used for simple HA together with Nomad

hetzner-dns-updater A small utility tool to update a single record via Hetzner D

Feb 12, 2022
Fake server, Consumer Driven Contracts and help with testing performance from one configuration file with zero system dependencies and no coding whatsoever
Fake server, Consumer Driven Contracts and help with testing performance from one configuration file with zero system dependencies and no coding whatsoever

mockingjay server Mockingjay lets you define the contract between a consumer and producer and with just a configuration file you get: A fast to launch

Jan 6, 2023
Protocol Buffers - Google's data interchange format

Protocol Buffers - Google's data interchange format Copyright 2008 Google Inc. https://developers.google.com/protocol-buffers/ Overview Protocol Buffe

Jan 3, 2023
Go support for Protocol Buffers - Google's data interchange format

Go support for Protocol Buffers - Google's data interchange format Google's data interchange format. Copyright 2010 The Go Authors. https://github.com

Dec 15, 2021
IPIP.net officially supported IP database ipdb format parsing library

IPIP.net officially supported IP database ipdb format parsing library

Dec 27, 2022
🚀 gnet is a high-performance, lightweight, non-blocking, event-driven networking framework written in pure Go./ gnet 是一个高性能、轻量级、非阻塞的事件驱动 Go 网络框架。
🚀 gnet is a high-performance, lightweight, non-blocking, event-driven networking framework written in pure Go./ gnet 是一个高性能、轻量级、非阻塞的事件驱动 Go 网络框架。

English | ???? 中文 ?? Introduction gnet is an event-driven networking framework that is fast and lightweight. It makes direct epoll and kqueue syscalls

Jan 2, 2023
webrpc is a schema-driven approach to writing backend services for modern Web apps and networks
webrpc is a schema-driven approach to writing backend services for modern Web apps and networks

webrpc is a schema-driven approach to writing backend servers for the Web. Write your server's api interface in a schema format of RIDL or JSON, and t

Jan 7, 2023
Fast and idiomatic client-driven REST APIs.
Fast and idiomatic client-driven REST APIs.

Vulcain is a brand new protocol using HTTP/2 Server Push to create fast and idiomatic client-driven REST APIs. An open source gateway server which you

Jan 8, 2023
Go driven rpc code generation tool for right now.
Go driven rpc code generation tool for right now.

Go driven rpc code generation tool for right now. 100% Go Describe services with Go interfaces (with structs, methods, comments, etc.) Generate server

Dec 20, 2022
High-performance, non-blocking, event-driven, easy-to-use networking framework written in Go, support tls/http1.x/websocket.

High-performance, non-blocking, event-driven, easy-to-use networking framework written in Go, support tls/http1.x/websocket.

Jan 8, 2023