Slide 1

Slide 1 text

࠷ۙɺςετίʔυ؀ڥ ͲΜͳ͔Μ͡Ͱ͔͢ʁ ΅͘͸͜Μͳ͔Μ͡Ͱ͢ɻ ॴ ༑ଠ @tokorom iOS App Programer These are “not” confidential sessions—please “not” refrain from blogging, or taking pictures Yokohama iPhone Developers #14

Slide 2

Slide 2 text

Agenda • ඇಉظॲཧͷςετ • matcher •ͦͷଞϥΠϒϥϦ • CUI & Guard •ίʔυΧόϨοδ •CI

Slide 3

Slide 3 text

લఏ৚݅ • ඪ४ͷXCTestϑϨʔϜϫʔΫΛ࢖͏͜ͱ • Command + U Ͱςετ࣮ߦ & Xcode୯ମͰ΋ ςετ݁Ռ͕֬ೝͰ͖Δ͜ͱ • ͜ͷൣғͰ֎෦ϥΠϒϥϦͷར༻Λڐ༰

Slide 4

Slide 4 text

ඇಉظॲཧͷςετ

Slide 5

Slide 5 text

GHUnit - (void)testExample { [self prepare]; __block NSString *response = nil; [self requestGetAsyncronous:^(id res, NSError *error) { response = res; if (error) { [self notify:kGHUnitWaitStatusSuccess]; } else { [self notify:kGHUnitWaitStatusFailure]; } }]; [self waitForStatus:kGHUnitWaitStatusSuccess timeout:10.0]; XCTAssertEqualObjects(response, @“OK!”); }

Slide 6

Slide 6 text

GHUnit • GHAsyncTestCase •̎೥લ͘Β͍͸σϑΝΫτελϯμʔυ • ͦͷࠒ͔Β͋·ΓUpdate͞Εͣ࠷৽ͷXcode & iOSͰ࢖͑ͳ͍ঢ়گ͕ଓ͘͜ͱ΋͋ͬͨ •ݱࡏ͸ x2on ͞Μ͕͕Μ͹ͬͯXcode 5 & iOS 7 Ͱ΋ಈ͘໛༷

Slide 7

Slide 7 text

ΦϨΦϨAsyncTestCase • ݱࡏͷσϑΝΫτʁ • ࣗ෼΋͍ͭઌ೔·ͰίϨ •ϝϦοτ •GHUnitͱಉ͡ײ֮Ͱ࢖͑Δ • σϝϦοτ •ΦϨΦϨͰ͍͍ͷ͔ʁ • ਌Ϋϥε͕ݶఆ͞ΕΔͷ͕௧͍ •Rubyist͔Βμα͍ͬͯݴΘΕͨ

Slide 8

Slide 8 text

will @ Expecta - (void)testExample { __block NSString *response = nil; [self requestGetAsyncronous:^(id res, NSError *error) { response = res; }]; expect(response).will.equal(@“OK!”); }

Slide 9

Slide 9 text

will @ Expecta •ྑ͍ͱ͜Ζ •ίʔυྔ͕ܶతʹݮΔ •਌Ϋϥε͕റΒΕͳ͍ •Rubyist΋ೲಘ •ѱ͍ͱ͜Ζ •matcherʹΑͬͯ͸ରԠͯ͠ͳ͍ •match͠ͳ͍ͱλΠϜΞ΢τ·Ͱ଴ͭ •matcher͕࿈ଓ͢Δ৔߹Ͳ͏ॻ͘?໰୊

Slide 10

Slide 10 text

RubyMotion it 'should be xxx' do some_method_with_block {|some_data| @data = some_data resume } wait_max 1.0 do @data.should.equal ‘OK!’ end end

Slide 11

Slide 11 text

͜͏͍͏ͷ͕ཧ૝ •RubyMotionελΠϧͷObjective-C൛ •wait & resume Ͱγϯϓϧʹ •wait΋ExpectaΈ͍ͨʹλΠϜΞ΢τઃఆΛলུՄ •match͠ͳͯ͘΋଴ͨ͞Εͳ͍

Slide 12

Slide 12 text

࡞ͬͨΑʂ - (void)testExample { __block NSString *response = nil; [self requestGetAsyncronous:^(id res, NSError *error) { response = res; RESUME; }]; WAIT; XCTAssertEqualObjects(response, @“OK!”); }

Slide 13

Slide 13 text

TKRGuard •ձࣾͰطʹ࣮༻Խ •waitͷೖΕࢠ΋Մೳ •GHUnitͷΑ͏ͳnotifyϞʔυ΋࣮૷༧ఆ •Macroݏ͍ͳਓ͸SHORTHANDϞʔυΛOffʹ͠ ͯͶ https://github.com/tokorom/TKRGuard

Slide 14

Slide 14 text

matcher

Slide 15

Slide 15 text

matcher •matcherʹ͍ͭͯ͸XCTAssertsͰ΋ͳΜͱ͔ͳ Γͦ͏ •΅͘͸Expecta͕޷ΈͰ͢

Slide 16

Slide 16 text

XCTAsserts int i1 = 100; NSInteger i2 = 100; NSNumber *number = @100; NSString *string = @"OK"; ! XCTAssertEqual(i1, 100); XCTAssertEqual((int)i2, 100); XCTAssertEqualObjects(number, @100); XCTAssertEqualObjects(string, @"OK");

Slide 17

Slide 17 text

OCHamcrest int i1 = 100; NSInteger i2 = 100; NSNumber *number = @100; NSString *string = @"OK"; assertThatInt(i1, equalToInt(100)); assertThatInteger(i2, equalToInteger(100)); assertThat(number, equalTo(@100)); assertThat(string, equalTo(@"OK"));

Slide 18

Slide 18 text

Expecta int i1 = 100; NSInteger i2 = 100; NSNumber *number = @100; NSString *string = @"OK"; expect(i1).to.equal(100); expect(i2).to.equal(100); expect(number).to.equal(@100); expect(string).to.equal(@"OK");

Slide 19

Slide 19 text

ςετࣦഊ࣌ͷΨΠυ • XCTAsserts •("OK") is not equal to ("NG") •(([number isKindOfClass:[NSString class]]) is true) failed • OCHamcrest •Expected "NG", but was "OK" •Expected an instance of NSString, but was __NSCFNumber instance <100> •Expecta •expected: NG, got: OK •expected: a kind of NSString, got: an instance of __NSCFNumber, which is not a kind of NSString

Slide 20

Slide 20 text

ͦͷଞϥΠϒϥϦ

Slide 21

Slide 21 text

ͦͷଞ࢖͍ͬͯΔϥΠϒϥϦ • OCMock •ಛఆͷςετͷͱ͖ʹڧ੍తʹΤϥʔΛฦ ͍ͨ͠ͱ͔ݩͷιʔεΛ͍͡Βͣʹςετ ༻ʹڍಈΛม͑ΒΕΔ •andDo ͱ͔ศརʂ • OHHTTPStubs •࣮ࡍʹ௨৴ͤͣ͞ʹςετ༻ͷσʔλʹࠩ ͠ସ͑Δͷ͕؆୯

Slide 22

Slide 22 text

CUI & Guard

Slide 23

Slide 23 text

Xcode 4.x xcodebuild \ -project $(PROJECT) \ -target $(TEST_TARGET) \ -sdk iphonesimulator \ -configuration Debug \ TEST_AFTER_BUILD=YES \ TEST_HOST=

Slide 24

Slide 24 text

Xcode 5.x xcodebuild test \ -scheme $(SCHEME) \ -destination $(DESTINATION)

Slide 25

Slide 25 text

Guard

Slide 26

Slide 26 text

Guard require 'guard/plugin' ! module ::Guard class InlineGuard < ::Guard::Plugin SCHEME = 'Tests' DESTINATION = 'platform=iOS Simulator,name=iPhone Retina (3.5-inch),OS=7.0' COMMAND = "xcodebuild test -scheme #{SCHEME} -destination '#{DESTINATION}'" def run_all system(COMMAND) end def run_on_changes(paths) run_all end end end ! guard :inline_guard do watch /.*\.[mh]$/ end

Slide 27

Slide 27 text

xcpretty (xctoolېࢭલఏͰʣ

Slide 28

Slide 28 text

xcpretty gem install xcpretty ! xcodebuild test \ -scheme $(SCHEME) \ -destination $(DESTINATION) \ | xcpretty -c

Slide 29

Slide 29 text

ฤूதͷςετ͚࣮ͩߦ͍ͨ͠ • xctoolΛ࢖͑͹Ͱ͖Δ͚Ͳ… •xcodebuild୯ମͰ͸Ͱ͖ͳ͍ͬΆ͍ •xctestίϚϯυͰ࣮ݱՄೳͬΆ͍͕·ͩௐࠪத •xctest·Ͱͷͭͳ͗ͱͯ͠xcodebuild୯ମͰ΋ Ͱ͖ΔϥΠϒϥϦΛ࡞ͬͨ

Slide 30

Slide 30 text

TKRSpecificTest xcodebuild test \ -scheme $(SCHEME) \ -destination $(DESTINATION) \ GCC_PREPROCESSOR_DEFINITIONS='TEST_ONLY=\"TestCase\"'

Slide 31

Slide 31 text

ίʔυΧόϨοδ

Slide 32

Slide 32 text

ίʔυΧόϨοδ

Slide 33

Slide 33 text

xxx.gcno & xxx.gcda GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES \ GCC_GENERATE_TEST_COVERAGE_FILES=YES !

Slide 34

Slide 34 text

Xcode 5 & iOS 7 •gcda͕ग़ྗ͞Εͳ͍ʂʁ

Slide 35

Slide 35 text

Xcode 5 & iOS 7 extern void __gcov_flush(void); __gcov_flush();

Slide 36

Slide 36 text

XCTestObserver

Slide 37

Slide 37 text

XCTestObserver NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:@"XCTestLog,XXXObserver" forKey:XCTestObserverClassKey]; [defaults synchronize];

Slide 38

Slide 38 text

XCTestObserver @interface XXXObserver : XCTestObserver @end ! @implementation XXXObserver - (void)stopObserving { [super stopObserving]; extern void __gcov_flush(void); __gcov_flush(); } ! @end

Slide 39

Slide 39 text

՝୊ • ී௨ʹ΍Δͱ gcda ͕ग़ྗ͞Εͣ •_gcov_flush() ͢Δͱ gcno ͕ग़ྗ͞Εͣ •ݱঢ়ɺී௨ʹtestɺ_gcov_flush()෇͖Ͱtestͷ̎ ஈߏ੒Ͱ΍͍ͬͯΔʢແବʣ

Slide 40

Slide 40 text

CI

Slide 41

Slide 41 text

σʔλͷ഑෍ • ͜ͷKeynote •=> Speaker DeckʹΞοϓ͠·͢ • αϯϓϧίʔυ •https://github.com/tokorom/CompareObjcMatcher •https://github.com/tokorom/ ReplaceImageCategoryForXcode •https://github.com/tokorom/TKRGuard •https://github.com/tokorom/TKRSpecificTest !

Slide 42

Slide 42 text

More Information Yuta ToKoRo! iOS App Programer! @tokorom! ! http://www.tokoro.me/