質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Q&A

解決済

1回答

1752閲覧

データベースのテスト

ikasoumen

総合スコア110

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

0グッド

1クリップ

投稿2017/02/12 00:41

編集2017/02/12 01:34

###前提・実現したいこと
現在データベースを使用したアプリケーションを開発していますが、
データベースを絡めたテストが難航しています。

アプリケーション内に閉じたテストであれば、
出力結果をユニットテストレベルで確認することは容易ですが、
データベースの更新ロジックを変更した場合、
確認に時間がかかっています。

具体的にどういったことに時間がかかっているかというと、

  1. 差分が上手くとれない

日付やautoincrementで自動採番されたりする項目があり、順番が上手く並ばない

  1. 差分確認まで時間がかかる

データ登録、データ出力を手動で行っており、
変更後の差分確認まで時間がかかる。
割り込みで作業が入ると、集中力が途切れる。

みなさんはどうやっているのでしょうか?
何か手法など教えていただけると嬉しいです。

#システム構成
Access(データエントリー) - MySQL - WEB(帳票出力)

お使いのプログラム言語は、一致していなくともかまいません。

以上、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

日付やautoincrementで自動採番されたりする項目があり、順番が上手く並ばない

そもそもMySQLは挿入したデータを常に同じ順番で持つことを保証していません。
なので、取り出すSQLもセットで考える必要があります。

データ登録、データ出力を手動で行っており、変更後の差分確認まで時間がかかる。

テスティングフレームワークを使って自動化をしましょう。
使用言語とのAND検索でこれぞと言うものが出てくるかと思います。


全体的に見て得られた印象から回答します。
これは結合テストをコードレベルで解決したいという話でしょうか?
しかし、質問内容の一文ではどうも単体テストの範囲の質問のようにも見受けられます。

データベースの更新ロジックを変更した場合、確認に時間がかかっています。

単体テストの鉄則ですが、1クラスや1メソッド単位でテストしてください。
上記を見る限り最低でも2~3クラスのやり取りを全て1個のロジックでこなそうとして自爆しているようにしか見えません。

質問内容から想定した順序です(仮の名前もわりふってみました)

  1. Accessからデータを読み込む → 秘書さん
  2. 読み込んだデータを計算 → ソロバン君
  3. MySQLに格納 → 司書さん

これらの3手順はオブジェクト指向言語で組んでいるならクラスによって分割され、
各々の担当業務をしっかりこなしてくれるプログラムであるべきです。

その上で、副作用のあるロジックと副作用のないロジックを分類していきます。

秘書さんが読み込むデータは、読み込むAccessファイルが同一ならば常に同じで、
読み込んだデータはそのまま結果としてソロバン君に渡されます。
なので副作用なし、Accessファイルは軽いものを複数個用意してプロジェクトのテストフォルダにでも突っ込んでおけば良いでしょう。

ソロバン君が計算して加工するデータは入力値が同一ならば出力値は同一なはずなのでこれも副作用なし。

残った司書さんですが、MySQLへの保存は書籍IDやら格納日時を勝手に付与し始めるので副作用があります。
なので、テストの度に作って壊せるテスト用のデータベースを用意しておくと良いでしょう。
もしくは、SQL文が入力値と出力値が等価になるようにして、SQLを作るまでのメソッド、作ったSQLをMySQLに入れるメソッドの2つを用意して、SQLを作るまでのメソッドを単体テストとするやり方でも十分でしょう。


次に、難関として残ったDB回りの単体テスト方針を考えていきます。
MySQLではDateTime型へのInsertはNow()でいけます。
なので、下記のようなSQLにすれば入力値と生成されるSQLは常に等価になりますね。
(SQL文はMySQLを想定、テスト用コードはわかり易さ優先のJavaScriptっぽい何かです)

SQL

1-- 保存用SQL 2INSERT INTO books(user_id, name, modified, created) 3VALUES('1', 'リーダブルコード', now(), now())
// Assert.equalは2つの引数が等価で有るという宣言 Assert.equal( 司書.create_sql_of(ソロバン.calc(秘書.read(Accessのパス))), 保存用SQL )

このSQL文をMySQLに1度発行して確認できれば、これは1行の挿入に成功することが保証されます。
なので、司書さんはこのSQL文を作成できればテスト終了とみなして良いでしょう。


もしnow()が使えない等の状況下では一度保存してから下記のSQLで取り出してみるって方法も使えると思います。

SQL

1-- 確認用SQL 2SELECT * 3FROM books 4WHERE name = 'リーダブルコード' 5LIMIT 1
before = MySQL.query(確認用SQL); 司書.create_book(ソロバン.calc(秘書.read(Accessのパス))); after = MySQL.query(確認用SQL); Assert.equal( (after.length == before.length + 1), true );

投稿2017/02/12 06:45

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikasoumen

2017/02/12 15:39

当初はレコードレベルでしたが、性能要件を満たせないため、 あえてループ系の処理は排除し、SQLはガツン系になっています。 また、処理の前提とされているデータが存在しており、 それらもまた単体レベルの確認を困難とする要因にもなっています。 やはり、レコードレベルで確認が取れないと厳しいでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問