Dem Fehler auf der Spur - Mobile Testing Days 2015

Dem Fehler auf der Spur - Mobile Testing Days 2015

Eine Expedition in die (Objective-C) Debugging Toolchain von iOS.
Talk gehalten auf den Mobile Testing Days in Berlin am 28. Mai 2015.

896e816a54b484b5233ed5f9ea5278a5?s=128

Florian

May 28, 2015
Tweet

Transcript

  1. Dem Fehler auf der Spur

  2. Florian Bürger @florianbuerger

  3. None
  4. keslcod Better software for happier humans

  5. — Denkweise — Debugging — Profiling

  6. Denkweise

  7. Incident Identifier: 63569671-4940-4162-B76F-D3AD44A607F0 CrashReporter Key: 09B60E97-4A43-4092-8C6A-51B4406BE34A Hardware Model: iPhone6,2 Process:

    App [268] Path: /private/var/mobile/Containers/Bundle/Appl Identifier: de.inhofer.app.beta Version: 101 Code Type: ARM-64 Parent Process: launchd [1] Date/Time: 2014-09-23T15:03:07Z OS Version: iPhone OS 8.0 (12A365) Report Version: 104 Exception Type: SIGABRT Exception Codes: #0 at 0x197c73270 Crashed Thread: 0 Application Specific Information: *** Terminating app due to uncaught exception 'NSInvalidArg …
  8. Panik Ruhig atmen Title Text

  9. keine Panik!

  10. ruhig atmen!

  11. Mentales Modell

  12. Ziel?

  13. 100% Verständnis

  14. 100% Verständnis Fremder Code!

  15. “Debugging is twice as hard as writing the code in

    the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” —Brian Kernighan
  16. seid klug, schreibt stupiden Code

  17. - (BOOL)isLogoHiddenAtIndexPath:(id)p { return ![self URLAtIndexPath:p]; }

  18. - (BOOL)isLogoHiddenAtIndexPath:(id)p { NSURL *logoURL = [self URLAtPath:p]; BOOL hidden

    = (logoURL != nil); return hidden; }
  19. - (BOOL)isLogoHiddenAtIndexPath:(id)p { NSURL *logoURL = [self URLAtPath:p]; BOOL hidden

    = (logoURL != nil); return hidden; }
  20. - (id)calculateWithThing:(Thing *)t { return [self doCalculation: [self calcForThing:t] withOtherThing:

    [self otherThing]; }
  21. - (id)calculateWithThing:(Thing *)t { return [self doCalculation: [self calcForThing:t] withOtherThing:

    [self otherThing]; }
  22. - (id)calculateWithThing:(Thing *)t { return [self doCalculation: [self calcForThing:t] withOtherThing:

    [self otherThing]; }
  23. - (id)calculateWithThing:(Thing *)t { return [self doCalculation: [self calcForThing:t] withOtherThing:

    [self otherThing]; }
  24. Lokale Variablen

  25. - (id)calculateWithThing:(Thing *)t { Calc* calc = [self calcForThing:t]; Thing

    *other = [self otherThing]; Result *result = [self doCalculation:calc withOtherThing:other]; return result; }
  26. - (id)calculateWithThing:(Thing *)t { Calc* calc = [self calcForThing:t]; Thing

    *other = [self otherThing]; Result *result = [self doCalculation:calc withOtherThing:other]; return result; }
  27. - (id)calculateWithThing:(Thing *)t { Calc* calc = [self calcForThing:t]; Thing

    *other = [self otherThing]; Result *result = [self doCalculation:calc withOtherThing:other]; return result; }
  28. - (id)calculateWithThing:(Thing *)t { Calc* calc = [self calcForThing:t]; Thing

    *other = [self otherThing]; Result *result = [self doCalculation:calc withOtherThing:other]; return result; }
  29. Guidelines einhalten

  30. travisjeffery/ ClangFormat-Xcode haaakon/Apple- clang-format

  31. Und was ist mit Swift?

  32. SwiftLint

  33. realm/SwiftLint

  34. None
  35. — Class implements isEqual: but not hash — Fixed-format NSDateFormatter

    not using invariant (POSIX) locale
  36. Denkweise Fehler passieren

  37. Denkweise 100% Verständnis

  38. Denkweise Simpler Code

  39. Debugging

  40. None
  41. Debug Navigator

  42. None
  43. Variables View

  44. None
  45. Console

  46. None
  47. Alle Breakpoints de-/aktivieren

  48. Pause/Continue

  49. Step over

  50. Step into

  51. Step out

  52. View hierarchy

  53. Location

  54. Bedingte Breakpoints

  55. None
  56. Breakpoint Commands

  57. None
  58. None
  59. None
  60. None
  61. None
  62. Demo

  63. Breakpoints teilen

  64. im Projekt Versions kontrolle

  65. im Projekt Kollegen

  66. im User Account für jedes Projekt!

  67. None
  68. None
  69. +++ b/Test.xcodeproj/xcshareddata/xcdebugger/ Breakpoints_v2.xcbkptlist @@ -2,4 +2,22 @@ <Bucket type =

    "4" version = "2.0"> + <Breakpoints> + <BreakpointProxy + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> + <BreakpointContent + shouldBeEnabled = "Yes" + ignoreCount = "0" + continueAfterRunningActions = "No" + filePath = "Test/ViewController.swift" + timestampString = "454418607.219209" + startingColumnNumber = "9223372036854775807" + endingColumnNumber = "9223372036854775807" + startingLineNumber = "15" + endingLineNumber = "15" + landmarkName = "viewDidLoad()"
  70. +++ b/Test.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist @@ -2,4 +2,22 @@ <Bucket type = "4"

    version = "2.0"> + <Breakpoints> + <BreakpointProxy + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> + <BreakpointContent + <Actions> + <BreakpointActionProxy> + ActionExtensionID = “Xcode.BreakpointAction.Log"> + <ActionContent + message = "Hello Mobile Testing Days" + conveyanceType = "0"> + </ActionContent> + </BreakpointActionProxy> + </Actions>
  71. LLDB

  72. NSString *foo = @“foo” (lldb) po foo

  73. NSString *foo = @“foo” (lldb) po foo foo

  74. NSString *foo = @“foo” (lldb) expr [foo stringByAppendString:@“bar”]

  75. NSString *foo = @“foo” (lldb) expr [foo stringByAppendString:@“bar”] (id) $1

    = 0x7b242670
  76. NSString *foo = @“foo” (lldb) expr [foo stringByAppendString:@“bar”] (id) $1

    = 0x7b242670 (lldb) po 0x7b242670
  77. NSString *foo = @“foo” (lldb) expr [foo stringByAppendString:@“bar”] (id) $1

    = 0x7b242670 (lldb) po 0x7b242670 foobar
  78. (lldb) po self.view.frame

  79. (lldb) po self.view.frame error: property 'frame' not found on object

    of type 'UIView *' error: 1 errors parsing expression
  80. (lldb) po self.view.window nil (lldb) po self.view.frame error: property 'frame'

    not found on object of type 'UIView *' error: 1 errors parsing expression (lldb) expr @import UIKit
  81. (lldb) po self.view.frame (origin = (x = 0, y =

    0), size = (width = 320, height = 568)) (origin = (x = 0, y = 0), size = (width = 320, height = 568))
  82. Quick Look

  83. None
  84. None
  85. .lldbinit

  86. chisel

  87. presponder Print the responder chain starting from the given object.

  88. mask/unmask Overlay a view or layer with a transparent rectangle

    to visualize where it is.
  89. Logging

  90. NSLog()?

  91. NSLog()

  92. Logging mit Breakpoints

  93. None
  94. Cocoa Lumber- jack

  95. — Schnell(er) — Flexibel — Dynamisch

  96. — Schnell(er) — Flexibel — Dynamisch

  97. — Schnell(er) — Flexibel — Dynamisch

  98. Schemes

  99. — Launch Arguments — Location — Application Data — Background

    Fetch — Localization
  100. Demo

  101. None
  102. System Argumente

  103. -com.apple.CoreData. ConcurrencyDebug 1

  104. Eigene Argumente

  105. -> NSUserDefaults

  106. -recording-disabled 1 -use-local-server 0 [NSUserDefaults standardUserDefaults] boolForKey:@"recording-enabled"];

  107. -recording-disabled 1 -use-local-server 0 [NSUserDefaults standardUserDefaults] boolForKey:@"recording-enabled"];

  108. — Launch Arguments — Location — Application Data — Background

    Fetch — Localization
  109. <?xml version="1.0" encoding="UTF-8" standalone="no"?> <gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/ XMLSchema-instance" xsi:schemaLocation="http:// www.topografix.com/GPX/1/1

    http:// www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" <wpt lat="52.509678" lon="13.399576"> <time>2015-05-27T19:29:40Z</time> </wpt> </gpx>
  110. None
  111. — Launch Arguments — Location — Application Data — Background

    Fetch — Localization
  112. None
  113. iOS 8 rdar://20622011

  114. Quick Radar

  115. — Launch Arguments — Location — Application Data — Background

    Fetch — Localization
  116. — Launch Arguments — Location — Application Data — Background

    Fetch — Localization
  117. None
  118. View Debugging

  119. None
  120. — Constraints — Bounds — Hierarchie — Read-Only…

  121. — Constraints — Bounds — Hierarchie — Read-Only…

  122. — Constraints — Bounds — Hierarchie — Read-Only…

  123. — Constraints — Bounds — Hierarchie — Read-Only…

  124. Reveal

  125. Demo

  126. None
  127. None
  128. Spark Inspector

  129. None
  130. Wo ist meine App?

  131. Sim Pholders2

  132. Sim Pholders2

  133. Debugging Logging ohne NSLog()

  134. Debugging Breapoints +Commands

  135. Debugging Launch Arguments

  136. Debugging Visuelles Debuggen

  137. Debugging Fehler verstehen

  138. Profiling

  139. Vermuten

  140. Vermuten Wissen

  141. None
  142. None
  143. Was dauert so lange?

  144. None
  145. None
  146. 60 FPS

  147. 60 FPS

  148. 60 FPS

  149. Demo

  150. Profiling Wissen! Vermuten

  151. Profiling Instruments

  152. Profiling 60 FPS

  153. Links - lldb-command-examples - LLDB-QuickLook - chisel - CocoaLumberjack -

    NSLogger - NSLogger-CocoaLumberjack-connector - Reveal - Spark Inspector
  154. Links - Symbolic breakpoint for sychronous network call on main

    thread - SimPholders - ClangFormat-Xcode - Apple-clang-format - SwiftLint - Faux Pas
  155. Be smart write stupid code