let s database_testing
TRANSCRIPT
![Page 1: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/1.jpg)
let's database testing!!
2010/10/16 YAPC::Asia 2010@xaicron
![Page 2: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/2.jpg)
自己紹介
name: Yuji Shimada ( 嶋田 裕二 )
works: DeNAtwitter: @xaicronblog: http://blog.livedoor.jp/xaicron/
![Page 3: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/3.jpg)
皆さん
![Page 4: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/4.jpg)
データーベース処理のテスト
![Page 5: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/5.jpg)
してますか?
![Page 6: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/6.jpg)
DB のテストをすると
この SELECT なんにもマッチしない...INSERT したデータが文字化けしてるやん!UPDATE や DELETE に WHERE 付け忘れてて全件あばばば TRIGGER が間違ってて、データ壊れた。。。
![Page 7: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/7.jpg)
という事態を未然に防げます!
![Page 8: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/8.jpg)
というか。。。
![Page 9: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/9.jpg)
永続的なストレージに実際に入出力があるんだから
テストするのはあたりまえですね!
![Page 10: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/10.jpg)
今回は MySQL に焦点を絞ってお話します
![Page 11: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/11.jpg)
ORM の話もしません
![Page 12: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/12.jpg)
基本的には 生DBI をつかってやります
![Page 13: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/13.jpg)
Haw To Testing
![Page 14: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/14.jpg)
鉄則
![Page 15: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/15.jpg)
ローカルでテストできる環境を作ること!!
![Page 16: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/16.jpg)
よくない例
ステージング環境のDBに接続してテストする本番は MySQL だけど、テストでは SQLite を使う自分のローカルに立ち上がっている MySQL をテストに使う
![Page 17: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/17.jpg)
実際に存在している DB を使ってテストすると、毎回データが変わってテストにならない本番は MySQL なのに テストでは SQLite とかは意味がない
![Page 18: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/18.jpg)
Test の大まかな流れ
Test::mysqld を使って毎回クリーンな mysql を立ち上げるTest::Fixture::DBI を使ってテストデータを突っ込むDB 接続して、実際にデータの入出力が行われているかテストそして伝説へ...
![Page 19: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/19.jpg)
Test::mysqld
new するだけで、lcoal に 新規 mysql が立ち上がるDESTROY が走ったら、自動的に mysql を落とすAuthor: kazuhooku
![Page 20: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/20.jpg)
DEMO
![Page 21: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/21.jpg)
Test::Fixture::DBI
table 作ったり、 procedure / function / trigger 作ったり、data ぶっこんだりできる既存の DB から schema 定義をもってきたり、指定のレコードをとって来たりできる
make_*_yaml.pl で fixture や database 定義を YAML に吐き出せる
Author: ZIGOROu, (test: xaicron)
![Page 22: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/22.jpg)
DEMO
![Page 23: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/23.jpg)
なかなか便利ですが
![Page 24: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/24.jpg)
テスト毎にこれを毎回書くのはめんどいので
![Page 25: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/25.jpg)
適当に組み合わせたTest Module を書いて使うと
いいでしょう
![Page 26: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/26.jpg)
Test::Foo::Fixture::DBIみたいな名前にして
setup_
![Page 27: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/27.jpg)
実際のテストの書き方
![Page 28: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/28.jpg)
の前に
![Page 29: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/29.jpg)
DBI を直接扱う上で便利なモジュールを紹介します
![Page 30: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/30.jpg)
DBI と親和性の高いモジュール
SQL::AbstractDBIx::DBHResolverDBIx::Connector
![Page 31: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/31.jpg)
DBIx::Connector ->DBIx::DBHResolver ->
DBI
![Page 32: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/32.jpg)
という感じでラップするとなかなかいい感じ
![Page 33: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/33.jpg)
DBIx::Connector
DBI の超薄いラッパー
$dbh を局所化できる多分最大の利点
fixup => で再接続トランザクション処理をよしなにやってくれる
![Page 34: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/34.jpg)
DBIx::DBHResolver
DBI 専用の container みたいなノリ複数の DB に接続するのに便利
Master / SlaveUser と Diary が別の DB
Sharding していてもかなり直感的
DBIx::Connector とも協調しやすい
![Page 35: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/35.jpg)
+SQL::Abstract
![Page 36: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/36.jpg)
my $row = $model->connector('SLAVE')->txn(fixup => sub { my $dbh = shift; my ($stmt, @bind) = $model->sql->select(...); return $dbh->selectrow_hashref($stmt, undef, @bind);});
![Page 37: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/37.jpg)
みたないな感じでつかえる
![Page 38: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/38.jpg)
ようやく実際のテストの話
![Page 39: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/39.jpg)
SELECT した結果を返すもののテスト
![Page 40: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/40.jpg)
my $row = try { $self->connector('SLAVE', $user_id)->run(fixup => sub { my $dbh = shift; my ($stmt, @bind) = $self->sql->select( 'user_data', [qw/id name/], { id => $user_id, disabled => 0 }, ); $dbh->selectrow_hashref($stmt, undef, @bind); });}catch { my $e = $_; ...};
![Page 41: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/41.jpg)
mysqld に fixture を入れる実際にたたいて値を取得取得した値が正しいかチェック
![Page 42: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/42.jpg)
DEMO
![Page 43: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/43.jpg)
INSERT のテスト
![Page 44: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/44.jpg)
try { my $seq = $self->next_seq('MASTER', 'seq_tweet'); $self->connector('MASTER', $user_id)->run(fixup => sub { my $dbh = shift; my ($stmt, @bind) = $self->sql->insert( 'tweet', { id => $seq, ... }, ); $dbh->do($stmt, undef, @bind); $dbh->commit; });}catch { my $e = $_;};
![Page 45: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/45.jpg)
実際にたたいて値を入力正常に INSERT されているかチェック
![Page 46: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/46.jpg)
UPDATE とか DELETE も同じ感じ
![Page 47: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/47.jpg)
特別に難しいことはやっていない
![Page 48: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/48.jpg)
すべての SQL に対して地道にテストを書きましょう
![Page 49: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/49.jpg)
PROCEDURE / FUNCTION/ TRIGGER
のテスト
![Page 50: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/50.jpg)
FUNCTION とは
そのまんま一連のSQLを関数化できるCALL function_name(args) で呼べる値を返すので、参照系に使える
![Page 51: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/51.jpg)
PROCEDURE と
値を返さない FUNCTION主に更新用途 CALL procedure_name(args) で呼べる
![Page 52: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/52.jpg)
TRIGGER とは
テーブルの更新タイミングで発火INSERT / UPDATE / DELETE
SQL なら何でも書ける
PROCEDURE をよく使う (更新なので)
![Page 53: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/53.jpg)
FUNCTION のテスト
![Page 54: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/54.jpg)
SELECT とおんなじ
![Page 55: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/55.jpg)
PROCEDURE / TRIGGERのテスト
![Page 56: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/56.jpg)
INSERT / UPDATE /DELETEとおんなじ
![Page 57: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/57.jpg)
Test::mysqld の問題点
![Page 58: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/58.jpg)
make test したときにすっごい時間がかかる orz
![Page 59: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/59.jpg)
1テスト毎に mysqld を立ち上げて落としてるから仕方ないよね
![Page 60: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/60.jpg)
なんとかしたい
![Page 61: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/61.jpg)
なんとかしたい
![Page 62: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/62.jpg)
![Page 63: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/63.jpg)
Makefile の書き換え大変です!
![Page 64: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/64.jpg)
Module かいたよーModule::Install::ExtendsMakeTest
![Page 65: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/65.jpg)
replace_default_make_test( includes => ['t/lib'], modules => ['Test::MyApp::DB'], before_run_codes => [ sub { $SIG{INT} = sub { CORE::exit 1 }; my $db = Test::MyApp::DB->setup; $ENV{TEST_MY_SOCKET} = $db->my_cnf->{socket}; }, ], );
![Page 66: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/66.jpg)
みたいな感じで書くとmake test 時に mysqld
が立ち上がる
![Page 67: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/67.jpg)
あとは、socket ファイルとかを指定して接続すれば OK
![Page 68: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/68.jpg)
$ENV に値があったら立ち上がっている mysqld を使って、
なかったら 新規に立ち上げるようにしておけばいい
![Page 69: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/69.jpg)
DEMO
![Page 70: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/70.jpg)
というわけで
![Page 71: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/71.jpg)
プログラムから扱いそうなDB の処理は
![Page 72: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/72.jpg)
ちゃんとテストできる!!
![Page 73: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/73.jpg)
ので、テストを書きましょう
![Page 74: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/74.jpg)
自分(とみんな)のために
![Page 75: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/75.jpg)
まとめ
地道にやっていけば DB 処理の大部分をテスト結構ツール類が充実してきているでもまだ自分で書く部分が多い印象割とこの辺のノウハウがたまりつつあるので、よくある処理は Module 化したい
![Page 77: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/77.jpg)
ご清聴ありがとうございました
![Page 78: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/78.jpg)
Questions?
![Page 79: Let s database_testing](https://reader035.vdocuments.net/reader035/viewer/2022062300/559a42691a28abc8398b481b/html5/thumbnails/79.jpg)
閑話休題