Skip to content

Commit 4f4ae0d

Browse files
committed
Added support for loading fixtures from a file or slice of files.
Also added some tests for better coverage on sql building.
1 parent f0844cf commit 4f4ae0d

File tree

4 files changed

+327
-4
lines changed

4 files changed

+327
-4
lines changed

fixtures/test_fixtures1.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- table: 'some_table'
2+
pk:
3+
id: 1
4+
fields:
5+
string_field: 'foobar'
6+
boolean_field: true
7+
created_at: 'ON_INSERT_NOW()'
8+
updated_at: 'ON_UPDATE_NOW()'

fixtures/test_fixtures2.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
- table: 'other_table'
2+
pk:
3+
id: 2
4+
fields:
5+
int_field: 123
6+
boolean_field: false
7+
created_at: 'ON_INSERT_NOW()'
8+
updated_at: 'ON_UPDATE_NOW()'
9+
10+
- table: 'join_table'
11+
pk:
12+
some_id: 1
13+
other_id: 2
14+
15+
- table: 'string_key_table'
16+
pk:
17+
id: 'new_id'
18+
fields:
19+
created_at: 'ON_INSERT_NOW()'
20+
updated_at: 'ON_UPDATE_NOW()'

load.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package fixtures
33
import (
44
"database/sql"
55
"fmt"
6+
"io/ioutil"
67
"strings"
78

89
"gopkg.in/yaml.v2"
@@ -56,7 +57,7 @@ func Load(data []byte, db *sql.DB, driver string) error {
5657
if driver == postgresDriver && row.GetInsertColumns()[0] == "id" {
5758

5859
var dtype string
59-
err = tx.QueryRow(checkPKDataType(row.Table)).Scan(&dtype)
60+
err = tx.QueryRow(checkPostgresPKDataType(row.Table)).Scan(&dtype)
6061
if err != nil {
6162
tx.Rollback() // rollback the transaction
6263
return err
@@ -87,7 +88,7 @@ func Load(data []byte, db *sql.DB, driver string) error {
8788
}
8889
if driver == postgresDriver && row.GetUpdateColumns()[0] == "id" {
8990
var dtype string
90-
err = tx.QueryRow(checkPKDataType(row.Table)).Scan(&dtype)
91+
err = tx.QueryRow(checkPostgresPKDataType(row.Table)).Scan(&dtype)
9192
if err != nil {
9293
tx.Rollback() // rollback the transaction
9394
return err
@@ -114,7 +115,7 @@ func Load(data []byte, db *sql.DB, driver string) error {
114115
return nil
115116
}
116117

117-
func checkPKDataType(table string) string {
118+
func checkPostgresPKDataType(table string) string {
118119
return fmt.Sprintf(
119120
"SELECT data_type "+
120121
"FROM information_schema.columns WHERE table_name='%s' "+
@@ -132,3 +133,23 @@ func fixPostgresPKSequence(table string) string {
132133
table,
133134
)
134135
}
136+
137+
func LoadFile(filename string, db *sql.DB, driver string) error {
138+
// Read fixture data from the file
139+
data, err := ioutil.ReadFile(filename)
140+
if err != nil {
141+
return err
142+
}
143+
144+
// Insert the fixture data
145+
return Load(data, db, driver)
146+
}
147+
148+
func LoadFiles(filenames []string, db *sql.DB, driver string) error {
149+
for _, filename := range filenames {
150+
if err := LoadFile(filename, db, driver); err != nil {
151+
return err
152+
}
153+
}
154+
return nil
155+
}

load_test.go

Lines changed: 275 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ CREATE TABLE string_key_table(
4141
updated_at DATETIME
4242
)`
4343

44+
var fixtureFile = "fixtures/test_fixtures1.yml"
45+
46+
var fixtureFiles = []string{
47+
"fixtures/test_fixtures1.yml",
48+
"fixtures/test_fixtures2.yml",
49+
}
50+
4451
var testData = `
4552
---
4653
@@ -75,7 +82,7 @@ var testData = `
7582
updated_at: 'ON_UPDATE_NOW()'
7683
`
7784

78-
func TestLoad(t *testing.T) {
85+
func TestLoadWorksWithValidData(t *testing.T) {
7986
// Delete the test database
8087
os.Remove(testDbPath)
8188

@@ -307,3 +314,270 @@ func TestLoad(t *testing.T) {
307314
assert.Equal(t, 2, otherID)
308315
}
309316
}
317+
318+
func TestLoadFileWorksWithValidFile(t *testing.T) {
319+
// Delete the test database
320+
os.Remove(testDbPath)
321+
322+
var (
323+
db *sql.DB
324+
err error
325+
)
326+
327+
// Connect to an in-memory SQLite database
328+
db, err = sql.Open("sqlite3", testDbPath)
329+
if err != nil {
330+
log.Fatal(err)
331+
}
332+
defer db.Close()
333+
334+
// Create a test schema
335+
_, err = db.Exec(testSchema)
336+
if err != nil {
337+
log.Fatal(err)
338+
}
339+
340+
var count int
341+
// Check row counts to show no data
342+
db.QueryRow("SELECT COUNT(*) FROM some_table").Scan(&count)
343+
assert.Equal(t, 0, count)
344+
db.QueryRow("SELECT COUNT(*) FROM other_table").Scan(&count)
345+
assert.Equal(t, 0, count)
346+
db.QueryRow("SELECT COUNT(*) FROM join_table").Scan(&count)
347+
assert.Equal(t, 0, count)
348+
db.QueryRow("SELECT COUNT(*) FROM string_key_table").Scan(&count)
349+
assert.Equal(t, 0, count)
350+
351+
// Let's load the fixture, since the database is empty, this should run inserts
352+
err = LoadFile(fixtureFile, db, "sqlite")
353+
354+
// Error should be nil
355+
assert.Nil(t, err)
356+
357+
var (
358+
rows *sql.Rows
359+
id int
360+
stringField string
361+
booleanField bool
362+
createdAt *time.Time
363+
updatedAt *time.Time
364+
)
365+
366+
// Check row counts
367+
db.QueryRow("SELECT COUNT(*) FROM some_table").Scan(&count)
368+
assert.Equal(t, 1, count)
369+
db.QueryRow("SELECT COUNT(*) FROM other_table").Scan(&count)
370+
assert.Equal(t, 0, count)
371+
db.QueryRow("SELECT COUNT(*) FROM join_table").Scan(&count)
372+
assert.Equal(t, 0, count)
373+
db.QueryRow("SELECT COUNT(*) FROM string_key_table").Scan(&count)
374+
assert.Equal(t, 0, count)
375+
376+
// Check correct data has been loaded into some_table
377+
rows, err = db.Query("SELECT id, string_field, boolean_field, " +
378+
"created_at, updated_at FROM some_table")
379+
if err != nil {
380+
log.Fatal(err)
381+
}
382+
383+
defer rows.Close()
384+
for rows.Next() {
385+
if err := rows.Scan(
386+
&id,
387+
&stringField,
388+
&booleanField,
389+
&createdAt,
390+
&updatedAt,
391+
); err != nil {
392+
log.Fatal(err)
393+
}
394+
395+
if err := rows.Err(); err != nil {
396+
log.Fatal(err)
397+
}
398+
399+
assert.Equal(t, 1, id)
400+
assert.Equal(t, "foobar", stringField)
401+
assert.Equal(t, true, booleanField)
402+
assert.NotNil(t, createdAt)
403+
assert.Nil(t, updatedAt)
404+
}
405+
406+
// Let's reload the fixture, this should run updates
407+
err = LoadFile(fixtureFile, db, "sqlite")
408+
409+
// Error should be nil
410+
assert.Nil(t, err)
411+
412+
// Check row counts, should be unchanged
413+
db.QueryRow("SELECT COUNT(*) FROM some_table").Scan(&count)
414+
assert.Equal(t, 1, count)
415+
db.QueryRow("SELECT COUNT(*) FROM other_table").Scan(&count)
416+
assert.Equal(t, 0, count)
417+
db.QueryRow("SELECT COUNT(*) FROM join_table").Scan(&count)
418+
assert.Equal(t, 0, count)
419+
db.QueryRow("SELECT COUNT(*) FROM string_key_table").Scan(&count)
420+
assert.Equal(t, 0, count)
421+
}
422+
423+
func TestLoadFileFailssWithMissingFile(t *testing.T) {
424+
// Delete the test database
425+
os.Remove(testDbPath)
426+
427+
var (
428+
db *sql.DB
429+
err error
430+
)
431+
432+
// Connect to an in-memory SQLite database
433+
db, err = sql.Open("sqlite3", testDbPath)
434+
if err != nil {
435+
log.Fatal(err)
436+
}
437+
defer db.Close()
438+
439+
// Create a test schema
440+
_, err = db.Exec(testSchema)
441+
if err != nil {
442+
log.Fatal(err)
443+
}
444+
445+
// Let's load the fixture, since the database is empty, this should run inserts
446+
err = LoadFile("bad_filename.yml", db, "sqlite")
447+
448+
// Error should be nil
449+
assert.EqualError(t, err, "open bad_filename.yml: no such file or directory", "Expected file not found error")
450+
}
451+
452+
func TestLoadFilesWorksWithValidFiles(t *testing.T) {
453+
// Delete the test database
454+
os.Remove(testDbPath)
455+
456+
var (
457+
db *sql.DB
458+
err error
459+
)
460+
461+
// Connect to an in-memory SQLite database
462+
db, err = sql.Open("sqlite3", testDbPath)
463+
if err != nil {
464+
log.Fatal(err)
465+
}
466+
defer db.Close()
467+
468+
// Create a test schema
469+
_, err = db.Exec(testSchema)
470+
if err != nil {
471+
log.Fatal(err)
472+
}
473+
474+
var count int
475+
476+
// Check rows are empty first
477+
db.QueryRow("SELECT COUNT(*) FROM some_table").Scan(&count)
478+
assert.Equal(t, 0, count)
479+
db.QueryRow("SELECT COUNT(*) FROM other_table").Scan(&count)
480+
assert.Equal(t, 0, count)
481+
db.QueryRow("SELECT COUNT(*) FROM join_table").Scan(&count)
482+
assert.Equal(t, 0, count)
483+
db.QueryRow("SELECT COUNT(*) FROM string_key_table").Scan(&count)
484+
assert.Equal(t, 0, count)
485+
486+
// Let's load the fixture, since the database is empty, this should run inserts
487+
err = LoadFiles(fixtureFiles, db, "sqlite")
488+
489+
// Error should be nil
490+
assert.Nil(t, err)
491+
492+
// Check row counts
493+
db.QueryRow("SELECT COUNT(*) FROM some_table").Scan(&count)
494+
assert.Equal(t, 1, count)
495+
db.QueryRow("SELECT COUNT(*) FROM other_table").Scan(&count)
496+
assert.Equal(t, 1, count)
497+
db.QueryRow("SELECT COUNT(*) FROM join_table").Scan(&count)
498+
assert.Equal(t, 1, count)
499+
db.QueryRow("SELECT COUNT(*) FROM string_key_table").Scan(&count)
500+
assert.Equal(t, 1, count)
501+
502+
// Let's reload the fixtures, this should run updates
503+
err = LoadFiles(fixtureFiles, db, "sqlite")
504+
505+
// Error should be nil
506+
assert.Nil(t, err)
507+
508+
// Check row counts, should be unchanged
509+
db.QueryRow("SELECT COUNT(*) FROM some_table").Scan(&count)
510+
assert.Equal(t, 1, count)
511+
db.QueryRow("SELECT COUNT(*) FROM other_table").Scan(&count)
512+
assert.Equal(t, 1, count)
513+
db.QueryRow("SELECT COUNT(*) FROM join_table").Scan(&count)
514+
assert.Equal(t, 1, count)
515+
}
516+
517+
func TestLoadFilesFailsWithABadFile(t *testing.T) {
518+
// Delete the test database
519+
os.Remove(testDbPath)
520+
521+
var (
522+
db *sql.DB
523+
err error
524+
)
525+
526+
// Connect to an in-memory SQLite database
527+
db, err = sql.Open("sqlite3", testDbPath)
528+
if err != nil {
529+
log.Fatal(err)
530+
}
531+
defer db.Close()
532+
533+
// Create a test schema
534+
_, err = db.Exec(testSchema)
535+
if err != nil {
536+
log.Fatal(err)
537+
}
538+
539+
var count int
540+
541+
// Check rows are empty first
542+
db.QueryRow("SELECT COUNT(*) FROM some_table").Scan(&count)
543+
assert.Equal(t, 0, count)
544+
db.QueryRow("SELECT COUNT(*) FROM other_table").Scan(&count)
545+
assert.Equal(t, 0, count)
546+
db.QueryRow("SELECT COUNT(*) FROM join_table").Scan(&count)
547+
assert.Equal(t, 0, count)
548+
db.QueryRow("SELECT COUNT(*) FROM string_key_table").Scan(&count)
549+
assert.Equal(t, 0, count)
550+
551+
var badList = []string{
552+
fixtureFile,
553+
"bad_file",
554+
}
555+
556+
// Let's load the fixture, since the database is empty, this should run inserts
557+
err = LoadFiles(badList, db, "sqlite")
558+
559+
// Error should be nil
560+
assert.EqualError(t, err, "open bad_file: no such file or directory", "Expected file not found error")
561+
562+
}
563+
564+
func TestCheckPostgresPKWorks(t *testing.T) {
565+
expected := "SELECT data_type " +
566+
"FROM information_schema.columns " +
567+
"WHERE table_name='test_table' " +
568+
"AND column_name='id';"
569+
570+
actual := checkPostgresPKDataType("test_table")
571+
572+
assert.Equal(t, actual, expected, "Data type sql should match")
573+
}
574+
575+
func TestFixPostgresSequenceWorks(t *testing.T) {
576+
expected := "SELECT pg_catalog.setval(" +
577+
"pg_get_serial_sequence('test_table', 'id'), " +
578+
"(SELECT MAX(id) FROM test_table));"
579+
580+
actual := fixPostgresPKSequence("test_table")
581+
582+
assert.Equal(t, actual, expected, "Sequence fix sql should match")
583+
}

0 commit comments

Comments
 (0)