sqltestutil

package module
v0.0.7 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2022 License: MIT Imports: 21 Imported by: 0

README

sqltestutil

Documentation

Utilities for testing Golang code that runs SQL.

Usage

PostgresContainer

PostgresContainer is a Docker container running Postgres that can be used to cheaply start a throwaway Postgres instance for testing.

RunMigration

RunMigration reads all of the files matching *.up.sql in a directory and executes them in lexicographical order against the provided DB.

LoadScenario

LoadScenario reads a YAML "scenario" file and uses it to populate the given DB.

Suite

Suite is a testify suite that provides a database connection for running tests against a SQL database.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func LoadScenario

func LoadScenario(ctx context.Context, db sqlx.ExtContext, filename string) error

LoadScenario reads a YAML "scenario" file and uses it to populate the given db. Top-level keys in the YAML are treated as table names having repeated rows, where keys on each row are column names. For example:

  users:
	 - id: 1
	   name: Alice
	   email: alice@example.com
	 - id: 2
    name: Bob
	   email: bob@example.com

  posts:
	 - user_id: 1
	   title: Hello, world!
	 - user_id: 2
	   title: Goodbye, world!
    is_draft: true

The above would populate the users and posts tables. Fields that are missing from the YAML are left out of the INSERT statement, and so are populated with the default value for that column.

func RunMigrations

func RunMigrations(ctx context.Context, db driver.ExecerContext, migrationDir string, files ...string) error

RunMigrations reads all of the files matching *.up.sql in migrationDir and executes them in lexicographical order against the provided db. A typical convention is to use a numeric prefix for each new migration, e.g.:

001_create_users.up.sql
002_create_posts.up.sql
003_create_comments.up.sql

Note that this function does not check whether the migration has already been run. Its primary purpose is to initialize a test database.

Types

type Option

type Option func(*PostgresContainer)

func WithContainerName added in v0.0.6

func WithContainerName(containerName string) Option

func WithDBName added in v0.0.2

func WithDBName(dbName string) Option

func WithPassword

func WithPassword(password string) Option

func WithPort

func WithPort(port uint16) Option

func WithUser

func WithUser(user string) Option

func WithVersion

func WithVersion(version string) Option

type PostgresContainer

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

PostgresContainer is a Docker container running Postgres. It can be used to cheaply start a throwaway Postgres instance for testing.

func StartPostgresContainer

func StartPostgresContainer(ctx context.Context, options ...Option) (*PostgresContainer, error)

StartPostgresContainer starts a new Postgres Docker container. The version parameter is the tagged version of Postgres image to use, e.g. to use postgres:12 pass "12". Creation involes a few steps:

1. Pull the image if it isn't already cached locally 2. Start the container 3. Wait for Postgres to be healthy

Once created the container will be immediately usable. It should be stopped with the Shutdown method. The container will bind to a randomly available host port, and random password. The SQL connection string can be obtained with the ConnectionString method.

Container startup and shutdown together can take a few seconds (longer when the image has not yet been pulled.) This is generally too slow to initiate in each unit test so it's advisable to do setup and teardown once for a whole suite of tests. TestMain is one way to do this, however because of Golang issue 37206 1, panics in tests will immediately exit the process without giving you the opportunity to Shutdown, which results in orphaned containers lying around.

Another approach is to write a single test that starts and stops the container and then run sub-tests within there. The testify 2 suite package provides a good way to structure these kinds of tests:

type ExampleTestSuite struct {
    suite.Suite
}

func (s *ExampleTestSuite) TestExample() {
    // test something
}

func TestExampleTestSuite(t *testing.T) {
    pg, _ := sqltestutil.StartPostgresContainer(context.Background(), WithVersion("12"))
    defer pg.Shutdown(ctx)
    suite.Run(t, &ExampleTestSuite{})
}

func (*PostgresContainer) ConnectionString

func (c *PostgresContainer) ConnectionString() string

ConnectionString returns a connection URL string that can be used to connect to the running Postgres container.

func (*PostgresContainer) Shutdown

func (c *PostgresContainer) Shutdown(ctx context.Context) error

Shutdown cleans up the Postgres container by stopping and removing it. This should be called each time a PostgresContainer is created to avoid orphaned containers.

type Suite

type Suite struct {
	suite.Suite

	// Context is a required field for constructing a Suite, and is used for
	// database operations within a suite. It's public because it's convenient to
	// have access to it in tests.
	context.Context

	// DriverName is a required field for constructing a Suite, and is used to
	// connect to the underlying SQL database.
	DriverName string

	// DataSourceName is a required field for constructing a Suite, and is used to
	// connect to the underlying SQL database.
	DataSourceName string
	// contains filtered or unexported fields
}

Suite is a testify suite 1 that provides a database connection for running tests against a SQL database. For each test that is run, a new transaction is started, and then rolled back at the end of the test so that each test can operate on a clean slate. Here's an example of how to use it:

    type ExampleTestSuite struct {
        sqltestutil.Suite
    }

    func (s *ExampleTestSuite) TestExample() {
        _, err := s.Tx().Exec("INSERT INTO foo (bar) VALUES (?)", "baz")
        s.Assert().NoError(err)
    }

    func TestExampleTestSuite(t *testing.T) {
        suite.Run(t, &ExampleTestSuite{
		       Suite: sqltestutil.Suite{
                Context: context.Background(),
                DriverName: "pgx",
			       DataSourceName: "postgres://localhost:5432/example",
            },
        })
    }

func (*Suite) DB

func (s *Suite) DB() *sqlx.DB

DB returns the underlying SQL connection.

func (*Suite) SetupSuite

func (s *Suite) SetupSuite()

func (*Suite) TearDownSuite

func (s *Suite) TearDownSuite()

func (*Suite) TearDownTest

func (s *Suite) TearDownTest()

func (*Suite) Tx

func (s *Suite) Tx() *sqlx.Tx

Tx returns the transaction for the current test.

Jump to

Keyboard shortcuts

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