Run unit tests in separate databases to avoid conflicts

Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
Michael Mayer
2020-05-08 19:34:29 +02:00
parent e703a54586
commit 3aad02501f
18 changed files with 78 additions and 61 deletions

View File

@@ -24,7 +24,7 @@ services:
PHOTOPRISM_TIDB_PASSWORD: "photoprism"
PHOTOPRISM_DATABASE_DRIVER: "tidb"
PHOTOPRISM_DATABASE_DSN: "root:photoprism@tcp(localhost:2343)/photoprism?parseTime=true"
PHOTOPRISM_TEST_DSN: "photoprism:photoprism@tcp(photoprism-db:4001)/photoprism?parseTime=true"
PHOTOPRISM_TEST_DSN: "root:photoprism@tcp(photoprism-db:4001)/photoprism?parseTime=true"
PHOTOPRISM_TITLE: "PhotoPrism"
PHOTOPRISM_SUBTITLE: "Browse your life"
PHOTOPRISM_DESCRIPTION: "Personal Photo Management tested by Travis CI."
@@ -47,6 +47,8 @@ services:
command: mysqld --port=4001 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=1024
expose:
- "4001"
volumes:
- "./scripts/test-db.sql:/docker-entrypoint-initdb.d/test-db.sql"
environment:
MYSQL_ROOT_PASSWORD: photoprism
MYSQL_USER: photoprism

View File

@@ -28,7 +28,7 @@ services:
PHOTOPRISM_TIDB_PASSWORD: "photoprism"
PHOTOPRISM_DATABASE_DRIVER: "tidb"
PHOTOPRISM_DATABASE_DSN: "root:photoprism@tcp(localhost:2343)/photoprism?parseTime=true"
PHOTOPRISM_TEST_DSN: "photoprism:photoprism@tcp(photoprism-db:4001)/photoprism?parseTime=true"
PHOTOPRISM_TEST_DSN: "root:photoprism@tcp(photoprism-db:4001)/photoprism?parseTime=true"
PHOTOPRISM_ASSETS_PATH: "/go/src/github.com/photoprism/photoprism/assets"
PHOTOPRISM_CACHE_PATH: "/go/src/github.com/photoprism/photoprism/assets/cache"
PHOTOPRISM_RESOURCES_PATH: "/go/src/github.com/photoprism/photoprism/assets/resources"
@@ -48,6 +48,8 @@ services:
- "4001"
ports:
- "4001:4001" # MySQL (for tests)
volumes:
- "./scripts/test-db.sql:/docker-entrypoint-initdb.d/test-db.sql"
environment:
MYSQL_ROOT_PASSWORD: photoprism
MYSQL_USER: photoprism

View File

@@ -61,10 +61,10 @@ func (c *Config) InitDb() {
entity.MigrateDb()
}
// ResetDb drops all tables in the currently configured database and re-creates them.
func (c *Config) ResetDb() {
// InitTestDb drops all tables in the currently configured database and re-creates them.
func (c *Config) InitTestDb() {
entity.SetDbProvider(c)
entity.InitTestFixtures()
entity.ResetTestFixtures()
}
// connectToDatabase establishes a database connection.

View File

@@ -102,7 +102,7 @@ func NewTestConfig() *Config {
log.Fatalf("config: %s", err.Error())
}
c.ResetDb()
c.InitTestDb()
thumb.Size = c.ThumbSize()
thumb.Limit = c.ThumbLimit()

View File

@@ -15,12 +15,13 @@ func TestCreateAccount(t *testing.T) {
accountForm, err := form.NewAccount(account)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
model, err := CreateAccount(accountForm)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, "/home", model.SharePath)
@@ -56,12 +57,12 @@ func TestAccount_Save(t *testing.T) {
accountForm, err := form.NewAccount(account)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
model, err := CreateAccount(accountForm)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, "Foo", model.AccName)
@@ -75,7 +76,7 @@ func TestAccount_Save(t *testing.T) {
err = model.Save(UpdateForm)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, "NewName", model.AccName)
@@ -94,18 +95,18 @@ func TestAccount_Delete(t *testing.T) {
accountForm, err := form.NewAccount(account)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
model, err := CreateAccount(accountForm)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
err = model.Delete()
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
// TODO how to assert deletion?
@@ -121,18 +122,18 @@ func TestAccount_Directories(t *testing.T) {
accountForm, err := form.NewAccount(account)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
model, err := CreateAccount(accountForm)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
result, err := model.Directories()
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.NotEmpty(t, result.Abs())
assert.Contains(t, result.Abs(), "/Photos")
@@ -146,18 +147,18 @@ func TestAccount_Directories(t *testing.T) {
accountForm, err := form.NewAccount(account)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
model, err := CreateAccount(accountForm)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
result, err := model.Directories()
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Empty(t, result.Abs())

View File

@@ -75,13 +75,13 @@ func TestAlbum_Save(t *testing.T) {
albumForm, err := form.NewAlbum(album2)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
err = album.Save(albumForm)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, "New name", album.AlbumName)

View File

@@ -9,7 +9,7 @@ func TestDescription_FirstOrCreate(t *testing.T) {
description := &Description{PhotoID: 123, PhotoDescription: ""}
err := description.FirstOrCreate()
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
}

View File

@@ -11,7 +11,6 @@ package entity
import (
"fmt"
"sync"
"time"
"github.com/jinzhu/gorm"
@@ -19,7 +18,6 @@ import (
)
var log = event.Log
var resetFixturesOnce sync.Once
func logError(result *gorm.DB) {
if result.Error != nil {
@@ -74,6 +72,18 @@ func (list Types) WaitForMigration() {
}
}
// Truncate removes all data from tables without dropping them.
func (list Types) Truncate() {
for name := range list {
if err := Db().Raw(fmt.Sprintf("TRUNCATE TABLE `%s`", name)).Scan(&struct{}{}).Error; err == nil {
log.Debugf("entity: removed all data from %s", name)
break
} else {
log.Debugf("entity: %s", err.Error())
}
}
}
// Drop migrates all database tables of registered entities.
func (list Types) Migrate() {
for _, entity := range list {
@@ -98,40 +108,31 @@ func (list Types) Drop() {
}
}
// MigrateDb creates all tables and inserts default entities as needed.
func MigrateDb() {
Entities.Migrate()
Entities.WaitForMigration()
// Creates default database entries for test and production.
func CreateDefaultFixtures() {
CreateUnknownPlace()
CreateUnknownCountry()
CreateUnknownCamera()
CreateUnknownLens()
}
// DropTables drops database tables for all known entities.
func DropTables() {
Entities.Drop()
// MigrateDb creates all tables and inserts default entities as needed.
func MigrateDb() {
Entities.Migrate()
Entities.WaitForMigration()
// wait for changes to be written to disk
time.Sleep(250 * time.Millisecond)
CreateDefaultFixtures()
}
// ResetDb drops database tables for all known entities and re-creates them with fixtures.
func ResetDb(testFixtures bool) {
DropTables()
MigrateDb()
// ResetTestFixtures drops database tables for all known entities and re-creates them with fixtures.
func ResetTestFixtures() {
Entities.Migrate()
Entities.WaitForMigration()
Entities.Truncate()
CreateDefaultFixtures()
if testFixtures {
CreateTestFixtures()
}
}
// InitTestFixtures resets the database and test fixtures once.
func InitTestFixtures() {
resetFixturesOnce.Do(func() {
ResetDb(true)
})
}
// InitTestDb connects to and completely initializes the test database incl fixtures.
@@ -146,7 +147,7 @@ func InitTestDb(dsn string) *Gorm {
}
SetDbProvider(db)
InitTestFixtures()
ResetTestFixtures()
return db
}

View File

@@ -2,6 +2,7 @@ package entity
import (
"os"
"strings"
"testing"
"github.com/sirupsen/logrus"
@@ -17,7 +18,7 @@ func TestMain(m *testing.M) {
panic("database dsn is empty")
}
db := InitTestDb(dsn)
db := InitTestDb(strings.Replace(dsn, "/photoprism", "/entity", 1))
code := m.Run()

View File

@@ -16,7 +16,7 @@ func TestFirstFileByHash(t *testing.T) {
t.Run("existing file", func(t *testing.T) {
f, err := FirstFileByHash("2cad9168fa6acc5c5c2965ddf6ec465ca42fd818")
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, uint(0xf4240), f.ID)
})

View File

@@ -70,7 +70,7 @@ func TestLabel_Update(t *testing.T) {
err := Label.Update(*classifyLabel)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, 5, Label.LabelPriority)
@@ -89,7 +89,7 @@ func TestLabel_Update(t *testing.T) {
err := Label.Update(*classifyLabel)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, 5, Label.LabelPriority)
@@ -109,7 +109,7 @@ func TestLabel_Update(t *testing.T) {
err := Label.Update(*classifyLabel)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, 5, Label.LabelPriority)

View File

@@ -50,7 +50,7 @@ func TestPhotoLabel_Save(t *testing.T) {
photoLabel := NewPhotoLabel(13, 1000, 99, "image")
err := photoLabel.Save()
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
})
}

View File

@@ -87,13 +87,13 @@ func TestPhoto_Save(t *testing.T) {
err := photo.Save()
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
})
t.Run("existing photo", func(t *testing.T) {
err := PhotoFixture19800101_000002_D640C559.Save()
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
})
}

View File

@@ -14,7 +14,7 @@ func TestNewAccount(t *testing.T) {
r, err := NewAccount(account)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, "Foo", r.AccName)

View File

@@ -26,7 +26,7 @@ func TestNewAlbum(t *testing.T) {
r, err := NewAlbum(album)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, "Foo", r.AlbumName)

View File

@@ -17,7 +17,7 @@ func TestNewPhoto(t *testing.T) {
r, err := NewPhoto(photo)
if err != nil {
t.Fatal("error")
t.Fatal(err)
}
assert.Equal(t, time.Date(2008, 1, 1, 2, 0, 0, 0, time.UTC), r.TakenAt)

View File

@@ -2,6 +2,7 @@ package query
import (
"os"
"strings"
"testing"
"github.com/photoprism/photoprism/internal/entity"
@@ -18,7 +19,7 @@ func TestMain(m *testing.M) {
panic("database dsn is empty")
}
db := entity.InitTestDb(dsn)
db := entity.InitTestDb(strings.Replace(dsn, "/photoprism", "/query", 1))
code := m.Run()

9
scripts/test-db.sql Normal file
View File

@@ -0,0 +1,9 @@
CREATE DATABASE IF NOT EXISTS api;
CREATE DATABASE IF NOT EXISTS config;
CREATE DATABASE IF NOT EXISTS entity;
CREATE DATABASE IF NOT EXISTS photoprism;
CREATE DATABASE IF NOT EXISTS query;
CREATE DATABASE IF NOT EXISTS remote;
CREATE DATABASE IF NOT EXISTS service;
CREATE DATABASE IF NOT EXISTS workers;
CREATE DATABASE IF NOT EXISTS acceptance;