Test::mysqldの話
TIME rest time current/total
TopicsPlaceHolder

Test::mysqldの話

mysqlcasual #10

Feb 1st, 2017

Profile

songmu

エンジニアとして

【宣伝】みんなのGo言語という本を書きました

私とMySQL

MySQLに関するテストをどうするか

モックではカバーしきれないこともある

バージョンや設定を揃えてテストしたい

DBに対する僕のポリシー

Webアプリケーションにおいてデータベースは最終防衛ラインです。「スキーマレス」がもてはやされることもありますが、実運用においては、きちんとしたスキーマ定義ができ、データに制約をかけられるデータベースを利用するべきでしょう。まかり間違ってデータベースに変なデータが入ってしまうと、下手をすればそのデータは10年以上残ることになり、喉に刺さった小骨のようにシステム運用を苦しめ続けることになります。変なデータが入ってしまうよりかは、一時的にサーバーエラーを返したほうがマシと言えます。
http://developer.hatenastaff.com/entry/2016/05/30/080000
(インフラを意識してコードを書くということ)

テストDB問題

テスト時にテンポラリでmysqlを起動してしまう

Go版にはパッチ

Test::mysqldはコミッターに

やったこと

互換性の維持について

具体的な使い方(Goの場合)

TestMainでDB初期化

func TestMain(m *testing.M) {
    os.Exit(runTests(m))
}

func runTests(m *testing.M) int {
    testMysqld, err := mysqltest.NewMysqld(nil)
    if err != nil {
       log.Fatal("runTests: failed launch mysql server:", err)
    }
    defer testMysqld.Stop()
    setupTestDB(testMysqld)

    return m.Run()
}

スキーマ流し込み

CREATE DATABASE した後にスキーマ流し込み。可能ならfixture類も

func setupTestDB(testMysqld *mysqltest.TestMysqld) {
    db, err := sql.Open("mysql", testMysqld.DSN(mysqltest.WithDbname("")))
    if err != nil {
        log.Fatalf("Failed to setup database for testing: %s", err)
    }

    const testdbname = "hoge_test"
    _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", testdbname))
    if err != nil {
        log.Fatal("create db error:", err)
    }
    // close and re-open with created db.
    db.Close()

    // set to global variable for other tests.
    testDB, err = sql.Open("mysql", testMysqld.DSN(mysqltest.WithDbname(testdbname)))
    if err != nil {
        log.Fatalf("Failed to setup database for testing: %s", err)
    }

    applySchema()
}

mysqltestのCopyDataFrom機能

mycnf := mysqltest.NewConfig()
mycnf.CopyDataFrom = "/tmp/mysqltest_data"
testMysqld, err := mysqltest.NewMysqld(mycnf)

mysqld起動時にコピー元のdataディレクトリを指定できる機能。テスト開始時にDBに大量のデータを入れておきたい場合に、MySQLの起動時間を節約できる。(MySQL5.7だと遅いかも…)

copyDataのセットアップ

これにも、 mysqltest を利用する。

mycnf := mysqltest.NewConfig()
mycnf.DataDir = "/tmp/mysqltest_data"
testMysqld, err := mysqltest.NewMysqld(mycnf)
// 以降セットアップ

具体的な使い方(Perlの場合)

App::Prove::Plugin::MySQLPool

以上

【急募】We are Hiring

hatena