|  |  | # Go Test Fixtures
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | [](https://godoc.org/gopkg.in/testfixtures.v2)
 | 
						
						
						
							|  |  | [](https://goreportcard.com/report/github.com/go-testfixtures/testfixtures)
 | 
						
						
						
							|  |  | [](https://travis-ci.org/go-testfixtures/testfixtures)
 | 
						
						
						
							|  |  | [](https://ci.appveyor.com/project/andreynering/testfixtures)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | > ***Warning***: this package will wipe the database data before loading the
 | 
						
						
						
							|  |  | fixtures! It is supposed to be used on a test database. Please, double check
 | 
						
						
						
							|  |  | if you are running it against the correct database.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Writing tests is hard, even more when you have to deal with an SQL database.
 | 
						
						
						
							|  |  | This package aims to make writing functional tests for web apps written in
 | 
						
						
						
							|  |  | Go easier.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Basically this package mimics the ["Rails' way"][railstests] of writing tests
 | 
						
						
						
							|  |  | for database applications, where sample data is kept in fixtures files. Before
 | 
						
						
						
							|  |  | the execution of every test, the test database is cleaned and the fixture data
 | 
						
						
						
							|  |  | is loaded into the database.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The idea is running tests against a real database, instead of relying in mocks,
 | 
						
						
						
							|  |  | which is boring to setup and may lead to production bugs not being caught in
 | 
						
						
						
							|  |  | the tests.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Installation
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | First, get it:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```bash
 | 
						
						
						
							|  |  | go get -u -v gopkg.in/testfixtures.v2
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Usage
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Create a folder for the fixture files. Each file should contain data for a
 | 
						
						
						
							|  |  | single table and have the name `<table_name>.yml`:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | myapp/
 | 
						
						
						
							|  |  |   myapp.go
 | 
						
						
						
							|  |  |   myapp_test.go
 | 
						
						
						
							|  |  |   ...
 | 
						
						
						
							|  |  |   fixtures/
 | 
						
						
						
							|  |  |     posts.yml
 | 
						
						
						
							|  |  |     comments.yml
 | 
						
						
						
							|  |  |     tags.yml
 | 
						
						
						
							|  |  |     posts_tags.yml
 | 
						
						
						
							|  |  |     ...
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The file would look like this (it can have as many record you want):
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```yml
 | 
						
						
						
							|  |  | # comments.yml
 | 
						
						
						
							|  |  | - id: 1
 | 
						
						
						
							|  |  |   post_id: 1
 | 
						
						
						
							|  |  |   content: A comment...
 | 
						
						
						
							|  |  |   author_name: John Doe
 | 
						
						
						
							|  |  |   author_email: john@doe.com
 | 
						
						
						
							|  |  |   created_at: 2016-01-01 12:30:12
 | 
						
						
						
							|  |  |   updated_at: 2016-01-01 12:30:12
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | - id: 2
 | 
						
						
						
							|  |  |   post_id: 2
 | 
						
						
						
							|  |  |   content: Another comment...
 | 
						
						
						
							|  |  |   author_name: John Doe
 | 
						
						
						
							|  |  |   author_email: john@doe.com
 | 
						
						
						
							|  |  |   created_at: 2016-01-01 12:30:12
 | 
						
						
						
							|  |  |   updated_at: 2016-01-01 12:30:12
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | # ...
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | An YAML object or array will be converted to JSON. It can be stored on a native
 | 
						
						
						
							|  |  | JSON type like JSONB on PostgreSQL or as a TEXT or VARCHAR column on other
 | 
						
						
						
							|  |  | databases.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```yml
 | 
						
						
						
							|  |  | - id: 1
 | 
						
						
						
							|  |  |   post_attributes:
 | 
						
						
						
							|  |  |     author: John Due
 | 
						
						
						
							|  |  |     author_email: john@due.com
 | 
						
						
						
							|  |  |     title: "..."
 | 
						
						
						
							|  |  |     tags:
 | 
						
						
						
							|  |  |       - programming
 | 
						
						
						
							|  |  |       - go
 | 
						
						
						
							|  |  |       - testing
 | 
						
						
						
							|  |  |     post: "..."
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | If you need to write raw SQL, probably to call a function, prefix the value
 | 
						
						
						
							|  |  | of the column with `RAW=`:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```yml
 | 
						
						
						
							|  |  | - id: 1
 | 
						
						
						
							|  |  |   uuid_column: RAW=uuid_generate_v4()
 | 
						
						
						
							|  |  |   postgis_type_column: RAW=ST_GeomFromText('params...')
 | 
						
						
						
							|  |  |   created_at: RAW=NOW()
 | 
						
						
						
							|  |  |   updated_at: RAW=NOW()
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Your tests would look like this:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | package myapp
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | import (
 | 
						
						
						
							|  |  |     "database/sql"
 | 
						
						
						
							|  |  |     "log"
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     _ "github.com/lib/pq"
 | 
						
						
						
							|  |  |     "gopkg.in/testfixtures.v2"
 | 
						
						
						
							|  |  | )
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | var (
 | 
						
						
						
							|  |  |     db *sql.DB
 | 
						
						
						
							|  |  |     fixtures *testfixtures.Context
 | 
						
						
						
							|  |  | )
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | func TestMain(m *testing.M) {
 | 
						
						
						
							|  |  |     var err error
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     // Open connection with the test database.
 | 
						
						
						
							|  |  |     // Do NOT import fixtures in a production database!
 | 
						
						
						
							|  |  |     // Existing data would be deleted
 | 
						
						
						
							|  |  |     db, err = sql.Open("postgres", "dbname=myapp_test")
 | 
						
						
						
							|  |  |     if err != nil {
 | 
						
						
						
							|  |  |         log.Fatal(err)
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     // creating the context that hold the fixtures
 | 
						
						
						
							|  |  |     // see about all compatible databases in this page below
 | 
						
						
						
							|  |  |     fixtures, err = testfixtures.NewFolder(db, &testfixtures.PostgreSQL{}, "testdata/fixtures")
 | 
						
						
						
							|  |  |     if err != nil {
 | 
						
						
						
							|  |  |         log.Fatal(err)
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     os.Exit(m.Run())
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | func prepareTestDatabase() {
 | 
						
						
						
							|  |  |     if err := fixtures.Load(); err != nil {
 | 
						
						
						
							|  |  |         log.Fatal(err)
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | func TestX(t *testing.T) {
 | 
						
						
						
							|  |  |     prepareTestDatabase()
 | 
						
						
						
							|  |  |     // your test here ...
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | func TestY(t *testing.T) {
 | 
						
						
						
							|  |  |     prepareTestDatabase()
 | 
						
						
						
							|  |  |     // your test here ...
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | func TestZ(t *testing.T) {
 | 
						
						
						
							|  |  |     prepareTestDatabase()
 | 
						
						
						
							|  |  |     // your test here ...
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Alternatively, you can use the `NewFiles` function, to specify which
 | 
						
						
						
							|  |  | files you want to load into the database:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | fixtures, err := testfixtures.NewFiles(db, &testfixtures.PostgreSQL{},
 | 
						
						
						
							|  |  |     "fixtures/orders.yml",
 | 
						
						
						
							|  |  |     "fixtures/customers.yml",
 | 
						
						
						
							|  |  |     // add as many files you want
 | 
						
						
						
							|  |  | )
 | 
						
						
						
							|  |  | if err != nil {
 | 
						
						
						
							|  |  |     log.Fatal(err)
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Security check
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | In order to prevent you from accidentally wiping the wrong database, this
 | 
						
						
						
							|  |  | package will refuse to load fixtures if the database name (or database
 | 
						
						
						
							|  |  | filename for SQLite) doesn't contains "test". If you want to disable this
 | 
						
						
						
							|  |  | check, use:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | testfixtures.SkipDatabaseNameCheck(true)
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Sequences
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | For PostgreSQL or Oracle, this package also resets all sequences to a high
 | 
						
						
						
							|  |  | number to prevent duplicated primary keys while running the tests.
 | 
						
						
						
							|  |  | The default is 10000, but you can change that with:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | testfixtures.ResetSequencesTo(10000)
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Compatible databases
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### PostgreSQL
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | This package has two approaches to disable foreign keys while importing fixtures
 | 
						
						
						
							|  |  | in PostgreSQL databases:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | #### With `DISABLE TRIGGER`
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | This is the default approach. For that use:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | &testfixtures.PostgreSQL{}
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | With the above snippet this package will use `DISABLE TRIGGER` to temporarily
 | 
						
						
						
							|  |  | disabling foreign key constraints while loading fixtures. This work with any
 | 
						
						
						
							|  |  | version of PostgreSQL, but it is **required** to be connected in the database
 | 
						
						
						
							|  |  | as a SUPERUSER. You can make a PostgreSQL user a SUPERUSER with:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```sql
 | 
						
						
						
							|  |  | ALTER USER your_user SUPERUSER;
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | #### With `ALTER CONSTRAINT`
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | This approach don't require to be connected as a SUPERUSER, but only work with
 | 
						
						
						
							|  |  | PostgreSQL versions >= 9.4. Try this if you are getting foreign key violation
 | 
						
						
						
							|  |  | errors with the previous approach. It is as simple as using:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | &testfixtures.PostgreSQL{UseAlterConstraint: true}
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### MySQL / MariaDB
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Just make sure the connection string have
 | 
						
						
						
							|  |  | [the multistatement parameter](https://github.com/go-sql-driver/mysql#multistatements)
 | 
						
						
						
							|  |  | set to true, and use:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | &testfixtures.MySQL{}
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### SQLite
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | SQLite is also supported. It is recommended to create foreign keys as
 | 
						
						
						
							|  |  | `DEFERRABLE` (the default) to prevent problems. See more
 | 
						
						
						
							|  |  | [on the SQLite documentation](https://www.sqlite.org/foreignkeys.html#fk_deferred).
 | 
						
						
						
							|  |  | (Foreign key constraints are no-op by default on SQLite, but enabling it is
 | 
						
						
						
							|  |  | recommended).
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | &testfixtures.SQLite{}
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Microsoft SQL Server
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | SQL Server support requires SQL Server >= 2008. Inserting on `IDENTITY` columns
 | 
						
						
						
							|  |  | are handled as well. Just make sure you are logged in with a user with
 | 
						
						
						
							|  |  | `ALTER TABLE` permission.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | &testfixtures.SQLServer{}
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Oracle
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Oracle is supported as well. Use:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | &testfixtures.Oracle{}
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Generating fixtures for a existing database (experimental)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The following code will generate a YAML file for each table of the database in
 | 
						
						
						
							|  |  | the given folder. It may be useful to boostrap a test scenario from a sample
 | 
						
						
						
							|  |  | database of your app.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | err := testfixtures.GenerateFixtures(db, &testfixtures.PostgreSQL{}, "testdata/fixtures")
 | 
						
						
						
							|  |  | if err != nil {
 | 
						
						
						
							|  |  |     log.Fatalf("Error generating fixtures: %v", err)
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Or
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```go
 | 
						
						
						
							|  |  | err := testfixtures.GenerateFixturesForTables(
 | 
						
						
						
							|  |  |     db,
 | 
						
						
						
							|  |  |     []*TableInfo{
 | 
						
						
						
							|  |  |         &TableInfo{Name: "table_name", Where: "foo = 'bar'"},
 | 
						
						
						
							|  |  |         // ...
 | 
						
						
						
							|  |  |     },
 | 
						
						
						
							|  |  |     &testfixtures.PostgreSQL{},
 | 
						
						
						
							|  |  |     "testdata/fixtures",
 | 
						
						
						
							|  |  | )
 | 
						
						
						
							|  |  | if err != nil {
 | 
						
						
						
							|  |  |     log.Fatalf("Error generating fixtures: %v", err)
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | > This was thought to run in small sample databases. It will likely break
 | 
						
						
						
							|  |  | if run in a production/big database.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Contributing
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Tests were written to ensure everything work as expected. You can run the tests
 | 
						
						
						
							|  |  | with:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```bash
 | 
						
						
						
							|  |  | # running tests for PostgreSQL
 | 
						
						
						
							|  |  | go test -tags postgresql
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | # running test for MySQL
 | 
						
						
						
							|  |  | go test -tags mysql
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | # running tests for SQLite
 | 
						
						
						
							|  |  | go test -tags sqlite
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | # running tests for SQL Server
 | 
						
						
						
							|  |  | go test -tags sqlserver
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | # running tests for Oracle
 | 
						
						
						
							|  |  | go test -tags oracle
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | # running test for multiple databases at once
 | 
						
						
						
							|  |  | go test -tags 'sqlite postgresql mysql'
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | # running tests + benchmark
 | 
						
						
						
							|  |  | go test -v -bench=. -tags postgresql
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Travis runs tests for PostgreSQL, MySQL and SQLite. AppVeyor run for all
 | 
						
						
						
							|  |  | these and also Microsoft SQL Server.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | To set the connection string of tests for each database, copy the `.sample.env`
 | 
						
						
						
							|  |  | file as `.env` and edit it according to your environment.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Alternatives
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | If you don't think using fixtures is a good idea, you can try one of these
 | 
						
						
						
							|  |  | packages instead:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | - [factory-go][factorygo]: Factory for Go. Inspired by Python's Factory Boy
 | 
						
						
						
							|  |  | and Ruby's Factory Girl
 | 
						
						
						
							|  |  | - [go-txdb (Single transaction SQL driver for Go)][gotxdb]: Use a single
 | 
						
						
						
							|  |  | database transaction for each functional test, so you can rollback to
 | 
						
						
						
							|  |  | previous state between tests to have the same database state in all tests
 | 
						
						
						
							|  |  | - [go-sqlmock][gosqlmock]: A mock for the sql.DB interface. This allow you to
 | 
						
						
						
							|  |  | unit test database code without having to connect to a real database
 | 
						
						
						
							|  |  | - [dbcleaner][dbcleaner] - Clean database for testing, inspired by
 | 
						
						
						
							|  |  | database_cleaner for Ruby
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | [railstests]: http://guides.rubyonrails.org/testing.html#the-test-database
 | 
						
						
						
							|  |  | [gotxdb]: https://github.com/DATA-DOG/go-txdb
 | 
						
						
						
							|  |  | [gosqlmock]: https://github.com/DATA-DOG/go-sqlmock
 | 
						
						
						
							|  |  | [factorygo]: https://github.com/bluele/factory-go
 | 
						
						
						
							|  |  | [dbcleaner]: https://github.com/khaiql/dbcleaner
 | 
						
						
						
							|  |  | 
 |