Repository navigation
Expand file tree
/
Copy pathchapter25_database_sandbox.txt
More file actions
116 lines (75 loc) · 6.27 KB
/
Copy pathchapter25_database_sandbox.txt
File metadata and controls
116 lines (75 loc) · 6.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
{{toc}}
! Database Sandbox
!! がいよう
''How do we develop and test software that depends on a database?''
'''We provide a separate test database for each developer or tester.'''
!! がいようのほそく
* 多くのアプリケーションは永続的な状態を保存するためにデータベースを使います
* 従って、そのアプリケーションのテストもデータベースにアクセスしなければなりません
* テストごとのデータが永続化されてしまうことが ''Erratic Test'' (pp.228) となる一番の要因です
* 対話テストにならないようにするためには、それぞれのテストが使用するフィクスチャーが重ならないことを保証するようにします
** 同じデータベースで複数の開発者がすべてのテストを実行するような環境では困難なことです
!! How It Works
* ユーザごとに独立したサンドボックスを提供します
* サンドボックスには、ユーザ自身のコードのコピーと、データベースのコピー (これが一番重要) を含みます
* ユーザのやりたいようにデータベースを変更できるようになります
* テストでアプリケーションを動かしても、他のユーザへの影響を気にする必要が無くなります
!! When to Use It
* データベースが、アプリケーションの機能における重要な部品となっている場合
* ''Shared Fixture'' (pp.317) を使うなら特に必要
* ユーザ間の ''Test Run Wars'' を避けたい場合
* ''Database Sandbox'' をどうやって実装したかによって、異なるユーザがデータベースの構造を変えられるかどうかが決まります
* ''Unrepeatable Tests'' や ''Interacting Tests'' は防げません
** ユーザごとの環境を独立するだけなので、1 つのテストが実行される間はフィクスチャーは共有されます
!! Implementation Notes
* テストを実施するときは、データベースを設定によって変更できるようにしなければなりません
** プロパティファイルから設定情報を読み取るようにすることが多いです
* 実装方法は無数にあります
** ユーザごとにデータベースインスタンスを提供 (推奨)
*** ベンダーによってはライセンスごとのコストがはんぱない
** 1 つのインスタンスで複数のインスタンスのふりをする
!!! Variation: Dedicated Database Sandbox
* ユーザごとにデータベースインスタンスを提供するパターンです
* ユーザごとのテスト環境に、軽量データベースをインストールすることで実現しています
* 軽量データベース
** MySQL
** Personal Oracle
* データベースインスタンスのインストール先
** ユーザの開発環境
** 共有のテストサーバ
** 共有サーバハード上で稼動している、専用の仮想マシン
!!! Variation: DB Schema per Test Runner
* 複数スキーマをサポートしたデータベースによって、ユーザごとに独立したデータベースインスタンスを提供する
* ''Dedicated Database Sandbox'' に対するメリット
** 共通スキーマに ''Immutable Shared Fixture'' を定義し、各ユーザのプライベートスキーマには変更されるフィクスチャーを定義することができます
** 全てのユーザにおいて、プライベートスキーマとはいえ、構造を変えることは許されません
** データベースの構造が変更されるときはちょっとした問題になります
!!! Variation: Database Partitioning Scheme
* 1 つの ''Database Sandbox'' で、開発者、テスター、ユーザーそれぞれに分離されたデータを提供します
* ユーザは自分のデータは変更できるが、他のユーザのデータは変更できません
* データベース管理の手間があまりかかりませんが、他の方法に比べてデータ管理の手間がかかります
* 開発者にデータベーススキーマを変更させないので、進化的なデータベース開発には向きません
* ''Interacting Test'' の回避に向いています
** 同じテストランナーによる異なるテストの実行に応用
** 全てのデータを使用していたテストについて、ユニークな顧客番号を指定します
** 他のユーザが同じテストを実行しても、使用するデータが別になります
* このパターンは他の ''Database Sandbox'' のバリエーションと組み合わせて ''Shared Fixture'' にすることで、''Interacting Test'' を回避できます
* このパターンを使っても、''Distinct Generated Values'' (pp.723) を使っていない限り、''Unrepetable Test'' は回避できません
!! Motivating Example
* 元のテストは Product のコンストラクタ引数に即値リテラルを使ってます
* Product は複数の開発者の共有するデータベースインスタンスに永続化されるものです
* Product の名前はユニークでなければなりません
[code]
* テストの後にどれだけ Product を綺麗に teardown したとしても、このテストは ''Test Run War'' になってしまいます
* 同じタイミングで他のテストランナーによって実行した同じテストが、同じ Product を作ろうとするからです
!! Refactoring Notes
* ユーザごとの ''Dedicated Database Sandbox'' を使っているなら修正はいりません
** テストは他のテストランナーから完全に独立して実行されます
* SUT には、設定によって異なるデータベースインスタンスに接続できるようなちょっとした改修が必要です
** やりかたは使用しているテクノロジーによって違ってくるし、この本の範疇を越えています
* 即値リテラルを getUnique メソッド呼び出しによって置き換えることができます
!!! Example: Database Partitioning Scheme
* ''Database Partitioning Scheme'' を使う例です
** テストが異なる product を使うことを保証します
** getUniqueString の引数には、コンピュータの MAC アドレスを渡しています
[code]