--You have to prepare test data for each test case. --You have to reset the DB change result so that it doesn't affect other test cases. --Cannot be executed in parallel because changes to DB affect other test cases.
-The DB connection that can be created with DATA-DOG/go-txdb has the following features.
--Compatible with sql.DB
.
--All queries are executed within an independent transaction.
--Calling .Close ()
rolls back all queries executed within that transaction.
--If you use this well, you can execute the query in an independent transaction for each test case, and the DB change will be rolled back after the test is completed, so you do not need to process the data for each test case and move to another test case. The test can be executed in parallel because the influence of is eliminated.
--The actual sample code is available at here.
--This time, put the code including the DB connection in the dao
package.
--Define TestMain
and insert the data needed for the test using go-testfixtures/testfixtures.
--It is written in the README that test fixtures
does not support parallel tests, but this time it is only called by TestMain
, so there is no problem.
--Call txdb.Register
to use txdb
in later tests.
func TestMain(m *testing.M) {
prepare()
txdb.Register("txdb", "mysql", config.DB.DSN)
code := m.Run()
os.Exit(code)
}
func prepare() {
db, err := sql.Open(config.DB.Driver, config.DB.DSN)
if err != nil {
panic(err)
}
defer db.Close()
fixtures, err := testfixtures.New(
testfixtures.Database(db),
testfixtures.Dialect("mysql"),
testfixtures.Directory("/go/src/github.com/rinchsan/txdb-todo/testdata/fixtures"),
)
if err != nil {
panic(err)
}
if err := fixtures.Load(); err != nil {
panic(err)
}
}
--Take the user-added test as an example.
--See GitHub for details such as the code to be tested and the schema of the DB.
--Test using the connection obtained by specifying " txdb "
in the Driver passed to sql.Open
.
--It creates an independent transaction for each string passed to the second argument of sql.Open
.
--DB changes are rolled back for each test case by db.Close ()
called by defer
.
--It is also possible to run tests in parallel using t.Parallel ()
.
――By the way, in this example, by using environment variables, we are trying to test using a database different from the database used for local development, so for details, see Makefile
. Take a look at test
.
func TestUserImpl_Add(t *testing.T) {
t.Parallel()
cases := map[string]struct {
user *entity.User
noErr bool
}{
"new user": {
user: &entity.User{Username: "rinchsan"},
noErr: true,
},
"duplicate username": {
user: &entity.User{Username: "John"},
noErr: true,
},
"empty username": {
user: &entity.User{Username: ""},
noErr: true,
},
}
for name, c := range cases {
c := c
t.Run(name, func(t *testing.T) {
t.Parallel()
db, err := sql.Open("txdb", uuid.New().String())
assert.NoError(t, err)
defer db.Close()
impl := dao.NewUser(db)
err = impl.Add(context.Background(), c.user)
if c.noErr {
assert.NoError(t, err)
} else {
assert.Error(t, err)
}
})
}
}
If you write a business logic test using gomock or something, it seems that you can write a test for the entire project quite nicely together with this txdb.