dsunit

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 8, 2018 License: Apache-2.0 Imports: 20 Imported by: 4

README

Datastore Testibility (dsunit)

Datastore testibility library for Go. GoDoc

This library is compatible with Go 1.5+

Please refer to CHANGELOG.md if you encounter breaking changes.

Introduction

Data focused testing belongs to blackbox group, where the main interest goes down to the initial and final state of the datastore.

To set the initial state of ta datastore, this framework provies utilities to either create empty datastore, or to prepare it with dataset data to test that application works correctly.

The final state testing focuses on checking that a dataset data matches an expected set of values after application logic run. In this case this library has ability to verify either complete or snapshot state of a datastore. While the first approach will be comparing all tables data with expected set of values, the latter will reduced verification to the range provided by expected dataset.

Motivation

This library has been design to provide easy and unified way of testing any datastore (SQL, NoSSQL,file logs) on any platform, language and on the cloud. It simplifies test organization by dataset auto discovery used for datastore preparation and verification. Dataset data can be loaded from various sources like: memory, local or remote csv, json files. All dataset support macro expression to dynamically evaluate value of data i.e <ds:sql ["SELECT CURRENT_DATE()"]> On top of that expected data, can also use predicate expressions to delegate verification of the data values i.e. <ds:between [11301, 11303]>. Finally a dataset like a view can be used to store data for many datastore sources in in just one dataset file.

Datastore initialization and dataset data verification can by managed locally or remotely on remote data store unit test server.



import (
	"testing"
	"github.com/viant/dsunit"
	_ "github.com/go-sql-driver/mysql"
)


func TestSetup(t *testing.T) {

    dsunit.InitDatastoresFromUrl(t, "test://test/datastore_init.json")
	dsunit.ExecuteScriptFromUrl(t, vertica_script_request.json)
	dsunit.PrepareDatastore(t, "mytestdb")
	
	
	... business test logic comes here
	
	dsunit.ExpectDatasets(t, "mytestdb", dsunit.SnapshotDatasetCheckPolicy)
}

API Documentation

API documentation is available in the docs directory.

GoCover

GoCover

Examples

Simple CRUD app with dsunit

License

The source code is made available under the terms of the Apache License, Version 2, as stated in the file LICENSE.

Individual files may be made available under their own specific license, all compatible with Apache License, Version 2. Please see individual files for details.

Credits and Acknowledgements

Library Author: Adrian Witas

Contributors: Sudhakaran Dharmaraj

Documentation

Overview

Package dsunit - Datastore testing library.

Index

Constants

View Source
const (
	//FullTableDatasetCheckPolicy policy will drive comparison of all actual datastore data
	FullTableDatasetCheckPolicy = 0
	//SnapshotDatasetCheckPolicy policy will drive comparison of subset of  actual datastore data that is is listed in expected dataset
	SnapshotDatasetCheckPolicy = 1
)
View Source
const (
	//ViolationTypeInvalidRowCount 'InvalidRowCount' constant used to report rows discrepancy between expected and actual dataset table.
	ViolationTypeInvalidRowCount = "InvalidRowCount"
	//ViolationTypeMissingActualRow 'AssertionMissingActualRow' constant used to report missing actual row.
	ViolationTypeMissingActualRow = "AssertionMissingActualRow"
	//ViolationTypeRowNotEqual 'AssertionRowNotEqual; constant used to report difference in values in the expected and actual row.
	ViolationTypeRowNotEqual = "AssertionRowNotEqual"
)

Variables

View Source
var TestSchema = "test://"

TestSchema constant test:// - it is used as shortcut for the test base directory.

Functions

func ExecuteScriptFromURL

func ExecuteScriptFromURL(t *testing.T, url string)

ExecuteScriptFromURL executes script from URL, URL should point to ExecuteScriptRequest JSON.

func ExpandTestProtocolAsPathIfNeeded

func ExpandTestProtocolAsPathIfNeeded(input string) string

ExpandTestProtocolAsPathIfNeeded extends input if it start with test:// fragment to currently test file directory

func ExpandTestProtocolAsURLIfNeeded

func ExpandTestProtocolAsURLIfNeeded(input string) string

ExpandTestProtocolAsUrlIfNeeded extends input if it start with test:// fragment to currently test file directory as file protocol

func ExpectDatasetFor

func ExpectDatasetFor(t *testing.T, datastore string, checkPolicy int, baseDirectory string, method string)

ExpectDatasetFor matches all dataset files that are located in baseDirectory with method name and verifies that all listed dataset values are present in datastore Note the matchable dataset files in the base directory have the following naming:

<lower_underscore method name>_expect_<table>.[json|csv]
To prepare expected dataset table: 'users' and 'permissions' for test method ReadAll you would
have you create the following files in the baseDirectory

read_all_expect_users.json
read_all_expect_permissions.json

func ExpectDatasets

func ExpectDatasets(t *testing.T, datastore string, checkPolicy int)

ExpectDatasets matches all dataset files that are located in the same directory as the test file with method name and verifies that all listed dataset values are present in datastore

func InitDatastoreFromURL

func InitDatastoreFromURL(t *testing.T, url string)

InitDatastoreFromURL initialises datastore from URL, URL needs to point to InitDatastoreRequest JSON it register datastore, table descriptor, data mapping, and optionally recreate datastore

func ParseColumnarData

func ParseColumnarData(reader io.Reader, separator string) ([]string, [][]interface{})

func ParseSQLScript

func ParseSQLScript(reader io.Reader) []string

parseSQLScript parses sql script and breaks it down to submittable sql statements

func PrepareDatastore

func PrepareDatastore(t *testing.T, datastore string)

PrepareDatastore matches all dataset files that are in the same location as a test file, with the same test file prefix, followed by lowe camel case test name.

func PrepareDatastoreFor

func PrepareDatastoreFor(t *testing.T, datastore string, baseDirectory string, method string)

PrepareDatastoreFor matches all dataset files that are located in baseDirectory with method name and populate datastore with all listed dataset Note the matchable dataset files in the base directory have the following naming:

<lower_underscore method name>_populate_<table>.[json|csv]
To prepare dataset to populate datastore table: 'users' and 'permissions' for test method ReadAll you would
have you create the following files in the baseDirectory

read_all_prepare_travelers2.json
read_all_populate_permissions.json

func SetService

func SetService(service Service)

SetService sets global dsunit service.

func StartServer

func StartServer(port string)

StartServer start dsunit server

func UseRemoteTestServer

func UseRemoteTestServer(serverURL string)

UseRemoteTestServer this method changes service to run all operation remotely using passed in URL.

Types

type AssertViolation

type AssertViolation struct {
	Datastore string
	Type      string
	Table     string
	Key       string
	Expected  string
	Actual    string
	Source    string
	Path      string
}

AssertViolation represents test violation.

type AssertViolations

type AssertViolations interface {
	Violations() []*AssertViolation

	HasViolations() bool

	String() string
}

AssertViolations represents a test violations.

func NewAssertViolations

func NewAssertViolations(violations []*AssertViolation) AssertViolations

NewAssertViolations creates a new instance of AssertViolations

type Dataset

type Dataset struct {
	*dsc.TableDescriptor
	Rows []*Row
}

Dataset represents test or expected dataset data values

func (*Dataset) AsMapArray

func (d *Dataset) AsMapArray() []map[string]interface{}

AsMapArray returns array of maps

type DatasetColumn

type DatasetColumn struct {
	Name         string
	DefaultValue string
	FromColumn   string
	Required     bool
}

DatasetColumn represents dataset mapping column.

type DatasetFactory

type DatasetFactory interface {
	//Create creates a dataset from map for passed in table descriptor
	Create(descriptor *dsc.TableDescriptor, dataset ...map[string]interface{}) *Dataset

	//CreateFromMap crate a dataset from a map for passed in datastore and table
	CreateFromMap(datastore string, table string, dataset ...map[string]interface{}) *Dataset

	//CreateFromURL crate a dataset from a map for passed in datastore and table
	CreateFromURL(datastore string, table string, url string) (*Dataset, error)

	//CreateDatasets crate a datasets from passed in data resources
	CreateDatasets(data *DatasetResource) (*Datasets, error)
}

DatasetFactory represents a dataset factory.

type DatasetMapping

type DatasetMapping struct {
	Table        string
	Columns      []*DatasetColumn
	Associations []*DatasetMapping
}

DatasetMapping represents a dataset mapping, mapping allow to route data defined in only one dataset to many datasets.

func (*DatasetMapping) Tables

func (m *DatasetMapping) Tables() []string

type DatasetResource

type DatasetResource struct {
	Datastore  string
	URL        string
	Credential string
	Prefix     string //apply prefix
	Postfix    string //apply suffix
	TableRows  []*TableRows
}

type DatasetTestManager

type DatasetTestManager interface {
	//ClearDatastore clears datastore, it takes adminDatastore and targetDatastore names.
	ClearDatastore(adminDatastore string, targetDatastore string) error

	//Execute executes passed in script, script defines what database it run on.
	Execute(script *Script) (int, error)

	//ExecuteFromUrl reads content from url and executes it on datastore
	ExecuteFromURL(datastore string, url string) (int, error)

	//PrepareDatastore prepare datastore datasets by adding, updating or deleting data.
	// Rows will be added if they weren't present, updated if they were present, and deleted if passed in dataset has not rows defined.
	PrepareDatastore(datasets *Datasets) (inserted, updated, deleted int, err error)

	//ExpectDatasets verifies that passed in expected dataset data values are present in the datastore, this methods reports any violations.
	ExpectDatasets(checkPolicy int, expected *Datasets) (AssertViolations, error)

	//ManagerRegistry returns ManagerRegistry.
	ManagerRegistry() dsc.ManagerRegistry

	//ValueProviderRegistry returns macro value provider registry.
	ValueProviderRegistry() toolbox.ValueProviderRegistry

	//MacroEvaluator returns macro evaluator.
	MacroEvaluator() *toolbox.MacroEvaluator

	//DatasetFactory returns dataset factory.
	DatasetFactory() DatasetFactory

	//RegisterTable register table descriptor within datastore manager.
	RegisterTable(datastore string, tableDescriptor *dsc.TableDescriptor)

	//RegisteredTables returns all registered table for passed in datastore.
	RegisteredTables(datastore string) []string

	//RegisterDatasetMapping registers dataset mapping for passed in name.
	//Note that dataset mapping name should never be the actual table name, as this method will create table descriptor for the mapping.
	RegisterDatasetMapping(name string, mapping *DatasetMapping)

	//RegisteredMapping returns all registered dataset mapping
	RegisteredMapping() []string

	//SafeMode enable/disable safe mode (in safe mode only datastore with test name can be dropper and recreated)
	SafeMode(enable bool)
}

DatasetTestManager supervises datastore initialization, test dataset preparation, and final datastore dataset verification

func NewDatasetTestManager

func NewDatasetTestManager() DatasetTestManager

NewDatasetTestManager returns a new DatasetTestManager

type DatasetTester

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

DatasetTester represent a dataset tester.

func (DatasetTester) Assert

func (t DatasetTester) Assert(datastore string, expected, actual *Dataset) []*AssertViolation

Assert compares expected and actual dataset, it reports and violations as result.

type DatasetTransformer

type DatasetTransformer struct{}

DatasetTransformer represents a dataset transformer.

func NewDatasetTransformer

func NewDatasetTransformer() *DatasetTransformer

NewDatasetTransformer returns a new NewDatasetTransformer

func (*DatasetTransformer) Transform

func (dt *DatasetTransformer) Transform(datastore string, sourceDataset *Dataset, mapping *DatasetMapping, registry dsc.TableDescriptorRegistry) *Datasets

Transform routes source dataset data into mapping dataset, it uses source dataset and table descriptor registry to build resulting datasets.

type Datasets

type Datasets struct {
	Datastore string
	Datasets  []*Dataset
}

Datasets represents a collection of Dataset's for Datastore

type DatastoreConfig

type DatastoreConfig struct {
	Datastore      string      //name of datastore registered in manager registry
	Config         *dsc.Config // datastore manager config
	ConfigURL      string      //url with Config JSON.
	AdminDbName    string      //optional admin datastore name, needed for sql datastore to drop/create database
	ClearDatastore bool        //flag to reset datastore (depending on dialablable it could be either drop/create datastore for CanDrop/CanCreate dialects, or drop/create tables
	Descriptors    []*dsc.TableDescriptor
	DatasetMapping map[string]*DatasetMapping //key represent name of dataset to be mapped
}

DatastoreConfig represets DatastoreConfig dsunit config

type DatastoreDatasetProvider

type DatastoreDatasetProvider struct {
	dsc.Manager
}

func NewDatastoreDatasetProvider

func NewDatastoreDatasetProvider(manager dsc.Manager) *DatastoreDatasetProvider

func (*DatastoreDatasetProvider) Get

func (p *DatastoreDatasetProvider) Get(table string, columns ...string) (*Dataset, error)

type DatastoreDatasetSnapshotManager

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

func NewDatastoreDatasetSnapshotManager

func NewDatastoreDatasetSnapshotManager(registry dsc.ManagerRegistry) *DatastoreDatasetSnapshotManager

func (*DatastoreDatasetSnapshotManager) Take

func (t *DatastoreDatasetSnapshotManager) Take(datastore string, targetDirectory string) error

type ExecuteScriptRequest

type ExecuteScriptRequest struct {
	Scripts []Script
}

ExecuteScriptRequest represent datastore script request.

type ExpectDatasetRequest

type ExpectDatasetRequest struct {
	Expect      []Datasets
	CheckPolicy int
}

ExpectDatasetRequest represent datastore verification request.

type ExpectResponse

type ExpectResponse struct {
	*Response
	Violations []*AssertViolation
}

ExpectResponse represetns a dataset verification response.

type InitDatastoreRequest

type InitDatastoreRequest struct {
	DatastoreConfigs []DatastoreConfig
}

InitDatastoreRequest represent initialization in dsunit service datastore request.

type PrepareDatastoreRequest

type PrepareDatastoreRequest struct {
	Prepare []Datasets
}

PrepareDatastoreRequest represent datastore prepare request.

type Response

type Response struct {
	Status  string
	Message string
}

Response represetns a response.

type Row

type Row struct {
	Values map[string]interface{}
	Source string
}

Row represents dataset row

func AsRow

func AsRow(instance interface{}) *Row

AsRow cast instance as Row.

func (Row) Columns

func (r Row) Columns() []string

Columns returns column names.

func (Row) HasColumn

func (r Row) HasColumn(column string) bool

HasColumn returns true if this row has passed in column value.

func (Row) SetValue

func (r Row) SetValue(column string, value interface{})

SetValue sets column value on this row.

func (Row) String

func (r Row) String() string

String prints row content.

func (Row) Value

func (r Row) Value(column string) interface{}

Value returns raw column value for this row.

func (Row) ValueAsString

func (r Row) ValueAsString(column string) string

ValueAsString returns column value as string.

type Script

type Script struct {
	Datastore string
	Url       string
	Sqls      []string
	Body      string
}

Script represents a datastore script

type Service

type Service interface {
	//Init creates datastore manager and register it in manaer registry, if ClearDatastore flag is set it will drop and create datastore.
	Init(request *InitDatastoreRequest) *Response

	//InitFromUrl reads from url  InitDatastoresRequest JSON and initializes
	InitFromURL(url string) *Response

	//ExecuteScripts executes script defined in the request
	ExecuteScripts(request *ExecuteScriptRequest) *Response

	//ExecuteScripts loads ExecuteScriptsExecuteScripts JSON from url and executes it.
	ExecuteScriptsFromURL(url string) *Response

	//PrepareDatastore prepares datastore for request, see DatasetTestManager#PrepareDatastore
	PrepareDatastore(request *PrepareDatastoreRequest) *Response

	//PrepareDatastore laods PrepareDatastoreRequest JSON from url to prepare datastore, see DatasetTestManager#PrepareDatastore
	PrepareDatastoreFromURL(url string) *Response

	//PrepareDatastore prepares for passed in datastore, it loads matching dataset files from based directory and method.
	PrepareDatastoreFor(datastore string, baseDir string, method string) *Response

	//ExpectDatasets verifies dataset data in datastore for passed in request, see DatasetTestManager#ExpectDataset
	ExpectDatasets(request *ExpectDatasetRequest) *ExpectResponse

	//ExpectDatasets loads ExpectDatasetRequest json from url to verify dataset, see DatasetTestManager#ExpectDataset
	ExpectDatasetsFromURL(url string) *ExpectResponse

	//ExpectDatasetsFor verifies datastore for passed in datastore, it loads matching dataset files from based directory and method.
	ExpectDatasetsFor(datastore string, baseDir string, method string, checkPolicy int) *ExpectResponse
}

Service represents test service

func GetService

func GetService() Service

GetService returns dsunit service.

func NewServiceClient

func NewServiceClient(testDirectory, serverURL string) Service

NewServiceClient returns a new dsunit service client

func NewServiceLocal

func NewServiceLocal(testDirectory string) Service

NewServiceLocal returns new local dsunit service, it takes test directory as argument.

type TableRows

type TableRows struct {
	Table string
	Rows  []map[string]interface{}
}

TableRows represent data records

Directories

Path Synopsis
Package server - Remote testing dsunit server
Package server - Remote testing dsunit server

Jump to

Keyboard shortcuts

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