kiwi 入門 | ios rdd テストフレームワーク

Post on 22-Jul-2015

291 Views

Category:

Engineering

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Yuki Tanabe

iOS 用 RDD テストフレームワーク !

Kiwi 入門

発表の流れ

・Kiwi とは ・Kiwi を選ぶ理由 ・Kiwi の導入方法 ・Kiwi でテストを書く ・得られる恩恵 ・いつテストを書く?

発表の流れ

・Kiwi とは ・Kiwi を選ぶ理由 ・Kiwi の導入方法 ・Kiwi でテストを書く ・得られる恩恵 ・いつテストを書く?

Kiwi とは

・BDD テストフレームワーク ・RSpec 的な書き方ができる ・command + U で実行可能 ・修正 BSD ライセンス

https://github.com/allending/Kiwi

BDD?

日本語的には、振る舞い駆動開発

仕様を振る舞いとして書くことで、 テストコードが仕様書の役割を果たす。

発表の流れ

・Kiwi とは ・Kiwi を選ぶ理由 ・Kiwi の導入方法 ・Kiwi でテストを書く ・得られる恩恵 ・いつテストを書く?

Kiwi を選ぶ理由

・仕様書作成&更新の手間がなくなる ・Xcode との相性が良い(⌘Uで実行できる) ・スタブ、モック、非同期処理のテストを標準装備 ・以前利用していた JavaScript の mocha と書き方が似てた

発表の流れ

・Kiwi とは ・Kiwi を選ぶ理由 ・Kiwi の導入方法 ・Kiwi でテストを書く ・得られる恩恵 ・いつテストを書く?

通常通りプロジェクト作成

Single View Application

プロジェクト名は Alpaca とする

通常通りプロジェクト作成

Alpaca?

いらない写真をサクサク消せる iPhone アプリです

https://itunes.apple.com/app/id934444072?mt=8

プロジェクト作成完了

通常通りプロジェクト作成

テストコードの在処

ここにテストコード を追加していく(AlpacaTests.m は消しておく)

Kiwi の導入

cocoapods で導入できる

source 'https://github.com/CocoaPods/Specs.git'platform :ios, '7.0'!target :AlpacaTests, :exclusive => true do pod 'Kiwi'end

Podfile

発表の流れ

・Kiwi とは ・Kiwi を選ぶ理由 ・Kiwi の導入方法 ・Kiwi でテストを書く ・得られる恩恵 ・いつテストを書く?

今回作ってみるサンプル

クラスの概要 アプリへのセッション回数を管理するクラス !クラス名 SessionCounter!メソッド +(void)countUp; // セッションカウントを増やす +(BOOL)isFirstSession; // 初回セッションかどうか

テストケースクラスの追加

Test Case Class を選択

クラス名を入力

[対象クラス名]Spec と命名

テストケースクラス作成完了

できた!

XCTest 的記述を除去

@interface 以下を全削除

テスト対象クラスを追加

SessionCounter追加>メソッド定義

テストコード側で import

Kiwi と対象クラスを import

テストのベース部分を追加

SPEC_BEGIN ~ SPEC_END まで記述

SPEC_* ?

SPEC_BEGIN @interface や @implementation を実装したマクロ !SPEC_END @end を実装したマクロ

KiwiMacros.h

describe?

describe クラス、メソッドなどのテスト対象を記述する

describe(@"SessionCounter のテスト", ^{ // ここにテストコードを書いていく});

テストを書く

describe(@"SessionCounter のテスト", ^{ context(@"初期状態", ^{ it(@"isFirstSession は NO が返る", ^{ BOOL sessionCount = [SessionCounter isFirstSession]; [[theValue(sessionCount) should] equal:theValue(NO)]; }); });});

SessionCounterSpec.m

context? it?

context テスト対象の状態、状況を記述 !

it この状態・入力の時に、どう振る舞うべきか。 期待される出力を記述

Assertion

describe(@"SessionCounter のテスト", ^{ context(@"初期状態", ^{ it(@"isFirstSession は NO が返る", ^{ BOOL isFirstSession = [SessionCounter isFirstSession]; [[theValue(isFirstSession) should] equal:theValue(NO)]; }); });});

isFirstSession should equal NO.Assertion が直感的で分かりやすい

テストコードの可読性が高い

describe(@"SessionCounter のテスト", ^{ context(@"初期状態", ^{ it(@"isFirstSession は NO が返る", ^{ BOOL isFirstSession = [SessionCounter isFirstSession]; [[theValue(isFirstSession) should] equal:theValue(NO)]; }); });});

SessionCounterSpec.m

テストを作り上げて、実装

細かい流れは割愛しますが、 本来は最小限のテストを書いた後に テスト(仕様書)を作り上げてから、 対象クラスをテストが通るまで実装

テストを通るようにクラス修正

テストを追加

context(@"1回目のセッション", ^{ beforeAll(^{ [SessionCounter countUp]; }); it(@"isFirstSession は YES が返る", ^{ BOOL sessionCount = [SessionCounter isFirstSession]; [[theValue(sessionCount) should] equal:theValue(YES)]; }); }); context(@"2回目のセッション", ^{ beforeAll(^{ [SessionCounter countUp]; }); it(@"isFirstSession は NO が返る", ^{ BOOL sessionCount = [SessionCounter isFirstSession]; [[theValue(sessionCount) should] equal:theValue(NO)]; }); });

最終形

最終形

beforeAll? afterAll?

beforeAll ブロック内の最初に一度だけ実行される !

afterAll ブロック内の最後に一度だけ実行される

初期化処理や後処理、 事前・事後にすべき操作をここで書く

他にも...

beforeEach ブロック内の it の直前に毎回実行される !

afterEach ブロック内の it の直後に毎回実行される

テスト実行方法command + U で実行

成功すると緑に✓

実際の作業の進め方

0. テストとテスト対象の疎通確認まで 1. テストを書く 2. テスト対象のコードを書く 3. テストが成功するまで実装 4. リファクタリングする 5. テストが通るまで実装

発表の流れ

・Kiwi とは ・Kiwi を選ぶ理由 ・Kiwi の導入方法 ・Kiwi でテストを書く ・得られる恩恵 ・いつテストを書く?

得られる恩恵

・コード変更やリファクタリングがしやすくなる ・複数人開発時にバグ混入を防げる ・仕様書=テストコードなので  仕様変更の度にドキュメントを編集する必要なし

発表の流れ

・Kiwi とは ・Kiwi を選ぶ理由 ・Kiwi の導入方法 ・Kiwi でテストを書く ・得られる恩恵 ・いつテストを書く?

いつテストを書く?

・新規クラス追加時  仕様を書きながらクラス追加 !

・実装変更やリファクタリング時  実装変更前にテスト導入  実装変更後にテストが通ることを確認

サンプルコード

https://github.com/tanabee/Alpacagithub

ご清聴ありがとうございました

top related