Skip to content

Commit

Permalink
Merge pull request #478 from takecian/ja-docs
Browse files Browse the repository at this point in the history
Add Ja docs
  • Loading branch information
modocache committed Feb 10, 2016
2 parents 7f7709a + f28a492 commit 8c19e2e
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 0 deletions.
83 changes: 83 additions & 0 deletions Documentation/ja/BehavioralTesting.md
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)
}
```

動作テストを書く際の重要なポイント:

- アプリケーションコードが何をすべきか明確にしているか?
- テストが *動作のみ* をテストしているか?コードの動作が他の要因で意図しない動きにならないか。
100 changes: 100 additions & 0 deletions Documentation/ja/NimbleAssertions.md
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())
```

0 comments on commit 8c19e2e

Please sign in to comment.