From a78c8f06a84416170667a25d2eabc55662a454bf Mon Sep 17 00:00:00 2001 From: Joseph Spurrier Date: Sat, 12 Jan 2019 11:44:28 -0500 Subject: [PATCH] Move testutil to it's own package Allow user to set the database name. Remove reliance on evironment variables in tests. Change md5 to checksum column name. --- cmd/rove/main_test.go | 63 ++++------ pkg/adapter/jsonfile/jsonfile_test.go | 37 +++--- pkg/adapter/mysql/mysql.go | 31 +++-- pkg/adapter/mysql/mysql_test.go | 123 +++++++++---------- pkg/adapter/mysql/{ => testutil}/testutil.go | 38 +++--- 5 files changed, 145 insertions(+), 147 deletions(-) rename pkg/adapter/mysql/{ => testutil}/testutil.go (80%) diff --git a/cmd/rove/main_test.go b/cmd/rove/main_test.go index 6c16bbd..3494d0a 100644 --- a/cmd/rove/main_test.go +++ b/cmd/rove/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/josephspurrier/rove/pkg/adapter/mysql" + "github.com/josephspurrier/rove/pkg/adapter/mysql/testutil" "github.com/jmoiron/sqlx" "github.com/stretchr/testify/assert" @@ -13,11 +13,11 @@ import ( func TestMigrationAll(t *testing.T) { _, unique := migrateAll(t) - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } func migrateAll(t *testing.T) (*sqlx.DB, string) { - db, unique := mysql.SetupDatabase() + db, unique := testutil.SetupDatabase() // Set the arguments. os.Args = []string{ @@ -34,7 +34,9 @@ func migrateAll(t *testing.T) (*sqlx.DB, string) { os.Stdout = w // Call the application. + testutil.SetEnv(unique) main() + testutil.UnsetEnv(unique) // Get the output. w.Close() @@ -42,19 +44,15 @@ func migrateAll(t *testing.T) (*sqlx.DB, string) { assert.Nil(t, err) os.Stdout = backupd - assert.Contains(t, string(out), "Changeset applied") - - // Count the records. - rows := 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) - assert.Nil(t, err) - assert.Equal(t, 3, rows) + assert.Contains(t, string(out), "josephspurrier:1") + assert.Contains(t, string(out), "josephspurrier:2") + assert.Contains(t, string(out), "josephspurrier:3") return db, unique } func TestMigrationReset(t *testing.T) { - db, unique := migrateAll(t) + _, unique := migrateAll(t) // Set the arguments. os.Args = []string{ @@ -71,7 +69,9 @@ func TestMigrationReset(t *testing.T) { os.Stdout = w // Call the application. + testutil.SetEnv(unique) main() + testutil.UnsetEnv(unique) // Get the output. w.Close() @@ -79,24 +79,20 @@ func TestMigrationReset(t *testing.T) { assert.Nil(t, err) os.Stdout = backupd - assert.Contains(t, string(out), "Rollback applied") - - // Count the records. - rows := 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) - assert.Nil(t, err) - assert.Equal(t, 0, rows) + assert.Contains(t, string(out), "Rollback applied: josephspurrier:3") + assert.Contains(t, string(out), "Rollback applied: josephspurrier:2") + assert.Contains(t, string(out), "Rollback applied: josephspurrier:1") - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } func TestMigrationUp(t *testing.T) { _, unique := migrateUp(t) - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } func migrateUp(t *testing.T) (*sqlx.DB, string) { - db, unique := mysql.SetupDatabase() + db, unique := testutil.SetupDatabase() // Set the arguments. os.Args = []string{ @@ -114,7 +110,9 @@ func migrateUp(t *testing.T) (*sqlx.DB, string) { os.Stdout = w // Call the application. + testutil.SetEnv(unique) main() + testutil.UnsetEnv(unique) // Get the output. w.Close() @@ -122,19 +120,14 @@ func migrateUp(t *testing.T) (*sqlx.DB, string) { assert.Nil(t, err) os.Stdout = backupd - assert.Contains(t, string(out), "Changeset applied") - - // Count the records. - rows := 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) - assert.Nil(t, err) - assert.Equal(t, 2, rows) + assert.Contains(t, string(out), "Changeset applied: josephspurrier:1") + assert.Contains(t, string(out), "Changeset applied: josephspurrier:2") return db, unique } func TestMigrationDown(t *testing.T) { - db, unique := migrateUp(t) + _, unique := migrateUp(t) // Set the arguments. os.Args = []string{ @@ -152,7 +145,9 @@ func TestMigrationDown(t *testing.T) { os.Stdout = w // Call the application. + testutil.SetEnv(unique) main() + testutil.UnsetEnv(unique) // Get the output. w.Close() @@ -160,13 +155,7 @@ func TestMigrationDown(t *testing.T) { assert.Nil(t, err) os.Stdout = backupd - assert.Contains(t, string(out), "Rollback applied") - - // Count the records. - rows := 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) - assert.Nil(t, err) - assert.Equal(t, 1, rows) + assert.Contains(t, string(out), "Rollback applied: josephspurrier:2") - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } diff --git a/pkg/adapter/jsonfile/jsonfile_test.go b/pkg/adapter/jsonfile/jsonfile_test.go index 471d214..dd61f46 100644 --- a/pkg/adapter/jsonfile/jsonfile_test.go +++ b/pkg/adapter/jsonfile/jsonfile_test.go @@ -7,17 +7,19 @@ import ( "github.com/josephspurrier/rove" "github.com/josephspurrier/rove/pkg/adapter/jsonfile" "github.com/josephspurrier/rove/pkg/adapter/mysql" + "github.com/josephspurrier/rove/pkg/adapter/mysql/testutil" "github.com/stretchr/testify/assert" ) func TestFileMigration(t *testing.T) { - db, unique := mysql.SetupDatabase() + _, unique := testutil.SetupDatabase() _ = os.Remove("test.json") // Create a new MySQL database object. - m := new(mysql.MySQL) - m.DB = db + m, err := mysql.New(testutil.Connection(unique)) + assert.Nil(t, err) + js, err := jsonfile.New("test.json", m) assert.Nil(t, err) @@ -70,16 +72,17 @@ func TestFileMigration(t *testing.T) { assert.Equal(t, "josephspurrier:1", s) _ = os.Remove("test.json") - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } func TestMigrationFailDuplicate(t *testing.T) { - db, unique := mysql.SetupDatabase() + _, unique := testutil.SetupDatabase() _ = os.Remove("test.json") // Create a new MySQL database object. - m := new(mysql.MySQL) - m.DB = db + m, err := mysql.New(testutil.Connection(unique)) + assert.Nil(t, err) + js, err := jsonfile.New("test.json", m) assert.Nil(t, err) @@ -97,16 +100,17 @@ func TestMigrationFailDuplicate(t *testing.T) { assert.Equal(t, "josephspurrier:2", s) _ = os.Remove("test.json") - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } func TestInclude(t *testing.T) { - db, unique := mysql.SetupDatabase() + _, unique := testutil.SetupDatabase() _ = os.Remove("test.json") // Create a new MySQL database object. - m := new(mysql.MySQL) - m.DB = db + m, err := mysql.New(testutil.Connection(unique)) + assert.Nil(t, err) + js, err := jsonfile.New("test.json", m) assert.Nil(t, err) @@ -159,16 +163,17 @@ func TestInclude(t *testing.T) { assert.Equal(t, "josephspurrier:1", s) _ = os.Remove("test.json") - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } func TestChangesetMigration(t *testing.T) { - db, unique := mysql.SetupDatabase() + _, unique := testutil.SetupDatabase() _ = os.Remove("test.json") // Create a new MySQL database object. - m := new(mysql.MySQL) - m.DB = db + m, err := mysql.New(testutil.Connection(unique)) + assert.Nil(t, err) + js, err := jsonfile.New("test.json", m) assert.Nil(t, err) @@ -221,7 +226,7 @@ func TestChangesetMigration(t *testing.T) { assert.Equal(t, "josephspurrier:1", s) _ = os.Remove("test.json") - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } var sSuccess = ` diff --git a/pkg/adapter/mysql/mysql.go b/pkg/adapter/mysql/mysql.go index 66897c5..4c66596 100644 --- a/pkg/adapter/mysql/mysql.go +++ b/pkg/adapter/mysql/mysql.go @@ -10,13 +10,14 @@ import ( ) const ( - sqlChangelog = `CREATE TABLE IF NOT EXISTS databasechangelog ( + tableName = "rovechangelog" + createQuery = `CREATE TABLE IF NOT EXISTS ` + tableName + ` ( id varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, author varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, filename varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, dateexecuted datetime NOT NULL, orderexecuted int(11) NOT NULL, - md5sum varchar(35) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + checksum varchar(35) COLLATE utf8mb4_unicode_ci DEFAULT NULL, description varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, tag varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, version varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL @@ -33,8 +34,9 @@ type dbchangeset struct { // MySQL is a MySQL database changelog. type MySQL struct { - DB *sqlx.DB - tablename string + DB *sqlx.DB + TableName string + InitializeQuery string } // New connects to the database and returns an object that satisfies the @@ -43,13 +45,18 @@ func New(c *Connection) (m *MySQL, err error) { // Connect to the database. m = new(MySQL) m.DB, err = c.Connect(true) + + // Set the default table and create query + m.TableName = tableName + m.InitializeQuery = createQuery + return m, err } // Initialize will create the changelog table or return an error. func (m *MySQL) Initialize() (err error) { // Create the table. - _, err = m.DB.Exec(sqlChangelog) + _, err = m.DB.Exec(m.InitializeQuery) if err != nil { return err } @@ -61,8 +68,8 @@ func (m *MySQL) Initialize() (err error) { // error if there was an issue, or a blank checksum with no error if it's not // found. func (m *MySQL) ChangesetApplied(id, author, filename string) (checksum string, err error) { - err = m.DB.Get(&checksum, `SELECT md5sum - FROM databasechangelog + err = m.DB.Get(&checksum, `SELECT checksum + FROM `+m.TableName+` WHERE id = ? AND author = ? AND filename = ?`, id, author, filename) @@ -87,7 +94,7 @@ func (m *MySQL) BeginTx() (rove.Transaction, error) { // Count returns the number of changesets in the database. func (m *MySQL) Count() (count int, err error) { - err = m.DB.Get(&count, `SELECT COUNT(*) FROM databasechangelog`) + err = m.DB.Get(&count, `SELECT COUNT(*) FROM `+m.TableName) if err != nil { return 0, err } @@ -98,8 +105,8 @@ func (m *MySQL) Count() (count int, err error) { // Insert will insert a new record into the database. func (m *MySQL) Insert(id, author, filename string, count int, checksum, description, version string) error { _, err := m.DB.Exec(` - INSERT INTO databasechangelog - (id,author,filename,dateexecuted,orderexecuted,md5sum,description,version) + INSERT INTO `+m.TableName+` + (id,author,filename,dateexecuted,orderexecuted,checksum,description,version) VALUES(?,?,?,NOW(),?,?,?,?)`, id, author, filename, count, checksum, description, version) return err @@ -116,7 +123,7 @@ func (m *MySQL) Changesets(reverse bool) ([]rove.Changeset, error) { results := make([]dbchangeset, 0) err := m.DB.Select(&results, ` SELECT id, author, filename, orderexecuted - FROM databasechangelog + FROM `+m.TableName+` ORDER BY orderexecuted `+order) // Copy from one struct to another. @@ -137,7 +144,7 @@ func (m *MySQL) Changesets(reverse bool) ([]rove.Changeset, error) { func (m *MySQL) Delete(id, author, filename string) error { // Delete the record. _, err := m.DB.Exec(` - DELETE FROM databasechangelog + DELETE FROM `+m.TableName+` WHERE id = ? AND author = ? AND filename = ? LIMIT 1`, id, author, filename) return err } diff --git a/pkg/adapter/mysql/mysql_test.go b/pkg/adapter/mysql/mysql_test.go index 534499e..5ae7844 100644 --- a/pkg/adapter/mysql/mysql_test.go +++ b/pkg/adapter/mysql/mysql_test.go @@ -5,30 +5,30 @@ import ( "github.com/josephspurrier/rove" "github.com/josephspurrier/rove/pkg/adapter/mysql" + "github.com/josephspurrier/rove/pkg/adapter/mysql/testutil" "github.com/stretchr/testify/assert" ) func TestFileMigration(t *testing.T) { - db, unique := mysql.SetupDatabase() + _, unique := testutil.SetupDatabase() // Create a new MySQL database object. - m := new(mysql.MySQL) - m.DB = db + m, err := mysql.New(testutil.Connection(unique)) + assert.Nil(t, err) // Set up rove. r := rove.NewFileMigration(m, "../testdata/success.sql") r.Verbose = true // Run migration. - err := r.Migrate(0) + err = r.Migrate(0) assert.Nil(t, err) - // Count the records. - rows := 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err := r.Status() assert.Nil(t, err) - assert.Equal(t, 3, rows) + assert.Equal(t, "josephspurrier:3", s) // Run migration again. err = r.Migrate(0) @@ -38,10 +38,10 @@ func TestFileMigration(t *testing.T) { err = r.Reset(0) assert.Nil(t, err) - rows = 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err = r.Status() assert.Nil(t, err) - assert.Equal(t, 0, rows) + assert.Equal(t, "", s) // Remove all migrations again. err = r.Reset(0) @@ -51,71 +51,65 @@ func TestFileMigration(t *testing.T) { err = r.Migrate(2) assert.Nil(t, err) - rows = 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err = r.Status() assert.Nil(t, err) - assert.Equal(t, 2, rows) + assert.Equal(t, "josephspurrier:2", s) // Remove 1 migration. err = r.Reset(1) assert.Nil(t, err) - rows = 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) - assert.Nil(t, err) - assert.Equal(t, 1, rows) - // Show status of the migrations. - s, err := r.Status() + s, err = r.Status() assert.Nil(t, err) assert.Equal(t, "josephspurrier:1", s) - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } func TestMigrationFailDuplicate(t *testing.T) { - db, unique := mysql.SetupDatabase() + _, unique := testutil.SetupDatabase() // Create a new MySQL database object. - m := new(mysql.MySQL) - m.DB = db + m, err := mysql.New(testutil.Connection(unique)) + assert.Nil(t, err) // Set up rove. r := rove.NewFileMigration(m, "../testdata/fail-duplicate.sql") r.Verbose = true - err := r.Migrate(0) + err = r.Migrate(0) assert.NotNil(t, err) assert.Contains(t, err.Error(), "checksum does not match") - rows := 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err := r.Status() assert.Nil(t, err) - assert.Equal(t, 2, rows) + assert.Equal(t, "josephspurrier:2", s) - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } func TestInclude(t *testing.T) { - db, unique := mysql.SetupDatabase() + _, unique := testutil.SetupDatabase() // Create a new MySQL database object. - m := new(mysql.MySQL) - m.DB = db + m, err := mysql.New(testutil.Connection(unique)) + assert.Nil(t, err) // Set up rove. r := rove.NewFileMigration(m, "../testdata/parent.sql") r.Verbose = true // Run migration. - err := r.Migrate(0) + err = r.Migrate(0) assert.Nil(t, err) - // Count the records. - rows := 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err := r.Status() assert.Nil(t, err) - assert.Equal(t, 3, rows) + assert.Equal(t, "josephspurrier:3", s) // Run migration again. err = r.Migrate(0) @@ -125,10 +119,10 @@ func TestInclude(t *testing.T) { err = r.Reset(0) assert.Nil(t, err) - rows = 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err = r.Status() assert.Nil(t, err) - assert.Equal(t, 0, rows) + assert.Equal(t, "", s) // Remove all migrations again. err = r.Reset(0) @@ -138,43 +132,42 @@ func TestInclude(t *testing.T) { err = r.Migrate(2) assert.Nil(t, err) - rows = 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err = r.Status() assert.Nil(t, err) - assert.Equal(t, 2, rows) + assert.Equal(t, "josephspurrier:2", s) // Remove 1 migration. err = r.Reset(1) assert.Nil(t, err) - rows = 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err = r.Status() assert.Nil(t, err) - assert.Equal(t, 1, rows) + assert.Equal(t, "josephspurrier:1", s) - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } func TestChangesetMigration(t *testing.T) { - db, unique := mysql.SetupDatabase() + _, unique := testutil.SetupDatabase() // Create a new MySQL database object. - m := new(mysql.MySQL) - m.DB = db + m, err := mysql.New(testutil.Connection(unique)) + assert.Nil(t, err) // Set up rove. r := rove.NewChangesetMigration(m, sSuccess) r.Verbose = true // Run migration. - err := r.Migrate(0) + err = r.Migrate(0) assert.Nil(t, err) - // Count the records. - rows := 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err := r.Status() assert.Nil(t, err) - assert.Equal(t, 3, rows) + assert.Equal(t, "josephspurrier:3", s) // Run migration again. err = r.Migrate(0) @@ -184,10 +177,10 @@ func TestChangesetMigration(t *testing.T) { err = r.Reset(0) assert.Nil(t, err) - rows = 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err = r.Status() assert.Nil(t, err) - assert.Equal(t, 0, rows) + assert.Equal(t, "", s) // Remove all migrations again. err = r.Reset(0) @@ -197,21 +190,21 @@ func TestChangesetMigration(t *testing.T) { err = r.Migrate(2) assert.Nil(t, err) - rows = 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err = r.Status() assert.Nil(t, err) - assert.Equal(t, 2, rows) + assert.Equal(t, "josephspurrier:2", s) // Remove 1 migration. err = r.Reset(1) assert.Nil(t, err) - rows = 0 - err = db.Get(&rows, `SELECT count(*) from databasechangelog`) + // Get the status. + s, err = r.Status() assert.Nil(t, err) - assert.Equal(t, 1, rows) + assert.Equal(t, "josephspurrier:1", s) - mysql.TeardownDatabase(unique) + testutil.TeardownDatabase(unique) } var sSuccess = ` diff --git a/pkg/adapter/mysql/testutil.go b/pkg/adapter/mysql/testutil/testutil.go similarity index 80% rename from pkg/adapter/mysql/testutil.go rename to pkg/adapter/mysql/testutil/testutil.go index 803db3d..c181ce4 100644 --- a/pkg/adapter/mysql/testutil.go +++ b/pkg/adapter/mysql/testutil/testutil.go @@ -1,4 +1,4 @@ -package mysql +package testutil import ( "fmt" @@ -8,7 +8,7 @@ import ( "time" "github.com/josephspurrier/rove" - "github.com/josephspurrier/rove/pkg/env" + "github.com/josephspurrier/rove/pkg/adapter/mysql" "github.com/jmoiron/sqlx" ) @@ -22,7 +22,8 @@ func init() { rand.Seed(time.Now().UnixNano()) } -func setEnv(unique string) { +// SetEnv will set the environment variables. +func SetEnv(unique string) { os.Setenv(unique+"DB_HOSTNAME", "127.0.0.1") os.Setenv(unique+"DB_PORT", "3306") os.Setenv(unique+"DB_USERNAME", "root") @@ -31,7 +32,8 @@ func setEnv(unique string) { os.Setenv(unique+"DB_PARAMETER", "parseTime=true&allowNativePasswords=true&multiStatements=true") } -func unsetEnv(unique string) { +// UnsetEnv will unset the environment variables. +func UnsetEnv(unique string) { os.Unsetenv(unique + "DB_HOSTNAME") os.Unsetenv(unique + "DB_PORT") os.Unsetenv(unique + "DB_USERNAME") @@ -40,13 +42,21 @@ func unsetEnv(unique string) { os.Unsetenv(unique + "DB_PARAMETER") } +// Connection returns the test connection. +func Connection(unique string) *mysql.Connection { + return &mysql.Connection{ + Hostname: "127.0.0.1", + Port: 3306, + Username: "root", + Password: "", + Database: TestDatabaseName + unique, + Parameter: "parseTime=true&allowNativePasswords=true&multiStatements=true", + } +} + // connectDatabase returns a test database connection. func connectDatabase(dbSpecificDB bool, unique string) *sqlx.DB { - dbc := new(Connection) - err := env.Unmarshal(dbc, unique) - if err != nil { - fmt.Println("DB ENV Error:", err) - } + dbc := Connection(unique) connection, err := dbc.Connect(dbSpecificDB) if err != nil { @@ -60,7 +70,6 @@ func connectDatabase(dbSpecificDB bool, unique string) *sqlx.DB { // variables. func SetupDatabase() (*sqlx.DB, string) { unique := "T" + fmt.Sprint(rand.Intn(500)) - setEnv(unique) db := connectDatabase(false, unique) _, err := db.Exec(`DROP DATABASE IF EXISTS ` + TestDatabaseName + unique) @@ -83,8 +92,6 @@ func TeardownDatabase(unique string) { if err != nil { fmt.Println("DB DROP TEARDOWN Error:", err) } - - unsetEnv(unique) } // LoadDatabaseFromFile will set up the DB for the tests. @@ -97,14 +104,11 @@ func LoadDatabaseFromFile(file string, usePrefix bool) (*sqlx.DB, string) { if usePrefix { db, unique = SetupDatabase() // Create a new MySQL database object. - m := new(MySQL) - m.DB = db + m, _ := mysql.New(Connection(unique)) r = rove.NewFileMigration(m, file) } else { - m := new(MySQL) - m.DB = db + m, _ := mysql.New(Connection(unique)) r = rove.NewFileMigration(m, file) - setEnv(unique) db = connectDatabase(false, unique) _, err := db.Exec(`DROP DATABASE IF EXISTS ` + TestDatabaseName) if err != nil {