QuickはRSpec風のBDDスタイル、Nimbleはそれに使うMatcherたち
Quick/Nimbleがそもそもなんぞやという方は↓を一読ください。

今回はポケモンでざっくり処理の役割を学ぶ回。
Contents 非表示
主要なmatcher
カテゴリ | Matcher | 意味 | 使用例(概要) |
---|---|---|---|
値の比較 | equal , beGreaterThan | 値が一致する、大小比較 | expect(level).to(equal(25)) |
存在・空チェック | beNil , beEmpty , contain | nil, 空配列, 含んでいるか | expect(team).to(contain("Pikachu")) |
真偽判定 | beTrue , beFalse | Boolがtrue/falseか | expect(isLegendary).to(beTrue()) |
非同期 | toEventually , toEventuallyNot | 値の変化を待つ | expect(x).toEventually(equal(...)) |
条件式(代替) | to(beTrue()) | 複雑な条件の判定 | expect(x > 10 && y == z).to(beTrue()) |
サンプルテストコード
import Quick
import Nimble
import Foundation
struct Pokemon: Equatable {
let name: String
let level: Int
let type: String
let evolution: String?
let team: [String]
let isLegendary: Bool
}
final class PokemonSpec: QuickSpec {
override class func spec() {
describe("Pokemon Matcher Examples") {
var pikachu: Pokemon!
var mewtwo: Pokemon!
var emptyTeam: [String]!
beforeEach {
pikachu = Pokemon(
name: "Pikachu",
level: 25,
type: "Electric",
evolution: "Raichu",
team: ["Bulbasaur", "Charmander", "Squirtle"],
isLegendary: false
)
mewtwo = Pokemon(
name: "Mewtwo",
level: 70,
type: "Psychic",
evolution: nil,
team: [],
isLegendary: true
)
emptyTeam = []
}
// 値の比較
context("Level Comparison") {
it("ミュウツーのレベルはピカチュウより高い、ピカチュウのレベルは25") {
expect(mewtwo.level).to(beGreaterThan(pikachu.level))
expect(pikachu.level).to(equal(25))
}
}
// 存在と空チェック
context("Team and Evolution Checks") {
it("nilと空をチェック") {
expect(mewtwo.evolution).to(beNil())
expect(emptyTeam).to(beEmpty())
expect(pikachu.team).to(contain("Bulbasaur"))
}
}
// 真偽チェック
context("Legendary Status") {
it("ミュウツーは伝説のポケモンである、ピカチュウはそうではない") {
expect(mewtwo.isLegendary).to(beTrue())
expect(pikachu.isLegendary).to(beFalse())
}
}
// 非同期チェック (簡易版)
context("Asynchronous Test With toEventually") {
it("ピカチュウは進化する") {
var evolvingPikachu: Pokemon? = nil
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
evolvingPikachu = pikachu
}
expect(evolvingPikachu?.name).toEventually(equal("Pikachu"))
expect(evolvingPikachu?.evolution).toEventuallyNot(beNil())
}
}
// 条件チェック & 同一インスタンス
context("Advanced Matchers") {
it("特定のConditionを満たすピカチュウ") {
expect(pikachu.level >= 20 && pikachu.type == "Electric").to(beTrue())
}
it("同一インスタンスのチェック") {
let sameMewTwo = mewtwo
expect(mewtwo).to(equal(sameMewTwo))
}
}
}
}
}
SwiftLint の nimble_operator
警告がでたら(→ offでもいい or 演算子使ってもOK)
まとめ:テストは「難しさ」より「慣れ」
- Matcherが分かれば、テストコードは「読みやすく、書きやすく」なる
- 今回のような感覚で覚えれば、怖くないし、テスト文化も育つ
- 次のステップ:実アプリで使う、↓が少し参考になるかも