Adam Ernst
Architecting and Testing
Large iOS Apps: Lessons
from Facebook
Facebook
developers
Adam Ernst
adamjernst@fb.com
@adamjernst
github.com/adamjernst
Testing Facebook for iOS
Agenda
▪ “Over the wall”: some history
▪ Product Teams and the Core Team
▪ Scheduling and Stabilizing Releases
▪ How We De...
History
Facebook for Mobile
▪ Web deeply engrained in Facebook’s DNA
▪ Use HTML5/Javascript within “wrapper” native app
▪ Develope...
HTML as an app platform
▪ What does it bring us?
One CodebaseInstant Updates A/B Testing
HTML as an app platform
A few engineers in a room
▪ Facebook for iOS 5.0 began as an experiment
A few engineers in a room
▪ Facebook for iOS 5.0 began as an experiment
▪ Could we achieve better results with native code?
A few engineers in a room
▪ Facebook for iOS 5.0 began as an experiment
▪ Could we achieve better results with native code...
A few engineers in a room
▪ Facebook for iOS 5.0 began as an experiment
▪ Could we achieve better results with native code...
A few engineers in a room
▪ Facebook for iOS 5.0 began as an experiment
▪ Could we achieve better results with native code...
Reaction
▪ Press loved it
▪ More importantly…
▪ Perceived Speed way up
▪ User Ratings way up
▪ 2x Speed increase!
Reaction
▪ Press loved it
▪ More importantly…
▪ Perceived Speed way up
▪ User Ratings way up
▪ 2x Speed increase!
Team
A multi-app ecosystem
A multi-app ecosystem
The Team Sandwich
Release Team: Release & Stabilization ProcessRelease Team: Release & Stabilization ProcessRelease Team: ...
Product Cycle
Fixed Release Cycle
▪ Waiting for all features in a
release to be “done” slowed us
down, and we want to move fast
▪ So, sh...
Building features with an “off switch”
▪ Every feature must be built with a way to
turn it off
▪ If a feature destabilizes...
Building a new “Like Bar”
Building a new “Like Bar”
Development
Phabricator
Text
Phabricator
Text
Phabricator
Text
Phabricator
Text
Phabricator
Text
Check code
▪ ‘arc lint’
▪ Set up rules to catch common mistakes
▪ Examples:
▪ Enforce style guidelines
▪ Warn against usin...
@implementation SampleClass
- (void)setupAccessibility
{
self.myView.accessibilityTraits = UIAccessibilityTraitHeader;
}
-...
RegEx Lint Rule
AST Lint Rule
NEW
clang
AST
AST Lint Rules
▪ Regular expressions have false positives and negatives
▪ Dot notation vs braces
▪ Even mentioning forbidd...
Verify changes: Buildbot
▪ Continuous integration
▪ Distributed across multiple build machines
▪ Sanity check:
▪ Do all pr...
Static Analyzer Remote Runs
Buildbot failure email
Builds
Multiple Builds
▪ Use different bundle IDs and icons for different types of builds:
▪ Development
▪ Daily Build
▪ App Stor...
Branching
▪ Two concurrent branches:
▪ Master
▪ Engineers make progress on future features
▪ All changes checked in here fi...
Testing
Testing is important to Facebook
▪ Not in Facebook’s culture:
▪ SDEs “in Test”
▪ Large QA departments
▪ Definitely in Faceb...
Snapshot Unit Tests
typedef NS_ENUM(NSUInteger, FBActionStyle) {
FBActionStyleUndefined = 0,
FBActionStyleDefault = 1,
FBA...
Snapshot Test Case Failures
2013-09-24 17:59:01.743 FBAppKitTestHost[44975:a0b] If you have Kaleidoscope installed you can...
Watchdog Timer
Main Thread work work work work workwork
Watchdog Timer
Main Thread work work work work workwork
Watchdog
Thread
ping
ack
ping
ack
ping
ack
ping
ack
ping
ack
ping
...
Watchdog Timer: How it Works
▪ Max-priority thread pings main thread every X seconds
▪ If main thread doesn’t respond in t...
Rage Shake
▪ Shake the device to report a bug
▪ Captures:
▪ Screen shot (with annotations!)
▪ Network logs
▪ Last crash lo...
Internal Settings
▪ Toggle features on and off
▪ Change parameters
▪ Trigger events
Future of iOS @ Facebook
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook
Upcoming SlideShare
Loading in …5
×

"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook

5,192 views

Published on

In 2012 Facebook relaunched their iOS app to use native code. This was a big shift in architecting and implementing the Facebook app experience, the most widely used third party app on the entire iOS platform. Adam Ernst will speak about how the decision was made to switch to native code and how the company prepared to rewrite the app. He will share an inside look at the APIs and technical architecture Facebook uses to enable dozens of iOS developers to work on the same application. Automated testing is very important to Facebook, so Adam will also speak about how Facebook uses testing on iOS to keep the app reliable.

Published in: Technology
1 Comment
9 Likes
Statistics
Notes
No Downloads
Views
Total views
5,192
On SlideShare
0
From Embeds
0
Number of Embeds
2,240
Actions
Shares
0
Downloads
45
Comments
1
Likes
9
Embeds 0
No embeds

No notes for slide

"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst, Facebook

  1. 1. Adam Ernst Architecting and Testing Large iOS Apps: Lessons from Facebook Facebook
  2. 2. developers Adam Ernst adamjernst@fb.com @adamjernst github.com/adamjernst Testing Facebook for iOS
  3. 3. Agenda ▪ “Over the wall”: some history ▪ Product Teams and the Core Team ▪ Scheduling and Stabilizing Releases ▪ How We Develop ▪ Eating the Dogfood: Builds ▪ A Culture of Unit Testing ▪ Future of iOS at Facebook
  4. 4. History
  5. 5. Facebook for Mobile ▪ Web deeply engrained in Facebook’s DNA ▪ Use HTML5/Javascript within “wrapper” native app ▪ Developed our own framework for advanced integration (image uploads, photo browsers, mixing native/web elements)
  6. 6. HTML as an app platform ▪ What does it bring us? One CodebaseInstant Updates A/B Testing
  7. 7. HTML as an app platform
  8. 8. A few engineers in a room ▪ Facebook for iOS 5.0 began as an experiment
  9. 9. A few engineers in a room ▪ Facebook for iOS 5.0 began as an experiment ▪ Could we achieve better results with native code?
  10. 10. A few engineers in a room ▪ Facebook for iOS 5.0 began as an experiment ▪ Could we achieve better results with native code? ▪ High barrier: requires rewriting every part of Facebook’s mobile UI!
  11. 11. A few engineers in a room ▪ Facebook for iOS 5.0 began as an experiment ▪ Could we achieve better results with native code? ▪ High barrier: requires rewriting every part of Facebook’s mobile UI! ▪ Couldn’t disrupt company for something that might not ship (At the time, few iOS engineers at Facebook anyway)
  12. 12. A few engineers in a room ▪ Facebook for iOS 5.0 began as an experiment ▪ Could we achieve better results with native code? ▪ High barrier: requires rewriting every part of Facebook’s mobile UI! ▪ Couldn’t disrupt company for something that might not ship (At the time, few iOS engineers at Facebook anyway) ▪ Sequester some engineers in a war room, and have them write the product from top to bottom
  13. 13. Reaction ▪ Press loved it ▪ More importantly… ▪ Perceived Speed way up ▪ User Ratings way up ▪ 2x Speed increase!
  14. 14. Reaction ▪ Press loved it ▪ More importantly… ▪ Perceived Speed way up ▪ User Ratings way up ▪ 2x Speed increase!
  15. 15. Team
  16. 16. A multi-app ecosystem
  17. 17. A multi-app ecosystem
  18. 18. The Team Sandwich Release Team: Release & Stabilization ProcessRelease Team: Release & Stabilization ProcessRelease Team: Release & Stabilization ProcessRelease Team: Release & Stabilization ProcessRelease Team: Release & Stabilization Process Photos Feed Search Places Messages Product Infrastructure Team: Shared LibrariesProduct Infrastructure Team: Shared LibrariesProduct Infrastructure Team: Shared LibrariesProduct Infrastructure Team: Shared LibrariesProduct Infrastructure Team: Shared Libraries
  19. 19. Product Cycle
  20. 20. Fixed Release Cycle ▪ Waiting for all features in a release to be “done” slowed us down, and we want to move fast ▪ So, ship an update every X weeks ▪ … no matter what ▪ Popularized by Mozilla
  21. 21. Building features with an “off switch” ▪ Every feature must be built with a way to turn it off ▪ If a feature destabilizes the build or isn’t complete, turn it off and try again next time ▪ #defines – or runtime switches (preferred)
  22. 22. Building a new “Like Bar”
  23. 23. Building a new “Like Bar”
  24. 24. Development
  25. 25. Phabricator Text
  26. 26. Phabricator Text
  27. 27. Phabricator Text
  28. 28. Phabricator Text
  29. 29. Phabricator Text
  30. 30. Check code ▪ ‘arc lint’ ▪ Set up rules to catch common mistakes ▪ Examples: ▪ Enforce style guidelines ▪ Warn against using certain symbols ▪ Check for common pattern mistakes, and fix them!
  31. 31. @implementation SampleClass - (void)setupAccessibility { self.myView.accessibilityTraits = UIAccessibilityTraitHeader; } - (void)dealloc { [_myString dealloc]; [super dealloc]; } @end
  32. 32. RegEx Lint Rule AST Lint Rule NEW clang AST
  33. 33. AST Lint Rules ▪ Regular expressions have false positives and negatives ▪ Dot notation vs braces ▪ Even mentioning forbidden API in a comment triggers rule! ▪ AST lint rules can “understand the code”
  34. 34. Verify changes: Buildbot ▪ Continuous integration ▪ Distributed across multiple build machines ▪ Sanity check: ▪ Do all projects still build? ▪ Do all unit tests still pass? ▪ Emails engineer, and updates Phabricator on failure
  35. 35. Static Analyzer Remote Runs
  36. 36. Buildbot failure email
  37. 37. Builds
  38. 38. Multiple Builds ▪ Use different bundle IDs and icons for different types of builds: ▪ Development ▪ Daily Build ▪ App Store release ▪ Special branches ▪ Burn your build number into your icon
  39. 39. Branching ▪ Two concurrent branches: ▪ Master ▪ Engineers make progress on future features ▪ All changes checked in here first ▪ …including bug fixes for Releases ▪ Release ▪ Once verified in Master… ▪ …“Release team” pulls them into Release branch
  40. 40. Testing
  41. 41. Testing is important to Facebook ▪ Not in Facebook’s culture: ▪ SDEs “in Test” ▪ Large QA departments ▪ Definitely in Facebook culture: ▪ High quality, reliable user experience ▪ We believe in developer-authored unit tests
  42. 42. Snapshot Unit Tests typedef NS_ENUM(NSUInteger, FBActionStyle) { FBActionStyleUndefined = 0, FBActionStyleDefault = 1, FBActionStyleProminent = 2, FBActionStyleSubdued = 3, } static NSArray *FBActionGetStyles() { return @[@"DEFAULT", @"PROMINENT", @"SUBDUED"]; } NSString *FBActionStringFromStyleValue(FBActionStyle styleValue) { NSArray *styles = FBActionGetStyles(); if (styleValue < [styles count]) { return [styles objectAtIndex:styleValue]; } else { return nil; } } typedef NS_ENUM(NSUInteger, FBActionStyle) { FBActionStyleUndefined = 0, FBActionStyleDefault = 1, FBActionStyleProminent = 2, FBActionStyleSubdued = 3, } NSString *FBActionStringFromStyleValue(FBActionStyle styleValue) { switch (styleValue) { case FBActionStyleDefault: return @”DEFAULT”; case FBActionStyleProminent: return @”PROMINENT”; case FBActionStyleSubdued: return @”SUBDUED”; } return nil; } Old Code: New Code:
  43. 43. Snapshot Test Case Failures 2013-09-24 17:59:01.743 FBAppKitTestHost[44975:a0b] If you have Kaleidoscope installed you can run this command to see an image diff: ksdiff "/Users/adamjernst/Library/Application Support/iPhone Simulator/7.0/Applications/D85DEF94-79B2-49AB- ABAA-093044D754CF/tmp/FBMegaphoneViewSnapshotTests/reference_testOverflowContent_socialContext_pad@2x.png" "/ Users/adamjernst/Library/Application Support/iPhone Simulator/7.0/Applications/D85DEF94-79B2-49AB- ABAA-093044D754CF/tmp/FBMegaphoneViewSnapshotTests/failed_testOverflowContent_socialContext_pad@2x.png" /Users/adamjernst/Documents/fbobjc/Libraries/FBAppKit/FBAppKitTests/FBMegaphoneViewSnapshotTests.m:276: SenTestFailureException: "comparisonSuccess__" should be true. Snapshot comparison failed: Error Domain=FBTestSnapshotControllerErrorDomain Code=4 "Images different" UserInfo=0x7b660230 {NSLocalizedDescription=Images different}: 273 FBMegaphoneStoryView *view = [FBMegaphoneStoryView viewForMegaphone:megaphone target:nil frame:CGRectMake(0, 0, 768, 320)]; 274 NSString *newIdentifier = identifier.length ? [NSString stringWithFormat:@"%@_pad", identifier] : @"pad"; 275 [view sizeToFit]; 276 FBSnapshotVerifyView(view, newIdentifier); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ github.com/facebook/ios-snapshot-test-case NEW
  44. 44. Watchdog Timer Main Thread work work work work workwork
  45. 45. Watchdog Timer Main Thread work work work work workwork Watchdog Thread ping ack ping ack ping ack ping ack ping ack ping Uh oh! No ack. Log backtrace.
  46. 46. Watchdog Timer: How it Works ▪ Max-priority thread pings main thread every X seconds ▪ If main thread doesn’t respond in time… ▪ Freeze the main thread ▪ Get the backtrace to see what code is running ▪ Log it to our servers for analysis github.com/facebook/ios-watchdog-timer NEW
  47. 47. Rage Shake ▪ Shake the device to report a bug ▪ Captures: ▪ Screen shot (with annotations!) ▪ Network logs ▪ Last crash log ▪ Last x-seconds of logging ▪ Dumps the view hierarchy ▪ Automatically files a bug and sends it to Facebook
  48. 48. Internal Settings ▪ Toggle features on and off ▪ Change parameters ▪ Trigger events
  49. 49. Future of iOS @ Facebook

×