ramsql

command module
v1.723.927 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2021 License: BSD-3-Clause Imports: 4 Imported by: 0

README

RamSQL

Disposable SQL engine

RamSQL has been written to be used in your project's test suite.

Unit testing in Go is simple:

  • create a foo_test.go
  • add import testing
  • add func Test...(t *testing.T) {...}
  • run go test ./...

But then there are SQL queries, constraints, CRUD... and suddenly you need a PostgresSQL, setup scripts, and nothing is easy anymore.

The idea is to avoid setup, DBMS installation, and credentials management as long as possible. A unique engine is tied to a single sql.DB with as much sql.Conn as needed providing a unique DataSourceName. Bottom line: One DataSourceName per test and you have full test isolation in no time.

Installation

go get github.com/kokizzu/ramsql

Usage

Let's say you want to test the function LoadUserAddresses:

func LoadUserAddresses(db *sql.DB, userID int64) ([]string, error) {
  query := `SELECT
      address.street_number,
      address.street
    FROM address 
    JOIN user_addresses
    ON address.id = user_addresses.address_id 
    WHERE user_addresses.user_id = $1;`

  rows, err := db.Query(query, userID)
  if err != nil {
    return nil, err
  }

  var addresses []string
  for rows.Next() {
    var number int
    var street string
    if err := rows.Scan(&number, &street); err != nil {
      return nil, err
    }
    addresses = append(addresses, fmt.Sprintf("%d %s", number, street))
  }

  return addresses, nil
}

Use RamSQL to test it in a disposable isolated in-memory SQL engine:

package myproject 

import (
  "database/sql"
  "fmt"
  "testing"

  _ "github.com/kokizzu/ramsql/driver"
)


func TestLoadUserAddresses(t *testing.T) {
  batch := []string{
    `CREATE TABLE address (id BIGSERIAL PRIMARY KEY, street TEXT, street_number INT);`,
    `CREATE TABLE user_addresses (address_id INT, user_id INT);`,
    `INSERT INTO address (street, street_number) VALUES ('rue Victor Hugo', 32);`,
    `INSERT INTO address (street, street_number) VALUES ('boulevard de la République', 23);`,
    `INSERT INTO address (street, street_number) VALUES ('rue Charles Martel', 5);`,
    `INSERT INTO address (street, street_number) VALUES ('chemin du bout du monde ', 323);`,
    `INSERT INTO address (street, street_number) VALUES ('boulevard de la liberté', 2);`,
    `INSERT INTO address (street, street_number) VALUES ('avenue des champs', 12);`,
    `INSERT INTO user_addresses (address_id, user_id) VALUES (2, 1);`,
    `INSERT INTO user_addresses (address_id, user_id) VALUES (4, 1);`,
    `INSERT INTO user_addresses (address_id, user_id) VALUES (2, 2);`,
    `INSERT INTO user_addresses (address_id, user_id) VALUES (2, 3);`,
    `INSERT INTO user_addresses (address_id, user_id) VALUES (4, 4);`,
    `INSERT INTO user_addresses (address_id, user_id) VALUES (4, 5);`,
  }

  db, err := sql.Open("ramsql", "TestLoadUserAddresses")
  if err != nil {
    t.Fatalf("sql.Open : Error : %s\n", err)
  }
  defer db.Close()

  for _, b := range batch {
    _, err = db.Exec(b)
    if err != nil {
      t.Fatalf("sql.Exec: Error: %s\n", err)
    }
  }

  addresses, err := LoadUserAddresses(db, 1)
  if err != nil {
    t.Fatalf("Too bad! unexpected error: %s", err)
  }

  if len(addresses) != 2 {
    t.Fatalf("Expected 2 addresses, got %d", len(addresses))
  }

}

Done. No need for a running PostgreSQL or a setup. Your tests are isolated, and compliant with go tools.

RamSQL binary

Let's say you have a SQL describing your application structure:

CREATE TABLE IF NOT EXISTS address (id BIGSERIAL PRIMARY KEY, street TEXT, street_number INT);
CREATE TABLE IF NOT EXISTS user_addresses (address_id INT, user_id INT);

You may want to test its validity:

$ go install github.com/kokizzu/ramsql
$ ramsql < schema.sql
ramsql> Query OK. 1 rows affected
ramsql> Query OK. 1 rows affected
$ echo $?
0

Features

Unit testing
  • Full isolation between tests
  • No setup (either file or databases)
  • Good performance
SQL parsing
  • Databse schema validation
  • ALTER file validation
Stress testing
  • File system full error with configurable maximum database size
  • Random configurable slow queries
  • Random deconnection

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
log
parser
Package parser implements a parser for SQL statements Inspired by go/parser Package parser implements a parser for SQL statements Inspired by go/parser Package parser implements a parser for SQL statements Inspired by go/parser
Package parser implements a parser for SQL statements Inspired by go/parser Package parser implements a parser for SQL statements Inspired by go/parser Package parser implements a parser for SQL statements Inspired by go/parser

Jump to

Keyboard shortcuts

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