SlideShare una empresa de Scribd logo
1 de 40
Descargar para leer sin conexión
TDD by Controlling
Dependencies
Jorge D. Ortiz-Fuentes
You Go First
TDD by Controlling
Dependencies
Jorge D. Ortiz-Fuentes
@jdortiz
#Swift2TDD
A Canonical
Examples
production
#Swift2TDD
#Swift2TDD
Agenda
★ TDD
★ Real Life
★ Swift
TDD
TDD
#Swift2TDD
Progress as a developer
★ It does things!
★ It does the things I want!
★ I can prove that it does what I say!
★ I am going to make it do exactly what i say!
Nerdvana
#Swift2TDD
The Rules of Testing
★ We only test our code
★ Only a level of abstraction
★ Only public methods
★ Only one assertion per test
★ Tests are independent of sequence or state
The TDD Dance
Red
Green
Refactor
#Swift2TDD
Pros
★ 100% coverage
★ Detect edge cases
and unforeseen
scenarios
★ Measurable progress
★ Easier to introduce
changes
★ Less debug
★ Decoupled code
★ Explicit
dependencies
★ Single responsibility
★ Autopilot
programming
★ Simpler design
Easier
TDD Cons?
#Swift2TDD
Cons
★ Put the horse before the cart
★ Takes longer
★ Initial investment. Slower and more work in QA
★ Design without the big picture
★ Tests must also be rewritten when requirements
change
★ Other tests are needed too
★ Tests are as bad as code
– Winston Churchill
“Success is stumbling from failure to failure
with no loss of enthusiasm.”
Real
Life
UI Testing
Persistence
Traits
TDD
Swift
+
2
Test the UI
#Swift2TDD
UI Testing
★ Xcode UI Testing ≠ Unit Testing
★ Nor is Kif, Calabash, or Cucumber
(Integration)
★ Unit test is about isolation
View
View Presenter Interactor EntityGateway
Make the view dumb
class SpeakerTableViewCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var dateLabel: UILabel!
}
extension SpeakerTableViewCell: SpeakerCellProtocol {
func displayName(name: String) {
nameLabel.text = name
}
func displayTitle(title: String) {
titleLabel.text = title
}
func displayDateSubmitted(date: String){
dateLabel.text = date
}
}
Testing a label
func testDisplayDateChangesLabelTextToAltValue() {
let labelMock = LabelMock()
sut.dateLabel = labelMock
sut.displayDateSubmitted(speakerAltDateSubmitted)
XCTAssertTrue(labelMock.setTextWasInvoked,
"displayDate must set the text of the label.")
XCTAssertEqual(labelMock.text, speakerAltDateSubmitted,
"displayDate must set the text of the label to the provided text.")
}
// MARK: - Stubs & Mocks
class LabelMock: UILabel {
// MARK: - Properties
var setTextWasInvoked = false
override var text: String? {
didSet {
setTextWasInvoked = true
}
}
}
Test despite the
persistence
#Swift2TDD
Testing Business Logic
★ Persistence seems to be a requirement for
testing the logic
★ But it can be abstracted
★ And the data from the entity gateway
Clean Architecture
View (VC) Presenter
Connector
Interactor Repository
Persistence
WSC
Isolate the user story
class ShowAllSpeakersInteractor {
// MARK: - Properties
let entityGateway: EntityGatewayProtocol
weak var presenter: SpeakersListPresenterProtocol?
// MARK: - Initializers
init(entityGateway: EntityGatewayProtocol) {
self.entityGateway = entityGateway
}
}
extension ShowAllSpeakersInteractor: ShowAllSpeakersInteractorProtocol {
func showAllSpeakers() {
let entities = entityGateway.fetchAllSpeakers()
let displayData = entities.map({entity in
return SpeakerDisplayData(speaker: entity)})
presenter?.presentAllSpeakers(displayData)
}
}
Testing a use case
func testEntityIstransformedIntoDisplayData() {
entityGateway.entities = [Speaker(name: speakerMainName,
title: speakerMainTitle,
synopsis: speakerMainSynopsis,
dateSubmitted: speakerMainDateSubmitted)]
sut.showAllSpeakers()
guard presenter.displayData.count == entityGateway.entities.count
else { XCTFail(“There must be one and only one display data per each
entity of the repo.”)
return }
let speakerData = presenter.displayData[0]
XCTAssertEqual(speakerData.name, speakerMainName,
"Speaker name must be copied onto the display data.")
XCTAssertEqual(speakerData.title, speakerMainTitle,
"Speaker title must be copied onto the display data.")
XCTAssertEqual(speakerData.dateSubmitted, speakerMainDateSubmitted,
"Speaker submitedDate must be copied onto the display data.")
}
Traits
Protocol extensions
protocol SegueHandlerTypeProtocol {
typealias SegueIdentifier: RawRepresentable
}
extension SegueHandlerTypeProtocol where
Self: UIViewController,
SegueIdentifier.RawValue == String {
func performSegueWithIdentifier(segueIdentifier: SegueIdentifier, sender:
AnyObject?) {
performSegueWithIdentifier(segueIdentifier.rawValue, sender: sender)
}
func segueIdentifierForSegue(segue: UIStoryboardSegue) -> SegueIdentifier {
guard let identifier = segue.identifier,
segueIdentifier = SegueIdentifier(rawValue: identifier)
else { fatalError("Invalid segue identifier (segue.identifier).") }
return segueIdentifier
}
}
As explained in WWDC 2015 Swift in Practice
Testing a Trait
var sut: SegueHandlerTypeViewControlerMock!
class SegueHandlerTypeViewControlerMock: UIViewController,
SegueHandlerTypeProtocol {
// MARK: - Properties
var identifierToPerformSegue: String?
var senderPerformingSegue: AnyObject?
enum SegueIdentifier: String {
case FirstSegue = "FirstSegueString"
case SecondSegue = "SecondSegueString"
}
// MARK: - Mocks & Stubs
override func performSegueWithIdentifier(identifier: String, sender:
AnyObject?) {
identifierToPerformSegue = identifier
senderPerformingSegue = sender
}
}
Testing a trait (2)
func testPerformSegueWithIdentifierInvokesClassicVersion() {
sut.performSegueWithIdentifier(SegueHandlerTypeViewControlerMock.SegueIdentifier.FirstSeg
ue, sender: nil)
XCTAssertNotNil(sut.identifierToPerformSegue,
"Classic version of performSegueWithIdentifier must be invoked by the one in
the protocol extension.")
}
func testPerformSegueWithIdentifierPassesRawValueOfFirstIdentifier() {
sut.performSegueWithIdentifier(SegueHandlerTypeViewControlerMock.SegueIdentifier.FirstSeg
ue, sender: nil)
XCTAssertEqual(sut.identifierToPerformSegue, firstSegueString,
"Identifier must correspond to the raw value of the enum case.")
}
func testPerformSegueWithIdentifierPassesRawValueOfSecondIdentifier() {
sut.performSegueWithIdentifier(SegueHandlerTypeViewControlerMock.SegueIdentifier.SecondSe
gue, sender: nil)
XCTAssertEqual(sut.identifierToPerformSegue, secondSegueString,
"Identifier must correspond to the raw value of the enum case.")
}
– Thomas A. Edison
“I have not failed. I’ve just found 10,000
ways that won’t work.”
Thank
you!
@jdortiz
#Swift2TDD
TDD Controlling Dependencies

Más contenido relacionado

La actualidad más candente

Protocols promised-land-2
Protocols promised-land-2Protocols promised-land-2
Protocols promised-land-2Michele Titolo
 
GraphQL API in Clojure
GraphQL API in ClojureGraphQL API in Clojure
GraphQL API in ClojureKent Ohashi
 
The Ring programming language version 1.7 book - Part 85 of 196
The Ring programming language version 1.7 book - Part 85 of 196The Ring programming language version 1.7 book - Part 85 of 196
The Ring programming language version 1.7 book - Part 85 of 196Mahmoud Samir Fayed
 
The Ring programming language version 1.8 book - Part 17 of 202
The Ring programming language version 1.8 book - Part 17 of 202The Ring programming language version 1.8 book - Part 17 of 202
The Ring programming language version 1.8 book - Part 17 of 202Mahmoud Samir Fayed
 
The Ring programming language version 1.10 book - Part 87 of 212
The Ring programming language version 1.10 book - Part 87 of 212The Ring programming language version 1.10 book - Part 87 of 212
The Ring programming language version 1.10 book - Part 87 of 212Mahmoud Samir Fayed
 
The Ring programming language version 1.5.4 book - Part 81 of 185
The Ring programming language version 1.5.4 book - Part 81 of 185The Ring programming language version 1.5.4 book - Part 81 of 185
The Ring programming language version 1.5.4 book - Part 81 of 185Mahmoud Samir Fayed
 
The Ring programming language version 1.3 book - Part 57 of 88
The Ring programming language version 1.3 book - Part 57 of 88The Ring programming language version 1.3 book - Part 57 of 88
The Ring programming language version 1.3 book - Part 57 of 88Mahmoud Samir Fayed
 
OTcl and C++ linkages in NS2
OTcl and C++ linkages in NS2OTcl and C++ linkages in NS2
OTcl and C++ linkages in NS2Pradeep Kumar TS
 
Typescript is the best by Maxim Kryuk
Typescript is the best by Maxim KryukTypescript is the best by Maxim Kryuk
Typescript is the best by Maxim KryukGlobalLogic Ukraine
 
The Ring programming language version 1.7 book - Part 79 of 196
The Ring programming language version 1.7 book - Part 79 of 196The Ring programming language version 1.7 book - Part 79 of 196
The Ring programming language version 1.7 book - Part 79 of 196Mahmoud Samir Fayed
 
The Ring programming language version 1.5.4 book - Part 82 of 185
The Ring programming language version 1.5.4 book - Part 82 of 185The Ring programming language version 1.5.4 book - Part 82 of 185
The Ring programming language version 1.5.4 book - Part 82 of 185Mahmoud Samir Fayed
 
The Ring programming language version 1.9 book - Part 19 of 210
The Ring programming language version 1.9 book - Part 19 of 210The Ring programming language version 1.9 book - Part 19 of 210
The Ring programming language version 1.9 book - Part 19 of 210Mahmoud Samir Fayed
 
The Ring programming language version 1.8 book - Part 88 of 202
The Ring programming language version 1.8 book - Part 88 of 202The Ring programming language version 1.8 book - Part 88 of 202
The Ring programming language version 1.8 book - Part 88 of 202Mahmoud Samir Fayed
 
Groovy AST Demystified
Groovy AST DemystifiedGroovy AST Demystified
Groovy AST DemystifiedAndres Almiray
 
The Ring programming language version 1.7 book - Part 87 of 196
The Ring programming language version 1.7 book - Part 87 of 196The Ring programming language version 1.7 book - Part 87 of 196
The Ring programming language version 1.7 book - Part 87 of 196Mahmoud Samir Fayed
 
Annotation processor and compiler plugin
Annotation processor and compiler pluginAnnotation processor and compiler plugin
Annotation processor and compiler pluginOleksandr Radchykov
 
The Ring programming language version 1.8 book - Part 14 of 202
The Ring programming language version 1.8 book - Part 14 of 202The Ring programming language version 1.8 book - Part 14 of 202
The Ring programming language version 1.8 book - Part 14 of 202Mahmoud Samir Fayed
 

La actualidad más candente (20)

Protocols promised-land-2
Protocols promised-land-2Protocols promised-land-2
Protocols promised-land-2
 
GraphQL API in Clojure
GraphQL API in ClojureGraphQL API in Clojure
GraphQL API in Clojure
 
The Ring programming language version 1.7 book - Part 85 of 196
The Ring programming language version 1.7 book - Part 85 of 196The Ring programming language version 1.7 book - Part 85 of 196
The Ring programming language version 1.7 book - Part 85 of 196
 
The Ring programming language version 1.8 book - Part 17 of 202
The Ring programming language version 1.8 book - Part 17 of 202The Ring programming language version 1.8 book - Part 17 of 202
The Ring programming language version 1.8 book - Part 17 of 202
 
The Ring programming language version 1.10 book - Part 87 of 212
The Ring programming language version 1.10 book - Part 87 of 212The Ring programming language version 1.10 book - Part 87 of 212
The Ring programming language version 1.10 book - Part 87 of 212
 
The Ring programming language version 1.5.4 book - Part 81 of 185
The Ring programming language version 1.5.4 book - Part 81 of 185The Ring programming language version 1.5.4 book - Part 81 of 185
The Ring programming language version 1.5.4 book - Part 81 of 185
 
The Ring programming language version 1.3 book - Part 57 of 88
The Ring programming language version 1.3 book - Part 57 of 88The Ring programming language version 1.3 book - Part 57 of 88
The Ring programming language version 1.3 book - Part 57 of 88
 
OTcl and C++ linkages in NS2
OTcl and C++ linkages in NS2OTcl and C++ linkages in NS2
OTcl and C++ linkages in NS2
 
Typescript is the best
Typescript is the bestTypescript is the best
Typescript is the best
 
Typescript is the best by Maxim Kryuk
Typescript is the best by Maxim KryukTypescript is the best by Maxim Kryuk
Typescript is the best by Maxim Kryuk
 
The Ring programming language version 1.7 book - Part 79 of 196
The Ring programming language version 1.7 book - Part 79 of 196The Ring programming language version 1.7 book - Part 79 of 196
The Ring programming language version 1.7 book - Part 79 of 196
 
The Ring programming language version 1.5.4 book - Part 82 of 185
The Ring programming language version 1.5.4 book - Part 82 of 185The Ring programming language version 1.5.4 book - Part 82 of 185
The Ring programming language version 1.5.4 book - Part 82 of 185
 
Spockを使おう!
Spockを使おう!Spockを使おう!
Spockを使おう!
 
The Ring programming language version 1.9 book - Part 19 of 210
The Ring programming language version 1.9 book - Part 19 of 210The Ring programming language version 1.9 book - Part 19 of 210
The Ring programming language version 1.9 book - Part 19 of 210
 
The Ring programming language version 1.8 book - Part 88 of 202
The Ring programming language version 1.8 book - Part 88 of 202The Ring programming language version 1.8 book - Part 88 of 202
The Ring programming language version 1.8 book - Part 88 of 202
 
Groovy AST Demystified
Groovy AST DemystifiedGroovy AST Demystified
Groovy AST Demystified
 
The Ring programming language version 1.7 book - Part 87 of 196
The Ring programming language version 1.7 book - Part 87 of 196The Ring programming language version 1.7 book - Part 87 of 196
The Ring programming language version 1.7 book - Part 87 of 196
 
Annotation processor and compiler plugin
Annotation processor and compiler pluginAnnotation processor and compiler plugin
Annotation processor and compiler plugin
 
The Ring programming language version 1.8 book - Part 14 of 202
The Ring programming language version 1.8 book - Part 14 of 202The Ring programming language version 1.8 book - Part 14 of 202
The Ring programming language version 1.8 book - Part 14 of 202
 
Introduction to typescript
Introduction to typescriptIntroduction to typescript
Introduction to typescript
 

Destacado

Manual do-laboratório
Manual do-laboratórioManual do-laboratório
Manual do-laboratórioAmilton Filho
 
Ideba Q3, 2015 Visual Portfolio
Ideba Q3, 2015 Visual PortfolioIdeba Q3, 2015 Visual Portfolio
Ideba Q3, 2015 Visual PortfolioIdeba
 
A la boulangie
A la boulangieA la boulangie
A la boulangiejamilepsi
 
خلاصة تجربة 30 عامًا في دعوة غير المسلمين (ميدانيًا وإلكترونيًا)
خلاصة تجربة 30 عامًا في دعوة غير المسلمين (ميدانيًا وإلكترونيًا)خلاصة تجربة 30 عامًا في دعوة غير المسلمين (ميدانيًا وإلكترونيًا)
خلاصة تجربة 30 عامًا في دعوة غير المسلمين (ميدانيًا وإلكترونيًا)Edaawah
 
A systematic review_of_internet_banking
A systematic review_of_internet_bankingA systematic review_of_internet_banking
A systematic review_of_internet_bankingsaali5984
 
Aula 2-planej e caracteristicas-tet
Aula 2-planej e caracteristicas-tetAula 2-planej e caracteristicas-tet
Aula 2-planej e caracteristicas-tetLeibnys
 
1 fil prov. especifica 4 bimestre
1 fil    prov. especifica  4 bimestre1 fil    prov. especifica  4 bimestre
1 fil prov. especifica 4 bimestreFelipe Serra
 
Brunswick Intelligence - Building reputational resilience to cyber attack
Brunswick Intelligence - Building reputational resilience to cyber attackBrunswick Intelligence - Building reputational resilience to cyber attack
Brunswick Intelligence - Building reputational resilience to cyber attackBrunswick Group
 
#FlipMyFunnel Atlanta 2016 - Jason Jue - Personalize The B2B Customer Journey...
#FlipMyFunnel Atlanta 2016 - Jason Jue - Personalize The B2B Customer Journey...#FlipMyFunnel Atlanta 2016 - Jason Jue - Personalize The B2B Customer Journey...
#FlipMyFunnel Atlanta 2016 - Jason Jue - Personalize The B2B Customer Journey...#FlipMyFunnel
 

Destacado (18)

Manual do-laboratório
Manual do-laboratórioManual do-laboratório
Manual do-laboratório
 
Vanguard award
Vanguard awardVanguard award
Vanguard award
 
E portafolio
E portafolioE portafolio
E portafolio
 
Vijay_resume
Vijay_resumeVijay_resume
Vijay_resume
 
Ideba Q3, 2015 Visual Portfolio
Ideba Q3, 2015 Visual PortfolioIdeba Q3, 2015 Visual Portfolio
Ideba Q3, 2015 Visual Portfolio
 
A la boulangie
A la boulangieA la boulangie
A la boulangie
 
Imformatica
ImformaticaImformatica
Imformatica
 
Doc1
Doc1Doc1
Doc1
 
خلاصة تجربة 30 عامًا في دعوة غير المسلمين (ميدانيًا وإلكترونيًا)
خلاصة تجربة 30 عامًا في دعوة غير المسلمين (ميدانيًا وإلكترونيًا)خلاصة تجربة 30 عامًا في دعوة غير المسلمين (ميدانيًا وإلكترونيًا)
خلاصة تجربة 30 عامًا في دعوة غير المسلمين (ميدانيًا وإلكترونيًا)
 
A systematic review_of_internet_banking
A systematic review_of_internet_bankingA systematic review_of_internet_banking
A systematic review_of_internet_banking
 
Aula 2-planej e caracteristicas-tet
Aula 2-planej e caracteristicas-tetAula 2-planej e caracteristicas-tet
Aula 2-planej e caracteristicas-tet
 
1 fil prov. especifica 4 bimestre
1 fil    prov. especifica  4 bimestre1 fil    prov. especifica  4 bimestre
1 fil prov. especifica 4 bimestre
 
Substance Use Disorders
Substance Use DisordersSubstance Use Disorders
Substance Use Disorders
 
выпускница школы № 92
выпускница школы № 92выпускница школы № 92
выпускница школы № 92
 
Brunswick Intelligence - Building reputational resilience to cyber attack
Brunswick Intelligence - Building reputational resilience to cyber attackBrunswick Intelligence - Building reputational resilience to cyber attack
Brunswick Intelligence - Building reputational resilience to cyber attack
 
A.b aula 4 amostragem
A.b aula 4 amostragemA.b aula 4 amostragem
A.b aula 4 amostragem
 
#FlipMyFunnel Atlanta 2016 - Jason Jue - Personalize The B2B Customer Journey...
#FlipMyFunnel Atlanta 2016 - Jason Jue - Personalize The B2B Customer Journey...#FlipMyFunnel Atlanta 2016 - Jason Jue - Personalize The B2B Customer Journey...
#FlipMyFunnel Atlanta 2016 - Jason Jue - Personalize The B2B Customer Journey...
 
Musu zodis
Musu zodisMusu zodis
Musu zodis
 

Similar a TDD Controlling Dependencies

TDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidTDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidCodemotion
 
지금 당장 (유사) BDD 시작하기
지금 당장 (유사) BDD 시작하기지금 당장 (유사) BDD 시작하기
지금 당장 (유사) BDD 시작하기chanju Jeon
 
Why the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureWhy the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureJorge Ortiz
 
Matteo Vaccari - TDD per Android | Codemotion Milan 2015
Matteo Vaccari - TDD per Android | Codemotion Milan 2015Matteo Vaccari - TDD per Android | Codemotion Milan 2015
Matteo Vaccari - TDD per Android | Codemotion Milan 2015Codemotion
 
Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive AppsJorge Ortiz
 
Refactoring In Tdd The Missing Part
Refactoring In Tdd The Missing PartRefactoring In Tdd The Missing Part
Refactoring In Tdd The Missing PartGabriele Lana
 
Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Murat Yener
 
Drinking from the Elixir Fountain of Resilience
Drinking from the Elixir Fountain of ResilienceDrinking from the Elixir Fountain of Resilience
Drinking from the Elixir Fountain of ResilienceC4Media
 
Introduction to Griffon
Introduction to GriffonIntroduction to Griffon
Introduction to GriffonJames Williams
 
Tdd & clean code
Tdd & clean codeTdd & clean code
Tdd & clean codeEyal Vardi
 
Cleaning your architecture with android architecture components
Cleaning your architecture with android architecture componentsCleaning your architecture with android architecture components
Cleaning your architecture with android architecture componentsDebora Gomez Bertoli
 
JDD 2016 - Sebastian Malaca - You Dont Need Unit Tests
JDD 2016 - Sebastian Malaca - You Dont Need Unit TestsJDD 2016 - Sebastian Malaca - You Dont Need Unit Tests
JDD 2016 - Sebastian Malaca - You Dont Need Unit TestsPROIDEA
 
Reactive clean architecture
Reactive clean architectureReactive clean architecture
Reactive clean architectureViktor Nyblom
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2Leonid Maslov
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)Jose Manuel Pereira Garcia
 
Q Con Performance Testing At The Edge
Q Con   Performance Testing At The EdgeQ Con   Performance Testing At The Edge
Q Con Performance Testing At The EdgeAlois Reitbauer
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinJorge Ortiz
 

Similar a TDD Controlling Dependencies (20)

TDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidTDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with Android
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
지금 당장 (유사) BDD 시작하기
지금 당장 (유사) BDD 시작하기지금 당장 (유사) BDD 시작하기
지금 당장 (유사) BDD 시작하기
 
Gwt and Xtend
Gwt and XtendGwt and Xtend
Gwt and Xtend
 
Why the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureWhy the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID Architecture
 
Matteo Vaccari - TDD per Android | Codemotion Milan 2015
Matteo Vaccari - TDD per Android | Codemotion Milan 2015Matteo Vaccari - TDD per Android | Codemotion Milan 2015
Matteo Vaccari - TDD per Android | Codemotion Milan 2015
 
Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive Apps
 
Refactoring In Tdd The Missing Part
Refactoring In Tdd The Missing PartRefactoring In Tdd The Missing Part
Refactoring In Tdd The Missing Part
 
Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15
 
Drinking from the Elixir Fountain of Resilience
Drinking from the Elixir Fountain of ResilienceDrinking from the Elixir Fountain of Resilience
Drinking from the Elixir Fountain of Resilience
 
Introduction to Griffon
Introduction to GriffonIntroduction to Griffon
Introduction to Griffon
 
Tdd & clean code
Tdd & clean codeTdd & clean code
Tdd & clean code
 
Cleaning your architecture with android architecture components
Cleaning your architecture with android architecture componentsCleaning your architecture with android architecture components
Cleaning your architecture with android architecture components
 
JDD 2016 - Sebastian Malaca - You Dont Need Unit Tests
JDD 2016 - Sebastian Malaca - You Dont Need Unit TestsJDD 2016 - Sebastian Malaca - You Dont Need Unit Tests
JDD 2016 - Sebastian Malaca - You Dont Need Unit Tests
 
Qt Workshop
Qt WorkshopQt Workshop
Qt Workshop
 
Reactive clean architecture
Reactive clean architectureReactive clean architecture
Reactive clean architecture
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 
Q Con Performance Testing At The Edge
Q Con   Performance Testing At The EdgeQ Con   Performance Testing At The Edge
Q Con Performance Testing At The Edge
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & Kotlin
 

Más de Jorge Ortiz

Tell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature FlagsTell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature FlagsJorge Ortiz
 
Unit Test your Views
Unit Test your ViewsUnit Test your Views
Unit Test your ViewsJorge Ortiz
 
Control your Voice like a Bene Gesserit
Control your Voice like a Bene GesseritControl your Voice like a Bene Gesserit
Control your Voice like a Bene GesseritJorge Ortiz
 
Kata gilded rose en Golang
Kata gilded rose en GolangKata gilded rose en Golang
Kata gilded rose en GolangJorge Ortiz
 
CYA: Cover Your App
CYA: Cover Your AppCYA: Cover Your App
CYA: Cover Your AppJorge Ortiz
 
Refactor your way forward
Refactor your way forwardRefactor your way forward
Refactor your way forwardJorge Ortiz
 
201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SGJorge Ortiz
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowersJorge Ortiz
 
iOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h editioniOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h editionJorge Ortiz
 
Android clean architecture workshop 3h edition
Android clean architecture workshop 3h editionAndroid clean architecture workshop 3h edition
Android clean architecture workshop 3h editionJorge Ortiz
 
To Protect & To Serve
To Protect & To ServeTo Protect & To Serve
To Protect & To ServeJorge Ortiz
 
Clean architecture workshop
Clean architecture workshopClean architecture workshop
Clean architecture workshopJorge Ortiz
 
Escape from Mars
Escape from MarsEscape from Mars
Escape from MarsJorge Ortiz
 
Dependence day insurgence
Dependence day insurgenceDependence day insurgence
Dependence day insurgenceJorge Ortiz
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowersJorge Ortiz
 
TDD for the masses
TDD for the massesTDD for the masses
TDD for the massesJorge Ortiz
 
7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOSJorge Ortiz
 
Building for perfection
Building for perfectionBuilding for perfection
Building for perfectionJorge Ortiz
 
Unit testing in swift 2 - The before & after story
Unit testing in swift 2 - The before & after storyUnit testing in swift 2 - The before & after story
Unit testing in swift 2 - The before & after storyJorge Ortiz
 
Core Data in Modern Times
Core Data in Modern TimesCore Data in Modern Times
Core Data in Modern TimesJorge Ortiz
 

Más de Jorge Ortiz (20)

Tell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature FlagsTell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature Flags
 
Unit Test your Views
Unit Test your ViewsUnit Test your Views
Unit Test your Views
 
Control your Voice like a Bene Gesserit
Control your Voice like a Bene GesseritControl your Voice like a Bene Gesserit
Control your Voice like a Bene Gesserit
 
Kata gilded rose en Golang
Kata gilded rose en GolangKata gilded rose en Golang
Kata gilded rose en Golang
 
CYA: Cover Your App
CYA: Cover Your AppCYA: Cover Your App
CYA: Cover Your App
 
Refactor your way forward
Refactor your way forwardRefactor your way forward
Refactor your way forward
 
201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
 
iOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h editioniOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h edition
 
Android clean architecture workshop 3h edition
Android clean architecture workshop 3h editionAndroid clean architecture workshop 3h edition
Android clean architecture workshop 3h edition
 
To Protect & To Serve
To Protect & To ServeTo Protect & To Serve
To Protect & To Serve
 
Clean architecture workshop
Clean architecture workshopClean architecture workshop
Clean architecture workshop
 
Escape from Mars
Escape from MarsEscape from Mars
Escape from Mars
 
Dependence day insurgence
Dependence day insurgenceDependence day insurgence
Dependence day insurgence
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
 
TDD for the masses
TDD for the massesTDD for the masses
TDD for the masses
 
7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS
 
Building for perfection
Building for perfectionBuilding for perfection
Building for perfection
 
Unit testing in swift 2 - The before & after story
Unit testing in swift 2 - The before & after storyUnit testing in swift 2 - The before & after story
Unit testing in swift 2 - The before & after story
 
Core Data in Modern Times
Core Data in Modern TimesCore Data in Modern Times
Core Data in Modern Times
 

Último

SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 

Último (20)

SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 

TDD Controlling Dependencies

  • 2.
  • 4.
  • 5. TDD by Controlling Dependencies Jorge D. Ortiz-Fuentes @jdortiz #Swift2TDD
  • 8. TDD
  • 9. TDD
  • 10. #Swift2TDD Progress as a developer ★ It does things! ★ It does the things I want! ★ I can prove that it does what I say! ★ I am going to make it do exactly what i say! Nerdvana
  • 11. #Swift2TDD The Rules of Testing ★ We only test our code ★ Only a level of abstraction ★ Only public methods ★ Only one assertion per test ★ Tests are independent of sequence or state
  • 14. #Swift2TDD Pros ★ 100% coverage ★ Detect edge cases and unforeseen scenarios ★ Measurable progress ★ Easier to introduce changes ★ Less debug ★ Decoupled code ★ Explicit dependencies ★ Single responsibility ★ Autopilot programming ★ Simpler design Easier
  • 16. #Swift2TDD Cons ★ Put the horse before the cart ★ Takes longer ★ Initial investment. Slower and more work in QA ★ Design without the big picture ★ Tests must also be rewritten when requirements change ★ Other tests are needed too ★ Tests are as bad as code
  • 17. – Winston Churchill “Success is stumbling from failure to failure with no loss of enthusiasm.”
  • 24. #Swift2TDD UI Testing ★ Xcode UI Testing ≠ Unit Testing ★ Nor is Kif, Calabash, or Cucumber (Integration) ★ Unit test is about isolation
  • 26. Make the view dumb class SpeakerTableViewCell: UITableViewCell { @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var dateLabel: UILabel! } extension SpeakerTableViewCell: SpeakerCellProtocol { func displayName(name: String) { nameLabel.text = name } func displayTitle(title: String) { titleLabel.text = title } func displayDateSubmitted(date: String){ dateLabel.text = date } }
  • 27. Testing a label func testDisplayDateChangesLabelTextToAltValue() { let labelMock = LabelMock() sut.dateLabel = labelMock sut.displayDateSubmitted(speakerAltDateSubmitted) XCTAssertTrue(labelMock.setTextWasInvoked, "displayDate must set the text of the label.") XCTAssertEqual(labelMock.text, speakerAltDateSubmitted, "displayDate must set the text of the label to the provided text.") } // MARK: - Stubs & Mocks class LabelMock: UILabel { // MARK: - Properties var setTextWasInvoked = false override var text: String? { didSet { setTextWasInvoked = true } } }
  • 29. #Swift2TDD Testing Business Logic ★ Persistence seems to be a requirement for testing the logic ★ But it can be abstracted ★ And the data from the entity gateway
  • 30. Clean Architecture View (VC) Presenter Connector Interactor Repository Persistence WSC
  • 31. Isolate the user story class ShowAllSpeakersInteractor { // MARK: - Properties let entityGateway: EntityGatewayProtocol weak var presenter: SpeakersListPresenterProtocol? // MARK: - Initializers init(entityGateway: EntityGatewayProtocol) { self.entityGateway = entityGateway } } extension ShowAllSpeakersInteractor: ShowAllSpeakersInteractorProtocol { func showAllSpeakers() { let entities = entityGateway.fetchAllSpeakers() let displayData = entities.map({entity in return SpeakerDisplayData(speaker: entity)}) presenter?.presentAllSpeakers(displayData) } }
  • 32. Testing a use case func testEntityIstransformedIntoDisplayData() { entityGateway.entities = [Speaker(name: speakerMainName, title: speakerMainTitle, synopsis: speakerMainSynopsis, dateSubmitted: speakerMainDateSubmitted)] sut.showAllSpeakers() guard presenter.displayData.count == entityGateway.entities.count else { XCTFail(“There must be one and only one display data per each entity of the repo.”) return } let speakerData = presenter.displayData[0] XCTAssertEqual(speakerData.name, speakerMainName, "Speaker name must be copied onto the display data.") XCTAssertEqual(speakerData.title, speakerMainTitle, "Speaker title must be copied onto the display data.") XCTAssertEqual(speakerData.dateSubmitted, speakerMainDateSubmitted, "Speaker submitedDate must be copied onto the display data.") }
  • 34. Protocol extensions protocol SegueHandlerTypeProtocol { typealias SegueIdentifier: RawRepresentable } extension SegueHandlerTypeProtocol where Self: UIViewController, SegueIdentifier.RawValue == String { func performSegueWithIdentifier(segueIdentifier: SegueIdentifier, sender: AnyObject?) { performSegueWithIdentifier(segueIdentifier.rawValue, sender: sender) } func segueIdentifierForSegue(segue: UIStoryboardSegue) -> SegueIdentifier { guard let identifier = segue.identifier, segueIdentifier = SegueIdentifier(rawValue: identifier) else { fatalError("Invalid segue identifier (segue.identifier).") } return segueIdentifier } } As explained in WWDC 2015 Swift in Practice
  • 35. Testing a Trait var sut: SegueHandlerTypeViewControlerMock! class SegueHandlerTypeViewControlerMock: UIViewController, SegueHandlerTypeProtocol { // MARK: - Properties var identifierToPerformSegue: String? var senderPerformingSegue: AnyObject? enum SegueIdentifier: String { case FirstSegue = "FirstSegueString" case SecondSegue = "SecondSegueString" } // MARK: - Mocks & Stubs override func performSegueWithIdentifier(identifier: String, sender: AnyObject?) { identifierToPerformSegue = identifier senderPerformingSegue = sender } }
  • 36. Testing a trait (2) func testPerformSegueWithIdentifierInvokesClassicVersion() { sut.performSegueWithIdentifier(SegueHandlerTypeViewControlerMock.SegueIdentifier.FirstSeg ue, sender: nil) XCTAssertNotNil(sut.identifierToPerformSegue, "Classic version of performSegueWithIdentifier must be invoked by the one in the protocol extension.") } func testPerformSegueWithIdentifierPassesRawValueOfFirstIdentifier() { sut.performSegueWithIdentifier(SegueHandlerTypeViewControlerMock.SegueIdentifier.FirstSeg ue, sender: nil) XCTAssertEqual(sut.identifierToPerformSegue, firstSegueString, "Identifier must correspond to the raw value of the enum case.") } func testPerformSegueWithIdentifierPassesRawValueOfSecondIdentifier() { sut.performSegueWithIdentifier(SegueHandlerTypeViewControlerMock.SegueIdentifier.SecondSe gue, sender: nil) XCTAssertEqual(sut.identifierToPerformSegue, secondSegueString, "Identifier must correspond to the raw value of the enum case.") }
  • 37. – Thomas A. Edison “I have not failed. I’ve just found 10,000 ways that won’t work.”