Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
TDD in iOS
Search
Dominik Hauser
December 04, 2019
Programming
0
47
TDD in iOS
German presentation about TDD in iOS
Dominik Hauser
December 04, 2019
Tweet
Share
Other Decks in Programming
See All in Programming
大体よく分かるscala.collection.immutable.HashMap ~ Compressed Hash-Array Mapped Prefix-tree (CHAMP) ~
matsu_chara
2
220
認証・認可の基本を学ぼう後編
kouyuume
0
240
MAP, Jigsaw, Code Golf 振り返り会 by 関東Kaggler会|Jigsaw 15th Solution
hasibirok0
0
250
認証・認可の基本を学ぼう前編
kouyuume
0
250
俺流レスポンシブコーディング 2025
tak_dcxi
14
8.9k
AIコーディングエージェント(skywork)
kondai24
0
180
堅牢なフロントエンドテスト基盤を構築するために行った取り組み
shogo4131
8
2.4k
「コードは上から下へ読むのが一番」と思った時に、思い出してほしい話
panda728
PRO
38
26k
宅宅自以為的浪漫:跟 AI 一起為自己辦的研討會寫一個售票系統
eddie
0
510
Socio-Technical Evolution: Growing an Architecture and Its Organization for Fast Flow
cer
PRO
0
340
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
120
ローターアクトEクラブ アメリカンナイト:川端 柚菜 氏(Japan O.K. ローターアクトEクラブ 会長):2720 Japan O.K. ロータリーEクラブ2025年12月1日卓話
2720japanoke
0
730
Featured
See All Featured
The Power of CSS Pseudo Elements
geoffreycrofte
80
6.1k
A designer walks into a library…
pauljervisheath
210
24k
Making the Leap to Tech Lead
cromwellryan
135
9.7k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Typedesign – Prime Four
hannesfritz
42
2.9k
The Art of Programming - Codeland 2020
erikaheidi
56
14k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
1
100
Building Adaptive Systems
keathley
44
2.9k
Fireside Chat
paigeccino
41
3.7k
Facilitating Awesome Meetings
lara
57
6.7k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Transcript
TDD und iOS Dominik Hauser, @dasdom
The quality and performance achieved could not have been done
without the use of unit testing. — Bill Bumgarner (bbum), über Core Data 1.0
Vorteile
Vorteile1 · Refaktorierbarkeit · Schnelles Feedback · Gedankenstütze · Doppelte
Buchführung · Regressionsschutz 1 Von (subjektiv) wichtig nach unwichtig
Planning/Feedback Loops Release Plan Code Iteration Plan Acceptance Test Stand
Up Meeting Pair Negotiation Unit Test Pair Programming Months Weeks Days One day Hours Minutes Seconds DonWells (CC BY-SA 3.0)
Wie? Red Green Refactor
Warum so wenig Tests?
"Was soll denn da kaputt gehen?"
if index-1 < userNames.count { nameLabel.text = userNames[index] } else
{ nameLabel.text = "Unknown" }
if index-1 < userNames.count { nameLabel.text = userNames[index] } else
{ nameLabel.text = "Unknown" }
class TableViewCell: UITableViewCell { let label = UILabel() override init(style:
UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) addSubview(label) } }
class TableViewCell: UITableViewCell { let label = UILabel() override init(style:
UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) addSubview(label) } }
"Was soll denn da kaputt gehen?" 1. That can’t happen.
2. That doesn’t happen on my machine. 3. That shouldn’t happen. 4. Why does that happen? 5. Oh, I see. 6. How did that ever work?2 2 Mike W. Cremer
"Machen wir nach dem Release."
RELEASE 1.0 TESTS RELEASE 1.1 Login Login Tests User User
Tests Logout Logout Tests Password reset Password Tests Blocking of users Blocking tests ... ...
RELEASE 1.0 RELEASE 1.1 TESTS Login Login Tests User User
Tests Logout Logout Tests Password reset Password Tests Blocking of users Blocking tests ... ...
RELEASE 1.0 RELEASE 1.1 RELEASE 1.1.1 Login User Logout Password
reset Blocking of users ... ...
Nach den Release ist vor den Release
"UI kann man nicht testen."
func test_viewHasLabel() { sut.loadViewIfNeeded() XCTAssertTrue(sut.label.isDescendant(of: sut.view)) }
func test_loadingView_registersCell() { // when sut.loadViewIfNeeded() // then let cell
= sut.tableView.dequeueReusableCell( withIdentifier: "Cell", for: IndexPath(row: 0, section: 0)) XCTAssertNotNil(cell) XCTAssertTrue(cell is Cell) }
func test_showNext_pushesViewController() { // given let navControllerMock = NavigationControllerMock( rootViewController:
sut) let user = User(name: "Foobar") // when sut.showNext(with: user) // then let detailController = navControllerMock.lastPushedVC as! DetailViewController XCTAssertEqual(detailController.user, user) }
"UI kann man nicht testen." Kann man
Tips & Tricks
Dependency Injection (Inversion of Control)
Zum Beispiel: Constructor Injection let defaultsStub = DefaultsStub(boolToReturn: false) let
user = User(defaults: defaultsStub)
Ausserdem · Constructor Injection · Setter Injection · Interface Injection
Abstraktion
Abstraktion Beispiel: Alerts protocol Alerter { func presentOKAlert(on: UIViewController, title:
String, message: String, okAction: ()->Void) }
View laden func test_foo() { // given ... // when
view loads sut.loadViewIfNeeded() // then ... }
viewWill/DidAppear func test_foo() { // given ... // when view
appears sut.beginAppearanceTransition(true, animated: false) sut.endAppearanceTransition() // then ... }
Modal presentation func test_presentationOfViewController() { // given let window =
UIWindow(frame: CGRect(x: 0, y: 0, width: 300, height: 300)) window.rootViewController = sut window.makeKeyAndVisible() // when sut.showNext() // then XCTAssertTrue(sut.presentedViewController is DetailViewController) }
Bestehender Code Wie anfangen?
Bug ➜ Test
Neues Feature ➜ Test
pragprog.com/book/jrlegios/ ios-unit-testing-by-example
Promolink http://leanpub.com/ tdd_ios_gimme_the_cod e/c/macdev
None
Promolink http://leanpub.com/ tdd_ios_gimme_the_cod e/c/macdev
Ende
Ende!
None