Slide 1

Slide 1 text

9DPEFͷΧόϨοδܭଌͰ͸ ͳͥϒϥϯνΧόϨοδ͕ औΕͳ͍ͷͩΖ͏͔ʁ J04%$ LBSJBE 1

Slide 2

Slide 2 text

ࣗݾ঺հ • kariad / @kariad_uu • ยࢁ େथ • ΦΠγοΫεɾϥɾେ஍גࣜձࣾ • ςετ / ઃܭ / ໊औ͞ͳ 2 ARIAͷ੟஍

Slide 3

Slide 3 text

ΞδΣϯμ • ίʔυΧόϨοδʹ͍ͭͯ • XcodeͰͷίʔυΧόϨοδܭଌͱදࣔ • XcodeͰͷίʔυΧόϨοδܭଌͷ࢓૊Έ • ·ͱΊ 3

Slide 4

Slide 4 text

ίʔυΧόϨοδʹ͍ͭͯ 4

Slide 5

Slide 5 text

ίʔυΧόϨοδͱ͸ • ιʔείʔυ͕ͲΕ͚ͩ໢ཏ͞Ε͔ͨͷׂ߹ • ԿΛ৚݅ʹ໢ཏ཰ΛݟΔ͔ෳ਺ͷ؍఺͕͋ Δ 5

Slide 6

Slide 6 text

• C0(εςʔτϝϯτΧόϨοδ)
 ໋ྩจ໢ཏɺ໋ྩจ͕ͲΕ͚ͩ໢ཏ͞Ε ͔ͨ • C1(ϒϥϯνΧόϨοδ)
 ෼ذ໢ཏɺ෼ذ͕ͲΕ͚ͩ໢ཏ͞Ε͔ͨ • C2(σΟγδϣϯΧόϨοδ)
 ৚݅໢ཏɺ৚͕݅ͲΕ͚ͩ໢ཏ͞Ε͔ͨ 6

Slide 7

Slide 7 text

9DPEFͰͷ ίʔυΧόϨοδܭଌ 7

Slide 8

Slide 8 text

8 ςετΛ࣮ߦͨ͠Β…

Slide 9

Slide 9 text

ͱͯ΋؆୯ʂ 9

Slide 10

Slide 10 text

؆୯ʹऔΕΔ͚Ͳʜ • ͲͷछྨͷΧόϨοδΛऔΔ͔બ୒Ͱ͖ͳ͍ • ͦ΋ͦ΋ͲΜͳ৚݅ͰΧόϨοδऔͬͯΔʁ 10

Slide 11

Slide 11 text

9DPEFͷ ΧόϨοδܭଌͱදࣔͷ࣮ଶ 11

Slide 12

Slide 12 text

• ·ͣ͸ԿΛ৚݅ͱͨ͠ΧόϨοδΛදࣔ ͍ͯ͠Δ͔ 12

Slide 13

Slide 13 text

• ࢀߟʹͳΔͷ͸WWDC 2018ͷ
 What’s New in Testing
 
 https://developer.apple.com/videos/play/ wwdc2018/403/ 13

Slide 14

Slide 14 text

• xccovͷ঺հ෦෼Ͱ໌֬ʹ
 Line coverage percentͱݴ͍ͬͯΔ • xccovͷ঺հͰ͸͋Δ͕ɺҧ͏΋ͷΛදࣔ ͍ͤͯ͞Δͱ΋ߟ͑ͮΒ͍ 14

Slide 15

Slide 15 text

YDDPWͱ͸ • Apple͕࡞ͬͨΧόϨοδΛਓʹ΋ಡΈ΍͢ ͘දࣔͤ͞Δπʔϧ • JSONͰͷग़ྗ΋Ͱ͖Δ 15

Slide 16

Slide 16 text

ΧόϨοδͷݩσʔλ • xccovͰ࢖͏ιʔε͸Build/Logs/Test഑Լͷ 16

Slide 17

Slide 17 text

YDDPWΛ࢖࣮ͬͯࡍʹ ݟͯΈΔ xcrun xccov view action.xccovreport ΧόϨοδͷ֓ཁΛݟͯΈΔ 17

Slide 18

Slide 18 text

/Users/daiki/workspace/sandbox/MVP_ConnpassEventSearch/MVP_ConnpassEventSearch/ MVP_ConnpassEventSearch/AppDelegate.swift 48.15% (13/27) MVP_ConnpassEventSearch.AppDelegate.application(_: __C.UIApplication, didFinishLaunchingWithOptions: Swift.Optional>) -> Swift.Bool 100.00% (10/10) MVP_ConnpassEventSearch.AppDelegate.applicationWillResignActive(__C.UIApplication) -> () 0.00% (0/4) MVP_ConnpassEventSearch.AppDelegate.applicationDidEnterBackground(__C.UIApplication) -> () 0.00% (0/4) MVP_ConnpassEventSearch.AppDelegate.applicationWillEnterForeground(__C.UIApplication) -> () 0.00% (0/3) MVP_ConnpassEventSearch.AppDelegate.applicationDidBecomeActive(__C.UIApplication) -> () 100.00% (3/3) MVP_ConnpassEventSearch.AppDelegate.applicationWillTerminate(__C.UIApplication) -> () 18

Slide 19

Slide 19 text

MVP_ConnpassEventSearch.AppDelegate.applicatio nWillEnterForeground(__C.UIApplication) -> () 0.00% (0/3) ίϝϯτ΋ؚΊͯ3ߦ ΧόϨοδ͸Xcode্ͷදࣔͱҰக͢Δ 19

Slide 20

Slide 20 text

9DPEFͰදࣔ͞Ε͍ͯΔ ΧόϨοδ͸ߦΛج४ʹܭଌͨ͠ -JOFDPWFSBHF 20

Slide 21

Slide 21 text

• Line coverageͱ͍͏͜ͱ͸Θ͔ͬͨ • ଞͷΧόϨοδ͸औΕͳ͍ͷ͔ʁ 21

Slide 22

Slide 22 text

9DPEFͷ ΧόϨοδܭଌͷ࢓૊Έ͔Β ݟ͍ͯ͘ 22

Slide 23

Slide 23 text

ͦ΋ͦ΋ΧόϨοδ Ͳ͏΍ͬͯऔͬͯΔͷʁ • ώϯτ͸υΩϡϝϯτʹ • https://developer.apple.com/library/archive/ documentation/DeveloperTools/Conceptual/ testing_with_xcode/chapters/07- code_coverage.html 23

Slide 24

Slide 24 text

$PEFDPWFSBHFJO9DPEFJTB UFTUJOHPQUJPOTVQQPSUFECZ --7. 24

Slide 25

Slide 25 text

9DPEF --7.ͷ ΧόϨοδܭଌͷ࢓૊Έ 25

Slide 26

Slide 26 text

--7.ͷΧόϨοδܭଌ • Source-based Code Coverage • SanitizerCoverage • gcov 26

Slide 27

Slide 27 text

--7.ͷΧόϨοδܭଌ • Source-based Code Coverage • SanitizerCoverage • gcov 27

Slide 28

Slide 28 text

4PVSDFCBTFE $PEF$PWFSBHF • AST΍ϓϦϓϩηοα৘ใΛ௚઀ૢ࡞͢Δ͜ ͱ͔ΒSource-basedͱݺ͹ΕΔ • ؆୯ʹ݁ՌΛࢹ֮Խ͢Δ͜ͱ·ͰՄೳ • ͓ͦΒ͘࠷΋ελϯμʔυͳ΋ͷ 28

Slide 29

Slide 29 text

࣮ࡍʹ4XJGUͷ 4PVSDFCBTFE$PEF$PWFSBHF ΛऔͬͯΈΔ 29

Slide 30

Slide 30 text

1. ΧόϨοδܭଌΛ༗ޮʹͯ͠ίϯύΠϧ 2. ੜ੒͞ΕͨϓϩάϥϜΛ࣮ߦ 3. ΧόϨοδϨϙʔτͷੜ੒ खॱ 30

Slide 31

Slide 31 text

main.swift let number = 10 if number % 2 == 0 { print("ۮ਺") } ୯७ͳϓϩάϥϜͰܭଌͯ͠ΈΔ 31

Slide 32

Slide 32 text

ΧόϨοδܭଌΛ ༗ޮʹͯ͠ίϯύΠϧ xcrun swiftc -profile-generate -profile-coverage-mapping main.swift ϓϩάϥϜ 32

Slide 33

Slide 33 text

ੜ੒͞Εͨ ϓϩάϥϜΛ࣮ߦ ϓϩάϥϜ EFGBVMUQSPGSBX ΧόϨοδ৘ใͷੜσʔλ 33

Slide 34

Slide 34 text

ΧόϨοδϨϙʔτΛੜ੒ xcrun llvm-profdata merge -o testprof.profdata default.profraw UFTUQSPGQSPGEBUB profrawϑΝΠϧ͸ͦͷ··ͩͱϨϙʔτΛग़ྗͰ͖Δ ܗࣜͰ͸ͳ͘ΠϯσοΫεΛ͚ͭΔඞཁ͕͋Δ testprof͸ࣗ෼Ͱ໋໊ 34

Slide 35

Slide 35 text

UFTUQSPGQSPGEBUB ࠷ऴతͳΧόϨοδ৘ใ͕ೖͬͨϑΝΠϧ
 ͜ͷঢ়ଶͩͱ·ͩਓ͕ಡΊΔঢ়ଶͰ͸ͳ͍ llvm-covΛ࢖ͬͯΧόϨοδ৘ใͷදࣔ΍JSONͰ ͷग़ྗΛߦ͏͜ͱ͕Ͱ͖Δ 35

Slide 36

Slide 36 text

xcrun llvm-cov show ./main -instr-profile=sample.profdata main.swift ߦʹରԠͨ͠ΧόϨοδ৘ใ 36

Slide 37

Slide 37 text

ccMFUOVNCFS*OU cc ccJGOVNCFS\ ccQSJOU ۮ਺ cc^ 37

Slide 38

Slide 38 text

• llvm-cov͸ҙ֎ͱߴػೳ • htmlͰͷग़ྗ΍ϨϙʔτܗࣜͰͷग़ྗʹ ΋ରԠ • ܭଌର৅ʹਖ਼نදݱΛ༻͍ͯಛఆͷϑΝ ΠϧΛؚΊͳ͍͜ͱ΋ • ࢖͍ํ࠷ޙʹ͚ͭ·ͨ͠ 38

Slide 39

Slide 39 text

xcrun llvm-cov export ./main -instr- profile=testprof.profdata main.swift JSONͷΧόϨοδ৘ใ
 ௕͗ͯ͢εϥΠυʹશͯ͸ࡌΓ·ͤΜͰͨ͠ 39

Slide 40

Slide 40 text

"totals": { "lines": { "count": 3, "covered": 3, "percent": 100 }, "functions": { "count": 2, "covered": 2, "percent": 100 }, "instantiations": { "count": 2, "covered": 2, "percent": 100 }, "regions": { "count": 4, "covered": 4, "notcovered": 0, "percent": 100 } } llvm-covͰग़ྗͨ͠
 JSONͷҰ෦ • lines • functions • Instantiations • regions 40

Slide 41

Slide 41 text

• ࣮͸Source-based Code Coverage͸4छྨͷ ΧόϨοδΛܭଌ͢Δ͜ͱ͕Ͱ͖Δ 41

Slide 42

Slide 42 text

-JOFDPWFSBHF • ߦͰݟͨΧόϨοδ(ίϝϯτؚΉ) • σϑΥϧτͷઃఆ͸͜Ε • ࣮ࡍʹLine਺Ͱ෇͖߹ΘͤͯΈΔͱ׬શʹҰ க͢ΔͨΊXcodeͰද͍ࣔͯ͠Δͷ͸͜Ε 42

Slide 43

Slide 43 text

'VODUJPODPWFSBHF *OTUBOUJBUJPODPWFSBHF • ؔ਺ͷݺͼग़͠ճ਺ • ΠϯελϯεԽͷճ਺ 43

Slide 44

Slide 44 text

3FHJPODPWFSBHF • ίʔυͷྖҬͰଌΔΧόϨοδ • ࡾ߲ԋࢉࢠͳͲ΋1ߦͰ͸ͳ͘ෳ਺ͱΈͳ͢ • Source-based Code CoverageͰ͸Ұ൪ཻ౓͕ࡉ ͔͍ 44

Slide 45

Slide 45 text

let result = 10 % 2 == 0 ? true : false 1ߦ͚ͩͷ؆୯ͳίʔυͷΧόϨοδΛݟͯΈΔ 45

Slide 46

Slide 46 text

Line coverage Region coverage 46

Slide 47

Slide 47 text

ɾಉ͡Line coverage͕͋ΔͷͰXcodeͰ͸ Source-based Code CoverageΛར༻ͯͦ͠͏ ɾXcode্දࣔ͞Ε͍ͯΔΧόϨοδ͸ Line coverage͕ͩSource-based Code Coverage ͱ͍͏͜ͱͳΒܭଌࣗମ͸4छྨߦΘΕ͍ͯ Δ͸ͣ 47

Slide 48

Slide 48 text

ͱݴ͏͜ͱ͸Region coverage΋औಘͰ͖Δ ͷͰ͸… 48

Slide 49

Slide 49 text

BuildϑΥϧμΛআ͘ͱ… 49

Slide 50

Slide 50 text

• Coverage.profdataϑΝΠϧ͕ଘࡏ͢Δ • *.profdataܗࣜͳͷͰllvm-covΛ࢖ͬͯݟΔ ͜ͱ͕Ͱ͖Δ 50

Slide 51

Slide 51 text

xcrun llvm-cov report ../../Products/Debug-iphonesimulator/ {ProductName}.app/{ProductName} -instr-profile=Coverage.profdata 51

Slide 52

Slide 52 text

• Line coverageΑΓࡉ͔͍Region coverageΛ ؆୯ʹΈΔ͜ͱ͕Ͱ͖Δ • ͔͠͠ຊ౰ʹগ͚͔ͩ͠͠ࡉ͔͘ͳ͍͔ ΋͠Εͳ͍ 52

Slide 53

Slide 53 text

• && ΍ || ͱ͍ͬͨ৚݅ʹ͍ͭͯ͸
 Line coverageͰݕग़Ͱ͖Δ 53

Slide 54

Slide 54 text

struct Foo { func bar() { let number = 10 if number % 2 == 0 || number == 10 { print("ۮ਺Ͱ10") } } } 54

Slide 55

Slide 55 text

struct Foo { func bar() { let number = 10 if number % 2 == 0 || number == 10 { print("ۮ਺Ͱ10") } } } struct Coverage { func hhoge() { let number = 10 if number % 2 == 0 || number == 10 { print("ۮ਺Ͱ10") } } } 55

Slide 56

Slide 56 text

ϝιου͚ͩͰΈΔͱ100%͕ͩ
 implicit closureͱͯ͠දࣔ͞Ε͓ͯΓɺ
 ϑΝΠϧ୯ҐͰ͸໢ཏͰ͖͍ͯͳ͍͜ͱ͕ Θ͔Δ 56

Slide 57

Slide 57 text

public static func || (lhs: Bool, rhs: @autoclosure () throws -> Bool) rethrows -> Bool { return lhs ? true : try rhs() } Swiftͷ࣮૷ͱͯ͠&&΍||ͷӈล͸closureͱͯ͠ ॲཧ͞ΕΔ 57

Slide 58

Slide 58 text

• closure͕ผͰܭଌ͞Ε͍ͯΔ • ͦͷཧ༝Λ஌ΔͨΊʹSource-based Code Coverage͕ͲͷΑ͏ʹऔಘ͞Ε͍ͯΔ͔ Λ؆୯ʹݟͯΈΔ 58

Slide 59

Slide 59 text

• Source-based Code Coverage͸LLVM͕ఏڙ ͢ΔCode Coverage Mapping Formatͱ͍͏ ΋ͷΛར༻ͯ͠ܭଌ͍ͯ͠Δ • ΦϓγϣϯΛ͚ͭͯίϯύΠϧͨ͠ࡍʹ Ϛοϐϯά༻ͷσʔλ͕ຒΊࠐ·ΕΔ 59

Slide 60

Slide 60 text

• ͜ͷϚοϐϯάϑΥʔϚοτ͸LLVMΛ όοΫΤϯυͱͯ࣋ͭ͠ϑϩϯτΤϯυ ͷϢχόʔαϧϑΥʔϚοτΛ໨ࢦͯ͠ ͍Δ • LLVMΛόοΫΤϯυʹ΋ͭશͯͷϑϩϯ τΤϯυͰڞ௨ͯ͠औಘͰ͖ΔΧόϨο δ 60

Slide 61

Slide 61 text

• LLVMͷυΩϡϝϯτʹCoverage Mapping Formatʹ͍ͭͯઆ໌ͨ͠΋ͷ͕ଘࡏ͢Δ
 https://llvm.org/docs/ CoverageMappingFormat.html • ͦΕʹΑΔͱϑϩϯτΤϯυ͕LLVM IRΛ ੜ੒͢ΔࡍʹຒΊࠐ·ΕΔ 61

Slide 62

Slide 62 text

• ͪͳΈʹSwiftcͰ͸IRGen.cppͷ
 performIRGeneration()
 
 GenDecl.cppͷ
 IRGenerator::emitGlobalTopLevel()
 
 GenCoverageͷ
 IRGenModule::emitCoverageMapping() • llvm/ProfileData/Coverage/CoverageMappingWriter.h 62

Slide 63

Slide 63 text

ͱ͍͏Θ͚Ͱ--7.*3Λ ݟ͍ͯ͘ 63

Slide 64

Slide 64 text

xcrun swiftc -emit-ir -profile-generate -profile-coverage-mapping Coverage/main.swift • -emit-irΛΦϓγϣϯͱͯ͠౉͢͜ͱͰ LLVM IRΛग़ྗ͢Δ͜ͱ͕Ͱ͖Δ • ΧόϨοδΛ༗ޮʹͯ͠LLVM IRΛग़ྗ 64

Slide 65

Slide 65 text

ܭଌΦϑ ܭଌΦϯ ࠩ෼͕ͨ͘͞Μ͋Δͷ͕Θ͔Δ 65

Slide 66

Slide 66 text

@"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyF" = linkonce hidden global [2 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 @"__profd_Coverage/Coverage.swift:$S4Hoge3FooV3baryyF" = linkonce hidden global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 1740746221156547191, i64 0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyF", i32 0, i32 0), i8* bitcast (void ()* @"$S4Hoge3FooV3baryyF" to i8*), i8* null, i32 2, [2 x i16] zeroinitializer }, section "__DATA,__llvm_prf_data,regular,live_support", align 8 @"__profc_Coverage/Coverage.swift:__ntd_Foo_line:1:1" = linkonce hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 @"__profd_Coverage/Coverage.swift:__ntd_Foo_line:1:1" = linkonce hidden global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 -7581103708217037269, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/Coverage.swift:__ntd_Foo_line:1:1", i32 0, i32 0), i8* bitcast (void ()* @"$S4Hoge3FooVACycfC" to i8*), i8* null, i32 1, [2 x i16] zeroinitializer }, section "__DATA,__llvm_prf_data,regular,live_support", align 8 @"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_" = linkonce hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 @"__profd_Coverage/Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_" = linkonce hidden global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 3556985279047318519, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i32 0, i32 0), i8* bitcast (void ()* @"$S4Hoge3FooV3baryyF" to i8*), i8* null, i32 1, [2 x i16] zeroinitializer }, section "__DATA,__llvm_prf_data,regular,live_support", align 8 ϔομʔ෦෼ͷҰ෦ʹ஫໨ 66

Slide 67

Slide 67 text

@"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyF" @"__profc_Coverage/Coverage.swift:__ntd_Foo_line:1:1" @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyFSbyKXKfu_" ͜ͷ3ͭͷάϩʔόϧม਺ʹ஫໨͢Δ ͜ͷ··ͩͱΘ͔Βͳ͍ͷͰσϚϯάϧͯ͠ΈΔ 67

Slide 68

Slide 68 text

@"__profc_Coverage/Coverage.swift:Hoge.Foo.bar() -> () @"__profc_Coverage/Coverage.swift:__ntd_Foo_line:1:1" @"__profc_Coverage/Coverage.swift:implicit closure #1 : @autoclosure () throws -> Swift.Bool in Hoge.Foo.bar() -> () @"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyF" @"__profc_Coverage/Coverage.swift:__ntd_Foo_line:1:1" @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyFSbyKXKfu_" 68

Slide 69

Slide 69 text

• ͜ΕΒͷάϩʔόϧม਺͸Χ΢ϯλͱ Ϛοϐϯά৘ใΛอଘ͍ͯ͠Δ΋ͷ 69

Slide 70

Slide 70 text

define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 70

Slide 71

Slide 71 text

define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 71

Slide 72

Slide 72 text

define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 ઌ΄ͲσϚϯάϧͨ͠ΒҎԼʹͳͬͨ΋ͷ @"__profc_Coverage/Coverage.swift:Hoge.Foo.bar() -> () 72

Slide 73

Slide 73 text

ͲΜͳॲཧΛ͍ͯ͠Δ͔ งғؾͰ ݟ͍ͯ͘ 73

Slide 74

Slide 74 text

define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 ͔͜͜ΒFoo.bar()ͷελʔτ 74

Slide 75

Slide 75 text

define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 άϩʔόϧม਺(഑ྻ)͔ΒཁૉΛऔΓग़ͯ͠ɺ ϨδελpgocountೖΕ͍ͯΔ 75

Slide 76

Slide 76 text

define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 pgocountͱ1ΛՃࢉͯ͠Ϩδελ0ʹೖΕ͍ͯΔ 76

Slide 77

Slide 77 text

define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 define hidden swiftcc void @"$S4Hoge3FooV3baryyF"() #0 { entry: %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyF", i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyF", i64 0, i64 0) br label %1 ܭࢉ݁ՌͷϨδελ0Λάϩʔόϧม਺ʹอଘ 77

Slide 78

Slide 78 text

• ͜ͷॲཧʹΑͬͯͲͷؔ਺ͷͲͷϒϩο ΫΛ௨ա͔ͨ͠ͷճ਺Χ΢ϯτ͕ߦΘΕ ͍ͯΔ 78

Slide 79

Slide 79 text

; :3: ; preds = %2 br i1 true, label %4, label %7 ͨͩͷ෼ذ 79

Slide 80

Slide 80 text

; :7: ; preds = %3 %pgocount1 = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) %8 = add i64 %pgocount1, 1 store i64 %8, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) br label %9 80

Slide 81

Slide 81 text

; :7: ; preds = %3 %pgocount1 = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) %8 = add i64 %pgocount1, 1 store i64 %8, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) br label %9 ; :7: ; preds = %3 %pgocount1 = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) %8 = add i64 %pgocount1, 1 store i64 %8, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) br label %9 81

Slide 82

Slide 82 text

; :7: ; preds = %3 %pgocount1 = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) %8 = add i64 %pgocount1, 1 store i64 %8, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) br label %9 ; :7: ; preds = %3 %pgocount1 = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) %8 = add i64 %pgocount1, 1 store i64 %8, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) br label %9 ઌ΄ͲσϚϯάϧͨ͠ΒҎԼʹͳͬͨ΋ͷ @"__profc_Coverage/Coverage.swift:implicit closure #1 : @autoclosure () throws -> Swift.Bool in Hoge.Foo.bar() -> () 82

Slide 83

Slide 83 text

; :7: ; preds = %3 %pgocount1 = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) %8 = add i64 %pgocount1, 1 store i64 %8, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) br label %9 ; :7: ; preds = %3 %pgocount1 = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/Coverage.swift: $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) %8 = add i64 %pgocount1, 1 store i64 %8, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @"__profc_Coverage/ Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0) br label %9 ͦͷଞͷ෦෼ʹ͍ͭͯ͸ઌ΄Ͳͱಉ͡Ճࢉॲཧ 83

Slide 84

Slide 84 text

• ͦ΋ͦ΋Χ΢ϯτ͢Δࡍʹผͷؔ਺ͱ͠ ͯΧ΢ϯτ͞Ε͍ͯͨ • ͳͷͰϑΝΠϧ୯ҐͰ͸ݟ͔ͭΔ͕ɺϝ ιου୯ҐͰ͸ݟ͔ͭΒͳ͔ͬͨ 84

Slide 85

Slide 85 text

• ͱ͍͏͜ͱ͔ΒLine coverageͰ΋&&΍||ͷΧό ϨοδΛݟΔ͜ͱ͸Ͱ͖Δ • ࠓͷॴࢲ͕ؾ͕෇͍ͨRegion coverageͰ͔͠ݟͭ ͚ΒΕͳ͍΋ͷ͸3߲ԋࢉࢠͱ1ߦʹ·ͱΊͯॻ ͍ͨifจ͘Β͍… • ͦΕͰ΋Line coverageΑΓ͸ࡉ͔͘औΕΔͷͰ Region coverageΛ࢖ͬͯܭଌͯ͠΋͍͍͔΋͠Ε ͳ͍ 85

Slide 86

Slide 86 text

ϒϥϯνΧόϨοδ Ͳ͍ͬͨ͜ • XcodeͰར༻͍ͯ͠ΔΧόϨοδܭଌ͕ Source-based Code CoverageͷͨΊɺXcode্ ͷϏϧυ͔ΒϒϥϯνΧόϨοδΛऔΔ͜ ͱ͸Ͱ͖ͳ͍ 86

Slide 87

Slide 87 text

--7.ͷΧόϨοδܭଌ • Source-based Code Coverage • SanitizerCoverage • gcov 87

Slide 88

Slide 88 text

--7.ͷΧόϨοδܭଌ • Source-based Code Coverage
 → Θ͔ͬͨ • SanitizerCoverage • gcov 
 → swiftcʹ࣮૷͞Ε͍ͯͳͦ͞͏ 88

Slide 89

Slide 89 text

4BOJUJ[FS$PWFSBHF • LLVMͱswiftcͰऔΕΔ΋͏ҰͭͷΧόϨοδ • Τοδͱݺ͹ΕΔΧόϨοδΛऔಘͰ͖Δ 89

Slide 90

Slide 90 text

Τοδͱ͸ if 1 == 1 { print("hogehoge") } 90

Slide 91

Slide 91 text

A B C ௨ৗ͸3ͭͷϒϩοΫ 91

Slide 92

Slide 92 text

A B C D edgeΛ༗ޮʹ͢Δͱ Dͱ͍͏μϛʔϒϩοΫ͕ੜ੒͞ΕΔ 92

Slide 93

Slide 93 text

͔ͤͬ͘ͳͷͰ --7.*3΋ݟΑ͏ 93

Slide 94

Slide 94 text

; :2: ; preds = %1 br i1 true, label %3, label %._crit_edge ._crit_edge: ; preds = %2 call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([5 x i32]* @__sancov_gen_ to i64), i64 4) to i32*)) call void asm sideeffect "", ""() br label %46 ; :3: ; preds = %2 Ұ෦ൈਮ 94

Slide 95

Slide 95 text

; :2: ; preds = %1 br i1 true, label %3, label %._crit_edge ._crit_edge: ; preds = %2 call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([5 x i32]* @__sancov_gen_ to i64), i64 4) to i32*)) call void asm sideeffect "", ""() br label %46 ; :3: ; preds = %2 ; :2: ; preds = %1 br i1 true, label %3, label %._crit_edge ._crit_edge: ; preds = %2 call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([5 x i32]* @__sancov_gen_ to i64), i64 4) to i32*)) call void asm sideeffect "", ""() br label %46 ; :3: ; preds = %2 ෼ذઌʹcrit_edgeͱ͍͏΋ͷ͕ଘࡏ͢Δ 95

Slide 96

Slide 96 text

; :2: ; preds = %1 br i1 true, label %3, label %._crit_edge ._crit_edge: ; preds = %2 call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([5 x i32]* @__sancov_gen_ to i64), i64 4) to i32*)) call void asm sideeffect "", ""() br label %46 ; :3: ; preds = %2 ; :2: ; preds = %1 br i1 true, label %3, label %._crit_edge ._crit_edge: ; preds = %2 call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([5 x i32]* @__sancov_gen_ to i64), i64 4) to i32*)) call void asm sideeffect "", ""() br label %46 ; :3: ; preds = %2 ຒΊࠐ·Εͨؔ਺ΛݺΜͰ͍Δ 96

Slide 97

Slide 97 text

• μϛʔϒϩοΫͱ͸LLVM IRͰຊདྷԿ΋ͳ ͍෼ذઌʹൃੜ͢ΔϒϩοΫ 97

Slide 98

Slide 98 text

ΧόϨοδΛݟͯΈΔ 98

Slide 99

Slide 99 text

• SanitizerCoverage͸ग़ྗ͕໘౗ • sancovͱ͍͏toolΛ࢖͏ඞཁ͕͋Δ • LLVMΛผ్DL͠ͳ͍ͱೖ͍ͬͯͳ͍ 99

Slide 100

Slide 100 text

xcrun swiftc -sanitize=address -sanitize-coverage=edge Coverage/main.swift ASAN_OPTIONS=coverage=1 ./main;wc -c *.sancov main.****.sancov 100

Slide 101

Slide 101 text

sancov -print-coverage-stats main.52871.sancov ./main all-edges: 5 cov-edges: 5 all-functions: 4 cov-functions: 4 ૯edge਺ͱΧόʔͨ͠edge਺͕ݟΕΔ 101

Slide 102

Slide 102 text

sancov -symbolize main.52871.sancov ./main > main.symcov HTMLͰݟΔͨΊʹ͸γϯϘϥΠζͯ͠ ͋͛Δඞཁ͕͋Δ 102

Slide 103

Slide 103 text

{ "covered-points" : ["100000b2d", "100000c22", "100000c9f", "100000ccf", "100000d1c"], "binary-hash" : "5CCB31D0F47A427284B9EE58B2C89557D382CD0B", "point-symbol-info" : { "" : { "$ss5print_9separator10terminatoryypd_S2StFfA0_" : { "100000c9f" : "0:0" }, "$ss5print_9separator10terminatoryypd_S2StFfA1_" : { "100000ccf" : "0:0" }, "asan.module_dtor" : { "100000d1c" : "0:0" }, "main" : { "100000b2d" : "0:0", "100000c22" : "0:0" } } } } 103

Slide 104

Slide 104 text

• llvm/tools/sancov/ ഑Լʹ͋Δ
 coverage-report-server.pyͰ
 HTTPαʔόΛىಈ͢Δ • coverage-report-server.py΋brewͰΠϯε τʔϧͨ͠LLVMʹ͸ແ͔ͬͨͷͰผ్DL 104

Slide 105

Slide 105 text

python3 coverage-report-server.py --symcov ~/workspace/Coverage/ main2.symcov --srcpath ~/workspace/Coverage/ ຊདྷ͸ϑΝΠϧ໊͕දࣔ͞ΕΔ͸͕ͣͩɺinvalidʹͳͬͯ͠· ͍ݟΕͳ͔ͬͨ(sancov͕Linux͔͠αϙʔτ͍ͯ͠ͳ͍ͷͰͦΕ ͕ݪҼ͔΋͠Εͳ͍) 105

Slide 106

Slide 106 text

• edgeΧόϨοδΛҰԠݟΕΔ • ͔͠͠edgeΧόϨοδ͸෼ذͷ਺Λج४ ʹݟ͍ͯΔͱ͍͏Θ͚Ͱ͸ͳ͍ͷͰϒϥ ϯνΧόϨοδͱ͸গ͠ҟͳΔ 106

Slide 107

Slide 107 text

ϒϥϯνΧόϨοδ͸ औΕΔͷ͔ 107

Slide 108

Slide 108 text

औΕ·ͤΜʂʂ 108

Slide 109

Slide 109 text

• edgeͱϒϥϯν͸ҟͳΔ΋ͷͳͷͰݫີ ʹϒϥϯνΧόϨοδΛऔΔ࢓૊Έ͸ແ ͔ͬͨ • ͦ΋ͦ΋ݱঢ়ͷ΋εςʔτϝϯτΧό ϨοδͰ͸ແ͔ͬͨ(Line coverage) 109

Slide 110

Slide 110 text

ँࡑ 110

Slide 111

Slide 111 text

ϓϩϙʔβϧͷҰ෦ • ҰํͰίʔυΧόϨοδʹ͸͍͔ͭ͘छྨ͕ ͋ΓɺXcodeͰ͸ͦͷҰͭͰ͋Δεςʔτϝ ϯτΧόϨοδ͔͠ܭଌͰ͖ͳ͍ͱ͍͏͜ͱ Λ͝ଘ஌Ͱ͠ΐ͏͔ɻ 111

Slide 112

Slide 112 text

ϓϩϙʔβϧͷҰ෦ • ҰํͰίʔυΧόϨοδʹ͸͍͔ͭ͘छྨ͕ ͋ΓɺXcodeͰ͸ͦͷҰͭͰ͋Δεςʔτϝ ϯτΧόϨοδ͔͠ܭଌͰ͖ͳ͍ͱ͍͏͜ͱ Λ͝ଘ஌Ͱ͠ΐ͏͔ɻ 112 XcodeͰݟΕΔͷ͸ Line coverageͰ͢ʂ

Slide 113

Slide 113 text

• ͨͩ͠Region coverageͱ͍͏Line coverage ΑΓࡉ͔͍΋ͷ͕؆୯ʹΈΔ͜ͱ͕Ͱ͖ Δ • %ͰͳΒ͹ҰԠedge coverage΋ݟΔ͜ͱ͸ Ͱ͖Δ 113

Slide 114

Slide 114 text

ͦΜͳίʔυΧόϨοδΛ Ͳ͏ͯ͠ͱΓ͍͔ͨ 114

Slide 115

Slide 115 text

• ΧόϨοδ͸Ͳ͕͜ॻ͚͍ͯͳ͍͔Λݟ Δ͜ͱ͕Ͱ͖Δπʔϧ • Ͳ͕͜ॻ͚͍ͯͳ͍͔෼͔Ε͹௥Ճ͢Δ ͜ͱ΋Ͱ͖Δ • (ͨͩ͠ॻ͚͍ͯͳ͍ͱ͜ΖΛશͯॻ͘΂ ͖͔Ͳ͏͔͸ผͷ࿩) 115

Slide 116

Slide 116 text

• ࡉ͔͘νΣοΫͯ͘͠ΕΔ΄Ͳؾ͕෇͔ ͳ͔ͬͨͱ͜Ζʹؾ͕͚ͭΔ • ͋͘·Ͱ΋ิॿπʔϧͱͯ͠࢖͏ 116

Slide 117

Slide 117 text

·ͱΊ • XcodeͰ͸Line coverage͕දࣔ͞Ε͍ͯΔ • গ͠ࡉ͔͍Region coverage΋औΕΔ • ϒϥϯνΧόϨοδ͸औΕͳ͍͕ɺedgeͰͷˋͳ Β(ҰԠ)ݟΕΔ • ΧόϨοδΛ্खʹ׆༻ͯ͠ྑ͍ςετϥΠϑΛ 117

Slide 118

Slide 118 text

ࢀߟࢿྉ • Code Coverage - Apple Developer
 https://developer.apple.com/library/archive/documentation/ DeveloperTools/Conceptual/testing_with_xcode/chapters/07- code_coverage.html • Source-based Code Coverage - Clang 10 documentation
 https://clang.llvm.org/docs/ SourceBasedCodeCoverage.html#exporting-coverage-data • LLVM Code Coverage Mapping Format - LLVM 10 documentation
 https://llvm.org/docs/CoverageMappingFormat.html 118

Slide 119

Slide 119 text

• llvm-cov - emit coverage information - LLVM 10 documentation
 https://llvm.org/docs/CommandGuide/llvm-cov.html • SwiftίϯύΠϥͷΞʔΩςΫνϟ
 https://qiita.com/rintaro/items/3ad640e3938207218c20 • https://github.com/apple/swift • SwiftίϯύΠϥͷManglingͷษڧํ๏
 https://qiita.com/omochimetaru/items/ 60b0d50146e0abbc9b7b 119

Slide 120

Slide 120 text

• LLVM Language Reference Manual - LLVM 10 documentation
 https://llvm.org/docs/LangRef.html • AddressSanitizerFlags
 https://github.com/google/sanitizers/wiki/ AddressSanitizerFlags 120

Slide 121

Slide 121 text

͓·͚ 121

Slide 122

Slide 122 text

YDDPWͷ࢖͍ํ 122

Slide 123

Slide 123 text

xcrun xccov view *.xccovreport ϑΝΠϧຖʹԿˋͱ͍ͬͨΞϓϦέʔ γϣϯશମͷΧόϨοδͷ֓ཁΛݟΔ͜ ͱ͕Ͱ͖Δ 123

Slide 124

Slide 124 text

xcrun xccov view *.xccovarchive/ --file *.swift ಛఆͷϑΝΠϧͷԿߦ໨͕Կճ࣮ߦ͞Ε͔ͨ ͷৄࡉΛݟΔ͜ͱ͕Ͱ͖Δ ·ͨϑΝΠϧΛࢦఆ͢Δࡍʹ͸
 xcrun xccov view —file-list *.xccovarchive/
 Ͱ֤ϑΝΠϧͷύεΛ֬ೝͰ͖Δ 124

Slide 125

Slide 125 text

MMWNDPWͷ࢖͍ํ 125

Slide 126

Slide 126 text

• https://llvm.org/docs/CommandGuide/llvm- cov.html • جຊ͜͜ʹॻ͍ͯ͋Γ·͢ 126

Slide 127

Slide 127 text

• 3छྨͷग़ྗํ๏ • show / report / export • show - ͲͷҐஔ͕௨ա͍ͯ͠ͳ͍͔͕ιʔε ίʔυͱରԠ͚ͮΒΕͯݟΕΔ • report - ֤ϑΝΠϧͷLine / Function / Region coverageͷsummary͕ҰཡͰݟΕΔ • export - JSON΍lcovܗࣜͰग़ྗ͕Ͱ͖Δ 127

Slide 128

Slide 128 text

• xcrun llvm-cov -show -format html -show- regions -instr-profile=**.profdata
 ͰHTMLͰιʔείʔυͱରԠͨ͠Region coverageΛݟΔ͜ͱ͕Ͱ͖Δ 128

Slide 129

Slide 129 text

129

Slide 130

Slide 130 text

• xcrun llvm-cov report -ignore-filename- regex=[pattern] -instr-profile=*.profdata • ਖ਼نදݱͰܭଌ͠ͳ͍ϑΝΠϧΛࢦఆͰ ͖Δ • -ignore-filename-regex=.*ViewController.swift
 ͰViewControllerΛআ֎͢ΔͳΜͯ͜ͱ΋ 130

Slide 131

Slide 131 text

͋Γ͕ͱ͏͍͟͝·ͨ͠ 131 Twitter: @kariad_uu