-
-
Notifications
You must be signed in to change notification settings - Fork 906
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #478 from takecian/ja-docs
Add Ja docs
- Loading branch information
Showing
2 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# コードをテストせず、動作を確認する | ||
|
||
テストはアプリケーションが**期待と異なる動作** をした時のみ失敗するようにすべきです。 | ||
アプリケーションコードが *何を* したかをテストすべきで、*どのように* したかをテストすべきではありません。 | ||
|
||
- アプリケーションが *何を* したかを確認するテストは **動作テスト(behavioral tests)** といいます。 | ||
- アプリケーションの動作が変わっていなくても、コードを変更すると失敗するようになるテストは **脆弱なテスト(brittle tests)** といいます。 | ||
|
||
ここで `GorillaDB` というバナナのデータベースを用意します。 | ||
`GorillaDB`は Key-Value 型のデータベースでバナナを保存することができます。 | ||
|
||
```swift | ||
let database = GorillaDB() | ||
let banana = Banana() | ||
database.save(banana: banana, key: "my-banana") | ||
``` | ||
|
||
そしてバナナをディスクから取り出すことができます。 | ||
|
||
```swift | ||
let banana = database.load(key: "my-banana") | ||
``` | ||
|
||
## 脆弱なテスト(Brittle Tests) | ||
|
||
どのようにして動作をテストするのでしょう?一つの方法としてここではバナナを保存した後にバナナのデータベースのサイズをチェックします。 | ||
|
||
```swift | ||
// GorillaDBTests.swift | ||
|
||
func testSave_savesTheBananaToTheDatabase() { | ||
// Arrange: Create a database and get its original size. | ||
let database = GorillaDB() | ||
let originalSize = database.size | ||
|
||
// Act: Save a banana to the database. | ||
let banana = Banana() | ||
database.save(banana: banana, key: "test-banana") | ||
|
||
// Assert: The size of the database should have increased by one. | ||
XCTAssertEqual(database.size, originalSize + 1) | ||
} | ||
``` | ||
|
||
ここで `GorillaDB` のソースコードを変更したとします。データベースからの読み出しを速くするためにもっとも頻繁に使用するバナナをキャッシュに保持するようにします。 | ||
`GorillaDB.size` はキャッシュのサイズに合わせて大きくなります。この場合ディスクに保存しなくなるため上記のテストは失敗します。 | ||
|
||
![](http://cl.ly/image/0G2s3B3d2F3O/Screen%20Shot%202015-02-23%20at%204.07.32%20PM.png) | ||
|
||
## 動作テスト(Behavioral Tests) | ||
|
||
動作のテストの重要なポイントは アプリケーションコードに期待する動作を明確にすることです。 | ||
The key to writing behavioral tests is determining exactly what you're expecting | ||
your application code to do. | ||
|
||
`testSave_savesTheBananaToTheDatabase` というテストで期待する動作は バナナをデータベースに "保存する" ことでしょうか? | ||
"保存する"というのは 後から読み出すことができる、という意味です。そのためデータベースのサイズが大きくなることをテストするのではなく、 | ||
バナナを読みだすことができるかをテストすべきです。 | ||
|
||
|
||
```diff | ||
// GorillaDBTests.swift | ||
|
||
func testSave_savesTheBananaToTheDatabase() { | ||
// Arrange: Create a database and get its original size. | ||
let database = GorillaDB() | ||
- let originalSize = database.size | ||
|
||
// Act: Save a banana to the database. | ||
let banana = Banana() | ||
database.save(banana: banana, key: "test-banana") | ||
|
||
- // Assert: The size of the database should have increased by one. | ||
- XCTAssertEqual(database.size, originalSize + 1) | ||
+ // Assert: The bananas saved to and loaded from the database should be the same. | ||
+ XCTAssertEqual(database.load(key: "test-banana"), banana) | ||
} | ||
``` | ||
|
||
動作テストを書く際の重要なポイント: | ||
|
||
- アプリケーションコードが何をすべきか明確にしているか? | ||
- テストが *動作のみ* をテストしているか?コードの動作が他の要因で意図しない動きにならないか。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# Nimble Assertions を使ってテストをより簡潔に | ||
|
||
テストが期待した通りに動作しない時、ユニットテストは **何が問題か** を明確にすべきです。 | ||
|
||
次の関数はサルの集団から馬鹿なサルだけを取得します。 | ||
|
||
```swift | ||
public func silliest(monkeys: [Monkey]) -> [Monkey] { | ||
return monkeys.filter { $0.silliness == .VerySilly } | ||
} | ||
``` | ||
|
||
ここでこの関数に対するテストを書いてみましょう。 | ||
|
||
```swift | ||
func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { | ||
let kiki = Monkey(name: "Kiki", silliness: .ExtremelySilly) | ||
let carl = Monkey(name: "Carl", silliness: .NotSilly) | ||
let jane = Monkey(name: "Jane", silliness: .VerySilly) | ||
let sillyMonkeys = silliest([kiki, carl, jane]) | ||
XCTAssertTrue(contains(sillyMonkeys, kiki)) | ||
} | ||
``` | ||
|
||
このテストは下記のメッセージとともに失敗します。 | ||
|
||
``` | ||
XCTAssertTrue failed | ||
``` | ||
|
||
![](http://f.cl.ly/items/1G17453p47090y30203d/Screen%20Shot%202015-02-26%20at%209.08.27%20AM.png) | ||
|
||
失敗した時は多くの情報を残すことが望ましいです。このメッセージのままではよく分かりません。 | ||
true や false だけではそれがなにか分かりません。このままではテストコードから原因を見つけるまでに時間がかかってしまいます。 | ||
|
||
## 良い失敗メッセージを残す: Part 1: XCTAssert に手動でメッセージを渡す | ||
|
||
`XCTAssert` は失敗時にメッセージを指定することができます。 | ||
|
||
```diff | ||
func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { | ||
let kiki = Monkey(name: "Kiki", silliness: .ExtremelySilly) | ||
let carl = Monkey(name: "Carl", silliness: .NotSilly) | ||
let jane = Monkey(name: "Jane", silliness: .VerySilly) | ||
let sillyMonkeys = silliest([kiki, carl, jane]) | ||
- XCTAssertTrue(contains(sillyMonkeys, kiki)) | ||
+ XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") | ||
} | ||
``` | ||
|
||
しかし`XCTAssert`では自分でメッセージを指定しないといけません。 | ||
|
||
## 良い失敗メッセージを残す: Part 2: Nimble Failure Messages を使う | ||
|
||
Nimble は Assert, 失敗時のメッセージを読みやすくしてくれます。 | ||
|
||
```diff | ||
func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { | ||
let kiki = Monkey(name: "Kiki", silliness: .ExtremelySilly) | ||
let carl = Monkey(name: "Carl", silliness: .NotSilly) | ||
let jane = Monkey(name: "Jane", silliness: .VerySilly) | ||
let sillyMonkeys = silliest([kiki, carl, jane]) | ||
- XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") | ||
+ expect(sillyMonkeys).to(contain(kiki)) | ||
} | ||
``` | ||
|
||
Nimble では自分でメッセージを指定しなくても Nimble がとても読みやすいメッセージを返してくれます。 | ||
|
||
``` | ||
expected to contain <Monkey(name: Kiki, sillines: ExtremelySilly)>, | ||
got <[Monkey(name: Jane, silliness: VerySilly)]> | ||
``` | ||
|
||
![](http://f.cl.ly/items/3N2e3g2K3W123b1L1J0G/Screen%20Shot%202015-02-26%20at%2011.27.02%20AM.png) | ||
|
||
失敗メッセージは何が問題かを明確にします:ここでは `kiki` が `silliest()` の戻り値に含まれることを期待していますが | ||
このテストでは 'jane' しか含まれていません。Nimble からのメッセージで何が問題かが分かりやすく伝えられるので、簡単に直すことができます。 | ||
|
||
```diff | ||
public func silliest(monkeys: [Monkey]) -> [Monkey] { | ||
- return monkeys.filter { $0.silliness == .VerySilly } | ||
+ return monkeys.filter { $0.silliness == .VerySilly || $0.silliness == .ExtremelySilly } | ||
} | ||
``` | ||
|
||
Nimble は具体的な失敗メッセージを返してくれる多くの種類の Assertion を提供します。 | ||
`XCTAssert` と違って毎回自分でメッセージを指定することはありません。 | ||
|
||
Nimble の全ての assertion はこちらで確認できます: [Nimble README](https://github.com/Quick/Nimble) 。 | ||
下記に幾つかの例を示します。 | ||
|
||
```swift | ||
expect(1 + 1).to(equal(2)) | ||
expect(1.2).to(beCloseTo(1.1, within: 0.1)) | ||
expect(3) > 2 | ||
expect("seahorse").to(contain("sea")) | ||
expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) | ||
expect(ocean.isClean).toEventually(beTruthy()) | ||
``` |