SlideShare a Scribd company logo
1 of 90
Download to read offline
Why we are (not)
writing tests in iOS
apps
by Paul Taykalo, MacPaw
To write or not to write, by Paul Taykalo, #MacPaw 1
Plan
To write or not to write, by Paul Taykalo, #MacPaw 2
Plan
» Tests vs No "Tests" Fractions
» Tests are not needed
» Need are needed
» I'm trying, but failing
» Aren't we testing already?
» Pivot point
» How not to write tests with success
To write or not to write, by Paul Taykalo, #MacPaw 3
Tests
No-Tests
Some-Tests
Groups
To write or not to write, by Paul Taykalo, #MacPaw 4
Tests arent't needed
» My grandpa hasn't run a test
» Waste of time
» Just write correct code
» No time
» ???
To write or not to write, by Paul Taykalo, #MacPaw 5
To write or not to write, by Paul Taykalo, #MacPaw 6
Test all the things
» It's only the right way to do it
» No tests - no feature
To write or not to write, by Paul Taykalo, #MacPaw 7
Some-Tests
To write or not to write, by Paul Taykalo, #MacPaw 8
Aren't we testing
already?
To write or not to write, by Paul Taykalo, #MacPaw 9
Aren't we testing already?
» Debugging
» Logging
» QAs
» End users
To write or not to write, by Paul Taykalo, #MacPaw 10
Testing is hard
To write or not to write, by Paul Taykalo, #MacPaw 11
Testing is hard
» Big/Small
» Very hard integration
» We don't actually know how
» Boring
» Next time
» Ther's no time atm
To write or not to write, by Paul Taykalo, #MacPaw 12
We aren't writing tests. We were
writing tests, but they were too fragile,
and they were breaking for no reason,
so we decided not to
— Unknown programmer
To write or not to write, by Paul Taykalo, #MacPaw 13
Every time new OS released, all my
snapshot tests are broken. It's not
worth it
— Unknown programmer
To write or not to write, by Paul Taykalo, #MacPaw 14
Testing is easy
To write or not to write, by Paul Taykalo, #MacPaw 15
Testing is easy
» Tests already setup
» Intro/PR/Review
» No commits without Tests ¯_( )_/¯
» It is not fixed unless there's a test
To write or not to write, by Paul Taykalo, #MacPaw 16
Why is there so big
difference?
To write or not to write, by Paul Taykalo, #MacPaw 17
Starting Test is hard
To write or not to write, by Paul Taykalo, #MacPaw 18
To write or not to write, by Paul Taykalo, #MacPaw 19
When do we start
thinking about tests?
To write or not to write, by Paul Taykalo, #MacPaw 20
Slowing down
To write or not to write, by Paul Taykalo, #MacPaw 21
Slowing down
» Not sure everything is fine
» R-word (Regression)
» Fixing bugs time >> Feature time
To write or not to write, by Paul Taykalo, #MacPaw 22
Slowing down
» No knowledge
» Huge base
» Different integrations M*N
» Code base/complexity
» Team change
» Same time expectation
To write or not to write, by Paul Taykalo, #MacPaw 23
We've slowed down
To write or not to write, by Paul Taykalo, #MacPaw 24
What did we
wrong?
To write or not to write, by Paul Taykalo, #MacPaw 25
What did we
wrong?
To write or not to write, by Paul Taykalo, #MacPaw 26
What did we
wrong?
To write or not to write, by Paul Taykalo, #MacPaw 27
What did we
wrong?
To write or not to write, by Paul Taykalo, #MacPaw 28
Time to add tests?
To write or not to write, by Paul Taykalo, #MacPaw 29
Tests
Expectations vs reality
To write or not to write, by Paul Taykalo, #MacPaw 30
Tests
Expectations vs reality
To write or not to write, by Paul Taykalo, #MacPaw 31
I added tests they didn't help
— Unknown programmer
To write or not to write, by Paul Taykalo, #MacPaw 32
Tests are not a cure
Tests are the
insurance
To write or not to write, by Paul Taykalo, #MacPaw 33
I spent weeks trying to test UI and
failed all deadlines
— Unknown programmer
To write or not to write, by Paul Taykalo, #MacPaw 34
Some parts are really
hard to test
Deal with it
To write or not to write, by Paul Taykalo, #MacPaw 35
There are a lot of tests, but the code
doesn't seem to be better
— Unknown programmer
To write or not to write, by Paul Taykalo, #MacPaw 36
Tests won't make your code
significantly better*
To write or not to write, by Paul Taykalo, #MacPaw 37
You still can write ugly code
To write or not to write, by Paul Taykalo, #MacPaw 38
Your tests can be ugly as well
To write or not to write, by Paul Taykalo, #MacPaw 39
The Good, The Bad
and The Ugly
To write or not to write, by Paul Taykalo, #MacPaw 40
The Bad
To write or not to write, by Paul Taykalo, #MacPaw 41
The Bad
func testImtheS() {
let url = "http://agileinaflash.com/feeds/posts/default"
let content = Data(withContensOfURL:URL(string:url))!
XCTAssertNotNil(content)
let parsedContent = parse(content)!
let rss = RSS(from: parsedContent)!
XCTAssertEqual(rss.title, title)
}
To write or not to write, by Paul Taykalo, #MacPaw 42
The Bad
func testImtheS() {
let url = "http://agileinaflash.com/feeds/posts/default"
let content = Data(withContensOfURL:URL(string:url))!
XCTAssertNotNil(content)
let parsedContent = parse(content)!
let rss = RSS(from: parsedContent)!
XCTAssertEqual(rss.title, title)
}
To write or not to write, by Paul Taykalo, #MacPaw 43
The Bad
func testImtheS() {
let url = "http://agileinaflash.com/feeds/posts/default"
let content = Data(withContensOfURL:URL(string:url))!
XCTAssertNotNil(content)
let parsedContent = parse(content)!
let rss = RSS(from: parsedContent)!
XCTAssertEqual(rss.title, title)
}
To write or not to write, by Paul Taykalo, #MacPaw 44
The Bad
func testImtheS() {
let url = "http://agileinaflash.com/feeds/posts/default"
let content = Data(withContensOfURL:URL(string:url))!
XCTAssertNotNil(content)
let parsedContent = parse(content)!
let rss = RSS(from: parsedContent)!
XCTAssertEqual(rss.title, title)
}
To write or not to write, by Paul Taykalo, #MacPaw 45
The Ugly
To write or not to write, by Paul Taykalo, #MacPaw 46
The Ugly
func testEncoding() {
let path = "Foo/Bar/Baz"
let info = ["Key": "Hello World"]
let request1 = XPCRequest(path: path, info: info)
let data1 = request1.encode()
let decoded1 = XPCRequest(with: data1)!
XCTAssertEqual(request1.path, decoded1.path)
XCTAssertTrue(NSDictionary(dictionary: request1.info!).isEqual(to: decoded1.info!))
let request2 = XPCRequest(path: path, info: nil)
let data2 = request2.encode()
let decoded2 = XPCRequest(with: data2)!
XCTAssertEqual(request2.path, decoded2.path)
XCTAssertNil(request2.info)
}
To write or not to write, by Paul Taykalo, #MacPaw 47
The Ugly
func testMenuItemCreated() throws {
let simulatedClickedRow = 7
let simulatedItems = ["Hello", " World!"]
let mapperExpectation = expectation(description: "mapper should be called")
let mapper: ([Any]) -> [String]? = { objects in
mapperExpectation.fulfill()
return objects as? [String]
}
let formatExpectation = expectation(description: "format should be called")
let format: ([String], Int, Localization.Type) -> String? = { strings, clickedRow, localization in
formatExpectation.fulfill()
XCTAssertEqual(strings, simulatedItems)
XCTAssertEqual(clickedRow, simulatedClickedRow)
return strings.reduce("") { $0 + $1 }
}
let action: ([String], Int) -> Void = { _, _ in }
let keyEquivalent: String = "Key"
let builder = MenuItemBuilder<String>(keyEquivalent: keyEquivalent, mapper: mapper, format: format, action: action)
let menuItem = try require(builder.item(from: simulatedItems, with: simulatedClickedRow))
XCTAssertEqual(menuItem.keyEquivalent, keyEquivalent)
XCTAssertEqual(menuItem.title, "Hello World!")
waitForExpectations(timeout: 0.0) { error in
XCTAssertFalse(error != nil)
}
}
To write or not to write, by Paul Taykalo, #MacPaw 48
The Good
To write or not to write, by Paul Taykalo, #MacPaw 49
F. I. R. S. T.
To write or not to write, by Paul Taykalo, #MacPaw 50
F. I. R. S. T.
» Fast — tests should be able to be executed often.
» Isolated — tests on their own cannot depend on external
factors or on the result of another test.
» Repeatable — tests should have the same result every time we
run them.(*)
» Self-verifying — tests should include assertions; no human
intervention needed.
» Timely — tests should be written along with the production
To write or not to write, by Paul Taykalo, #MacPaw 51
The Good
- (void)testAddMalwareInformationCanBeReadFromDataBase {
// Given
TestMalwareInfo info = [self.knowledgeBase _addMalwareInfo];
// When
NSDictionary *malwareInfo = [self.knowledgeBase malwareInfoForItem:nil hash:info.hash];
// Then
XCTAssertEqualObjects(malwareInfo[CMMalwareInfoKeyName], info.name);
XCTAssertEqualObjects(malwareInfo[CMMalwareInfoKeyType], info.type);
}
To write or not to write, by Paul Taykalo, #MacPaw 52
The Good
- (void)testMalwareDetectionTasksReturnsMalwareModels {
// Given
MPFileSizerMockWithStubbedAnyPath(^(MPFileSize size) {
CMMalwaresDetectionTask * sut = [self _sutWithItemsCount:3 malwaresCount:2];
// When
CMScanResult *result = [sut scan];
CMEntity *entity = [result.items firstObject];
// Then
XCTAssertTrue([entity isKindOfClass:[CMMalwareModel class]]);
});}
To write or not to write, by Paul Taykalo, #MacPaw 53
The Good
- (void)testMalwareDetectionTasksReturnsMalwareModels {
// Given
MPFileSizerMockWithStubbedAnyPath(^(MPFileSize size) {
CMMalwaresDetectionTask * sut = [self _sutWithItemsCount:3 malwaresCount:2];
// When
CMScanResult *result = [sut scan];
CMEntity *entity = [result.items firstObject];
// Then
XCTAssertTrue([entity isKindOfClass:[CMMalwareModel class]]);
});}
To write or not to write, by Paul Taykalo, #MacPaw 54
The Good
- (void)testMalwareDetectionTasksReturnsMalwareModels {
// Given
MPFileSizerMockWithStubbedAnyPath(^(MPFileSize size) {
CMMalwaresDetectionTask * sut = [self _sutWithItemsCount:3 malwaresCount:2];
// When
CMScanResult *result = [sut scan];
CMEntity *entity = [result.items firstObject];
// Then
XCTAssertTrue([entity isKindOfClass:[CMMalwareModel class]]);
});}
To write or not to write, by Paul Taykalo, #MacPaw 55
The Good
- (void)testMalwareDetectionTasksReturnsMalwareModels {
// Given
MPFileSizerMockWithStubbedAnyPath(^(MPFileSize size) {
CMMalwaresDetectionTask * sut = [self _sutWithItemsCount:3 malwaresCount:2];
// When
CMScanResult *result = [sut scan];
CMEntity *entity = [result.items firstObject];
// Then
XCTAssertTrue([entity isKindOfClass:[CMMalwareModel class]]);
});}
To write or not to write, by Paul Taykalo, #MacPaw 56
Why aren't we writing
tests?
To write or not to write, by Paul Taykalo, #MacPaw 57
Why aren't we writing tests?
» Too small (project)
» Simple project
» Clear code
» No complaints from product owner/users
To write or not to write, by Paul Taykalo, #MacPaw 58
Some tips for
those who
doesn't write
tests
To write or not to write, by Paul Taykalo, #MacPaw 59
Some tips for
those who
doesn't write
tests
To write or not to write, by Paul Taykalo, #MacPaw 60
Don't show/require all data
YAGNI
struct User {
let id: String
let name: String
let address: String
let friends: [User]
let dogName: String?
let hairStyle: HairStyle
...
}
To write or not to write, by Paul Taykalo, #MacPaw 61
Own Data layer
Layer things out
class AppApi {
func getUser(by id: String)
-> SignalProducer<User, AppApiError>
}
To write or not to write, by Paul Taykalo, #MacPaw 62
Layer things out
enum AppApiError: Error {
case userNotLoggedIn
case serverFeelsBad
case subscriptionEnded
case unknown(NetworkError) //
}
To write or not to write, by Paul Taykalo, #MacPaw 63
Layer things out
// Struct for showing error imeediately to the user
struct UserError {
let title: String
let message: String
// just in some really rare cases
let underlyingError: Error
}
To write or not to write, by Paul Taykalo, #MacPaw 64
Don't allow invalid data
struct UserForm {
let id: String?
let name: String?
let lastName: String?
}
struct User {
let id: String
let name: String
let lastName: String
}
To write or not to write, by Paul Taykalo, #MacPaw 65
Isolate Order Dependent Code
dataSource.addItems(["1","2","3")
tableView.insertItems(at indexPaths:[IndexPath])
tableView.deleteItems(at indexPaths:[])
tableView.reloadData()
To write or not to write, by Paul Taykalo, #MacPaw 66
Semantic meaning
if itemsCount > 4
if user.rating > 200 && user.userName.isNotEmpty
if view.tag == 13
To write or not to write, by Paul Taykalo, #MacPaw 67
Unidirectional data
flow
To write or not to write, by Paul Taykalo, #MacPaw 68
Linear code
loginUser(onSuccess: { user in
getAllImages(for: user, onSuccess: { images is
verify(images: images, onSuccess: { verified, unverified is
verifyDeletion(images: unverified, onSuccess: { shouldDelete in
},
onFailure: {
// TODO Handle it
print(error)
})
},
onFailure: {
// TODO Handle it
print(error)
})
},
onFailure: {
// TODO Handle it
print(error)
})
},
onFailure: {
// TODO Handle it
print(error)
})
To write or not to write, by Paul Taykalo, #MacPaw 69
Linear code
loggeduserRequest
.flatMap(.latest, { user in getAllimages(for: user)})
.flatMap(.latest, { images in verify(images: images)})
.flatMap { verified, unverified in askForDeletion(images: unverified)}
.filter { shouldDelete in deleteImages(shouldDelete) }
To write or not to write, by Paul Taykalo, #MacPaw 70
Linear code
loggeduserRequest
.flatMap(.latest, getAllimages)
.flatMap(.latest, verify)
.flatMap { verified, unverified in askForDeletion(images: unverified)}
.filter(deleteImages)
To write or not to write, by Paul Taykalo, #MacPaw 71
Non failable code
file.open()
guard something else { file.close(); return}
file.read()
file.close()
To write or not to write, by Paul Taykalo, #MacPaw 72
Non failable code
extension File {
func opened(process: (File -> Void)) {
open()
process(self)
close();
}
}
file.opened { f in
guard something else { return }
f.read()
}
To write or not to write, by Paul Taykalo, #MacPaw 73
Decrease amount of possible
states
» Optionals
» BFO (Object)
» Exponential number of states
» Mutability
To write or not to write, by Paul Taykalo, #MacPaw 74
Some tips for those who doesn't
write tests
» Don't show/require all data
» Layer things out
» Don't allow invalid data
» Semantic meaning
» Linear flow
» Decrease amount of possible states
To write or not to write, by Paul Taykalo, #MacPaw 75
More tips for those
who doesn't write
tests
To write or not to write, by Paul Taykalo, #MacPaw 76
More tips for those who doesn't
write tests
» Visual snapshots
» Revealing hidden info (i.e. Analytics)
» Logs
To write or not to write, by Paul Taykalo, #MacPaw 77
How (not) to fail
adding tests
To write or not to write, by Paul Taykalo, #MacPaw 78
How (not) to fail adding tests
» Read a lot about testing and types of testing
» Try to test-first, try to test-last
» Determine your core
» Isolate features and test them
» Start with Unit tests
» For Custom UI you can run snapshot testing
» Hire someone and let them help you
To write or not to write, by Paul Taykalo, #MacPaw 79
Te$t$
To write or not to write, by Paul Taykalo, #MacPaw 80
- I won't pay additionally for tests
- But there'll be bugs
- They'll be there even if you write tests!
To write or not to write, by Paul Taykalo, #MacPaw 81
Tests readiness
To write or not to write, by Paul Taykalo, #MacPaw 82
There are many ways to write an
application. We're not building
spaceships, you know?
— Unknown programmer
To write or not to write, by Paul Taykalo, #MacPaw 83
Thank you
To write or not to write, by Paul Taykalo, #MacPaw 84
Q & A
To write or not to write, by Paul Taykalo, #MacPaw 85
Why we are (not)
writing tests in iOS
apps
by Paul Taykalo, MacPaw
@TT_Kilew
To write or not to write, by Paul Taykalo, #MacPaw 86
The end
To write or not to write, by Paul Taykalo, #MacPaw 87
Bonus
Building a Swift Quiz App with TDD
and Modular Design
https://goo.gl/cUzTkr
To write or not to write, by Paul Taykalo, #MacPaw 88
Links
http://merowing.info/2017/01/testing-ios-apps/
https://www.swiftbysundell.com/posts/testing-swift-code-
that-uses-system-singletons-in-3-easy-steps?
utmcontent=buffer1765f&utmmedium=social&utmsource=twitter.co
m&utmcampaign=buffer
https://www.joelonsoftware.com/2001/07/31/hard-assed-bug-
fixin/
https://www.objc.io/issues/15-testing/bad-testing-practices/
To write or not to write, by Paul Taykalo, #MacPaw 89
More links
https://medium.com/essential-developer-ios
To write or not to write, by Paul Taykalo, #MacPaw 90

More Related Content

Similar to Is it time to write unit tests?

utPLSQL: Unit Testing for Oracle PL/SQL
utPLSQL: Unit Testing for Oracle PL/SQLutPLSQL: Unit Testing for Oracle PL/SQL
utPLSQL: Unit Testing for Oracle PL/SQLSteven Feuerstein
 
Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)vilniusjug
 
Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"Fwdays
 
Narrow Down What to Test
Narrow Down What to TestNarrow Down What to Test
Narrow Down What to TestZsolt Fabok
 
Testing in FrontEnd World by Nikita Galkin
Testing in FrontEnd World by Nikita GalkinTesting in FrontEnd World by Nikita Galkin
Testing in FrontEnd World by Nikita GalkinSigma Software
 
Approval Testing & Mutation Testing - Cork Software Crafters - June 2019
Approval Testing & Mutation Testing - Cork Software Crafters - June 2019Approval Testing & Mutation Testing - Cork Software Crafters - June 2019
Approval Testing & Mutation Testing - Cork Software Crafters - June 2019Paulo Clavijo
 
Unit Test Your Database
Unit Test Your DatabaseUnit Test Your Database
Unit Test Your DatabaseDavid Wheeler
 
Deliberate Practice, New Learning Styles (2015)
Deliberate Practice, New Learning Styles (2015)Deliberate Practice, New Learning Styles (2015)
Deliberate Practice, New Learning Styles (2015)Peter Kofler
 
Developer Tests - Things to Know
Developer Tests - Things to KnowDeveloper Tests - Things to Know
Developer Tests - Things to KnowVaidas Pilkauskas
 
Extreme Programming practices for your team
Extreme Programming practices for your teamExtreme Programming practices for your team
Extreme Programming practices for your teamPawel Lipinski
 
TDD super mondays-june-2014
TDD super mondays-june-2014TDD super mondays-june-2014
TDD super mondays-june-2014Alex Kavanagh
 

Similar to Is it time to write unit tests? (15)

utPLSQL: Unit Testing for Oracle PL/SQL
utPLSQL: Unit Testing for Oracle PL/SQLutPLSQL: Unit Testing for Oracle PL/SQL
utPLSQL: Unit Testing for Oracle PL/SQL
 
Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)
 
Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"
 
Narrow Down What to Test
Narrow Down What to TestNarrow Down What to Test
Narrow Down What to Test
 
Testing in FrontEnd World by Nikita Galkin
Testing in FrontEnd World by Nikita GalkinTesting in FrontEnd World by Nikita Galkin
Testing in FrontEnd World by Nikita Galkin
 
Approval Testing & Mutation Testing - Cork Software Crafters - June 2019
Approval Testing & Mutation Testing - Cork Software Crafters - June 2019Approval Testing & Mutation Testing - Cork Software Crafters - June 2019
Approval Testing & Mutation Testing - Cork Software Crafters - June 2019
 
Unit Test Your Database
Unit Test Your DatabaseUnit Test Your Database
Unit Test Your Database
 
Deliberate Practice, New Learning Styles (2015)
Deliberate Practice, New Learning Styles (2015)Deliberate Practice, New Learning Styles (2015)
Deliberate Practice, New Learning Styles (2015)
 
Developer Tests - Things to Know
Developer Tests - Things to KnowDeveloper Tests - Things to Know
Developer Tests - Things to Know
 
TDD Best Practices
TDD Best PracticesTDD Best Practices
TDD Best Practices
 
Extreme Programming practices for your team
Extreme Programming practices for your teamExtreme Programming practices for your team
Extreme Programming practices for your team
 
IntroTestMore
IntroTestMoreIntroTestMore
IntroTestMore
 
IntroTestMore
IntroTestMoreIntroTestMore
IntroTestMore
 
TDD super mondays-june-2014
TDD super mondays-june-2014TDD super mondays-june-2014
TDD super mondays-june-2014
 
Tdd - introduction
Tdd - introductionTdd - introduction
Tdd - introduction
 

More from Artjoker

Redux and React. Learning from giants.
Redux and React. Learning from giants.Redux and React. Learning from giants.
Redux and React. Learning from giants.Artjoker
 
MVVM+Router or how to use all advantage from MVVM and VIPER
MVVM+Router or how to use all advantage from MVVM and VIPERMVVM+Router or how to use all advantage from MVVM and VIPER
MVVM+Router or how to use all advantage from MVVM and VIPERArtjoker
 
"Опыт внедрения автоматизации на PHP проектах (Docker, Gitlab CI)"
"Опыт внедрения автоматизации на PHP проектах (Docker, Gitlab CI)""Опыт внедрения автоматизации на PHP проектах (Docker, Gitlab CI)"
"Опыт внедрения автоматизации на PHP проектах (Docker, Gitlab CI)"Artjoker
 
«Let`s do it right»
«Let`s do it right»«Let`s do it right»
«Let`s do it right»Artjoker
 
«Высоконагруженное тестирование РНР проектов»
«Высоконагруженное тестирование РНР проектов» «Высоконагруженное тестирование РНР проектов»
«Высоконагруженное тестирование РНР проектов» Artjoker
 
3-е свидание с functional-js, что дальше
3-е свидание с functional-js, что дальше3-е свидание с functional-js, что дальше
3-е свидание с functional-js, что дальшеArtjoker
 
GraphQL для FrontEnd разработчика
GraphQL для FrontEnd разработчикаGraphQL для FrontEnd разработчика
GraphQL для FrontEnd разработчикаArtjoker
 
React 16: new features and beyond
React 16: new features and beyondReact 16: new features and beyond
React 16: new features and beyondArtjoker
 
Первые шаги интернет-магазина одежды
Первые шаги интернет-магазина одеждыПервые шаги интернет-магазина одежды
Первые шаги интернет-магазина одеждыArtjoker
 
«Без каких микровзаимодействий нельзя делать WEB и mobile продукты в 2018-м»
«Без каких микровзаимодействий нельзя делать WEB и mobile продукты в 2018-м»«Без каких микровзаимодействий нельзя делать WEB и mobile продукты в 2018-м»
«Без каких микровзаимодействий нельзя делать WEB и mobile продукты в 2018-м»Artjoker
 
«Эмоциональный веб-дизайн, история одного чуткого лендинга»
«Эмоциональный веб-дизайн, история одного чуткого лендинга» «Эмоциональный веб-дизайн, история одного чуткого лендинга»
«Эмоциональный веб-дизайн, история одного чуткого лендинга» Artjoker
 
«Дизайн система для мобильных и веб проектов»
«Дизайн система для мобильных и веб проектов»«Дизайн система для мобильных и веб проектов»
«Дизайн система для мобильных и веб проектов»Artjoker
 
QA Evening Марк Курченко - Чек-лист против тест-кейса
QA Evening Марк Курченко - Чек-лист против тест-кейсаQA Evening Марк Курченко - Чек-лист против тест-кейса
QA Evening Марк Курченко - Чек-лист против тест-кейсаArtjoker
 
QA Evening Игорь Колосов - Performance Testing: Metrics & Measurements
QA Evening Игорь Колосов - Performance Testing: Metrics & MeasurementsQA Evening Игорь Колосов - Performance Testing: Metrics & Measurements
QA Evening Игорь Колосов - Performance Testing: Metrics & MeasurementsArtjoker
 
QA Evening Максим Колотилкин - Test State Pattern
QA Evening Максим Колотилкин - Test State PatternQA Evening Максим Колотилкин - Test State Pattern
QA Evening Максим Колотилкин - Test State PatternArtjoker
 
Меликян Артём (Team Lead of SEO Classifieds, Netpeak) Продвижение крупных про...
Меликян Артём (Team Lead of SEO Classifieds, Netpeak) Продвижение крупных про...Меликян Артём (Team Lead of SEO Classifieds, Netpeak) Продвижение крупных про...
Меликян Артём (Team Lead of SEO Classifieds, Netpeak) Продвижение крупных про...Artjoker
 
Клуб Большого мозга - DevOps Evening
Клуб Большого мозга - DevOps EveningКлуб Большого мозга - DevOps Evening
Клуб Большого мозга - DevOps EveningArtjoker
 
Performance: How to build an app instead of slideshow
Performance: How to build an app instead of slideshowPerformance: How to build an app instead of slideshow
Performance: How to build an app instead of slideshowArtjoker
 
Productivity Hero. Know Your Tools
Productivity Hero. Know Your ToolsProductivity Hero. Know Your Tools
Productivity Hero. Know Your ToolsArtjoker
 
Мобильная разработка. Между Сциллой и Харибдой. Native, hybrid or cross platf...
Мобильная разработка. Между Сциллой и Харибдой. Native, hybrid or cross platf...Мобильная разработка. Между Сциллой и Харибдой. Native, hybrid or cross platf...
Мобильная разработка. Между Сциллой и Харибдой. Native, hybrid or cross platf...Artjoker
 

More from Artjoker (20)

Redux and React. Learning from giants.
Redux and React. Learning from giants.Redux and React. Learning from giants.
Redux and React. Learning from giants.
 
MVVM+Router or how to use all advantage from MVVM and VIPER
MVVM+Router or how to use all advantage from MVVM and VIPERMVVM+Router or how to use all advantage from MVVM and VIPER
MVVM+Router or how to use all advantage from MVVM and VIPER
 
"Опыт внедрения автоматизации на PHP проектах (Docker, Gitlab CI)"
"Опыт внедрения автоматизации на PHP проектах (Docker, Gitlab CI)""Опыт внедрения автоматизации на PHP проектах (Docker, Gitlab CI)"
"Опыт внедрения автоматизации на PHP проектах (Docker, Gitlab CI)"
 
«Let`s do it right»
«Let`s do it right»«Let`s do it right»
«Let`s do it right»
 
«Высоконагруженное тестирование РНР проектов»
«Высоконагруженное тестирование РНР проектов» «Высоконагруженное тестирование РНР проектов»
«Высоконагруженное тестирование РНР проектов»
 
3-е свидание с functional-js, что дальше
3-е свидание с functional-js, что дальше3-е свидание с functional-js, что дальше
3-е свидание с functional-js, что дальше
 
GraphQL для FrontEnd разработчика
GraphQL для FrontEnd разработчикаGraphQL для FrontEnd разработчика
GraphQL для FrontEnd разработчика
 
React 16: new features and beyond
React 16: new features and beyondReact 16: new features and beyond
React 16: new features and beyond
 
Первые шаги интернет-магазина одежды
Первые шаги интернет-магазина одеждыПервые шаги интернет-магазина одежды
Первые шаги интернет-магазина одежды
 
«Без каких микровзаимодействий нельзя делать WEB и mobile продукты в 2018-м»
«Без каких микровзаимодействий нельзя делать WEB и mobile продукты в 2018-м»«Без каких микровзаимодействий нельзя делать WEB и mobile продукты в 2018-м»
«Без каких микровзаимодействий нельзя делать WEB и mobile продукты в 2018-м»
 
«Эмоциональный веб-дизайн, история одного чуткого лендинга»
«Эмоциональный веб-дизайн, история одного чуткого лендинга» «Эмоциональный веб-дизайн, история одного чуткого лендинга»
«Эмоциональный веб-дизайн, история одного чуткого лендинга»
 
«Дизайн система для мобильных и веб проектов»
«Дизайн система для мобильных и веб проектов»«Дизайн система для мобильных и веб проектов»
«Дизайн система для мобильных и веб проектов»
 
QA Evening Марк Курченко - Чек-лист против тест-кейса
QA Evening Марк Курченко - Чек-лист против тест-кейсаQA Evening Марк Курченко - Чек-лист против тест-кейса
QA Evening Марк Курченко - Чек-лист против тест-кейса
 
QA Evening Игорь Колосов - Performance Testing: Metrics & Measurements
QA Evening Игорь Колосов - Performance Testing: Metrics & MeasurementsQA Evening Игорь Колосов - Performance Testing: Metrics & Measurements
QA Evening Игорь Колосов - Performance Testing: Metrics & Measurements
 
QA Evening Максим Колотилкин - Test State Pattern
QA Evening Максим Колотилкин - Test State PatternQA Evening Максим Колотилкин - Test State Pattern
QA Evening Максим Колотилкин - Test State Pattern
 
Меликян Артём (Team Lead of SEO Classifieds, Netpeak) Продвижение крупных про...
Меликян Артём (Team Lead of SEO Classifieds, Netpeak) Продвижение крупных про...Меликян Артём (Team Lead of SEO Classifieds, Netpeak) Продвижение крупных про...
Меликян Артём (Team Lead of SEO Classifieds, Netpeak) Продвижение крупных про...
 
Клуб Большого мозга - DevOps Evening
Клуб Большого мозга - DevOps EveningКлуб Большого мозга - DevOps Evening
Клуб Большого мозга - DevOps Evening
 
Performance: How to build an app instead of slideshow
Performance: How to build an app instead of slideshowPerformance: How to build an app instead of slideshow
Performance: How to build an app instead of slideshow
 
Productivity Hero. Know Your Tools
Productivity Hero. Know Your ToolsProductivity Hero. Know Your Tools
Productivity Hero. Know Your Tools
 
Мобильная разработка. Между Сциллой и Харибдой. Native, hybrid or cross platf...
Мобильная разработка. Между Сциллой и Харибдой. Native, hybrid or cross platf...Мобильная разработка. Между Сциллой и Харибдой. Native, hybrid or cross platf...
Мобильная разработка. Между Сциллой и Харибдой. Native, hybrid or cross platf...
 

Recently uploaded

Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)Dana Luther
 
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call GirlVIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girladitipandeya
 
AlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with FlowsAlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with FlowsThierry TROUIN ☁
 
Denver Web Design brochure for public viewing
Denver Web Design brochure for public viewingDenver Web Design brochure for public viewing
Denver Web Design brochure for public viewingbigorange77
 
How is AI changing journalism? (v. April 2024)
How is AI changing journalism? (v. April 2024)How is AI changing journalism? (v. April 2024)
How is AI changing journalism? (v. April 2024)Damian Radcliffe
 
On Starlink, presented by Geoff Huston at NZNOG 2024
On Starlink, presented by Geoff Huston at NZNOG 2024On Starlink, presented by Geoff Huston at NZNOG 2024
On Starlink, presented by Geoff Huston at NZNOG 2024APNIC
 
FULL ENJOY Call Girls In Mayur Vihar Delhi Contact Us 8377087607
FULL ENJOY Call Girls In Mayur Vihar Delhi Contact Us 8377087607FULL ENJOY Call Girls In Mayur Vihar Delhi Contact Us 8377087607
FULL ENJOY Call Girls In Mayur Vihar Delhi Contact Us 8377087607dollysharma2066
 
VIP Kolkata Call Girl Dum Dum 👉 8250192130 Available With Room
VIP Kolkata Call Girl Dum Dum 👉 8250192130  Available With RoomVIP Kolkata Call Girl Dum Dum 👉 8250192130  Available With Room
VIP Kolkata Call Girl Dum Dum 👉 8250192130 Available With Roomdivyansh0kumar0
 
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)Christopher H Felton
 
Russian Call Girls Thane Swara 8617697112 Independent Escort Service Thane
Russian Call Girls Thane Swara 8617697112 Independent Escort Service ThaneRussian Call Girls Thane Swara 8617697112 Independent Escort Service Thane
Russian Call Girls Thane Swara 8617697112 Independent Escort Service ThaneCall girls in Ahmedabad High profile
 
Networking in the Penumbra presented by Geoff Huston at NZNOG
Networking in the Penumbra presented by Geoff Huston at NZNOGNetworking in the Penumbra presented by Geoff Huston at NZNOG
Networking in the Penumbra presented by Geoff Huston at NZNOGAPNIC
 
VIP Call Girls Pune Madhuri 8617697112 Independent Escort Service Pune
VIP Call Girls Pune Madhuri 8617697112 Independent Escort Service PuneVIP Call Girls Pune Madhuri 8617697112 Independent Escort Service Pune
VIP Call Girls Pune Madhuri 8617697112 Independent Escort Service PuneCall girls in Ahmedabad High profile
 
Russian Call Girls in Kolkata Samaira 🤌 8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Samaira 🤌  8250192130 🚀 Vip Call Girls KolkataRussian Call Girls in Kolkata Samaira 🤌  8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Samaira 🤌 8250192130 🚀 Vip Call Girls Kolkataanamikaraghav4
 
Low Rate Call Girls Kolkata Avani 🤌 8250192130 🚀 Vip Call Girls Kolkata
Low Rate Call Girls Kolkata Avani 🤌  8250192130 🚀 Vip Call Girls KolkataLow Rate Call Girls Kolkata Avani 🤌  8250192130 🚀 Vip Call Girls Kolkata
Low Rate Call Girls Kolkata Avani 🤌 8250192130 🚀 Vip Call Girls Kolkataanamikaraghav4
 
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts serviceChennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts servicevipmodelshub1
 
Call Girls in East Of Kailash 9711199171 Delhi Enjoy Call Girls With Our Escorts
Call Girls in East Of Kailash 9711199171 Delhi Enjoy Call Girls With Our EscortsCall Girls in East Of Kailash 9711199171 Delhi Enjoy Call Girls With Our Escorts
Call Girls in East Of Kailash 9711199171 Delhi Enjoy Call Girls With Our Escortsindian call girls near you
 

Recently uploaded (20)

Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
 
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call GirlVIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
 
AlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with FlowsAlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with Flows
 
Denver Web Design brochure for public viewing
Denver Web Design brochure for public viewingDenver Web Design brochure for public viewing
Denver Web Design brochure for public viewing
 
How is AI changing journalism? (v. April 2024)
How is AI changing journalism? (v. April 2024)How is AI changing journalism? (v. April 2024)
How is AI changing journalism? (v. April 2024)
 
On Starlink, presented by Geoff Huston at NZNOG 2024
On Starlink, presented by Geoff Huston at NZNOG 2024On Starlink, presented by Geoff Huston at NZNOG 2024
On Starlink, presented by Geoff Huston at NZNOG 2024
 
FULL ENJOY Call Girls In Mayur Vihar Delhi Contact Us 8377087607
FULL ENJOY Call Girls In Mayur Vihar Delhi Contact Us 8377087607FULL ENJOY Call Girls In Mayur Vihar Delhi Contact Us 8377087607
FULL ENJOY Call Girls In Mayur Vihar Delhi Contact Us 8377087607
 
Model Call Girl in Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in  Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝Model Call Girl in  Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝
 
VIP Kolkata Call Girl Dum Dum 👉 8250192130 Available With Room
VIP Kolkata Call Girl Dum Dum 👉 8250192130  Available With RoomVIP Kolkata Call Girl Dum Dum 👉 8250192130  Available With Room
VIP Kolkata Call Girl Dum Dum 👉 8250192130 Available With Room
 
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)
A Good Girl's Guide to Murder (A Good Girl's Guide to Murder, #1)
 
Russian Call Girls Thane Swara 8617697112 Independent Escort Service Thane
Russian Call Girls Thane Swara 8617697112 Independent Escort Service ThaneRussian Call Girls Thane Swara 8617697112 Independent Escort Service Thane
Russian Call Girls Thane Swara 8617697112 Independent Escort Service Thane
 
Networking in the Penumbra presented by Geoff Huston at NZNOG
Networking in the Penumbra presented by Geoff Huston at NZNOGNetworking in the Penumbra presented by Geoff Huston at NZNOG
Networking in the Penumbra presented by Geoff Huston at NZNOG
 
VIP Call Girls Pune Madhuri 8617697112 Independent Escort Service Pune
VIP Call Girls Pune Madhuri 8617697112 Independent Escort Service PuneVIP Call Girls Pune Madhuri 8617697112 Independent Escort Service Pune
VIP Call Girls Pune Madhuri 8617697112 Independent Escort Service Pune
 
Rohini Sector 22 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 22 Call Girls Delhi 9999965857 @Sabina Saikh No AdvanceRohini Sector 22 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 22 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
 
Russian Call Girls in Kolkata Samaira 🤌 8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Samaira 🤌  8250192130 🚀 Vip Call Girls KolkataRussian Call Girls in Kolkata Samaira 🤌  8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Samaira 🤌 8250192130 🚀 Vip Call Girls Kolkata
 
Low Rate Call Girls Kolkata Avani 🤌 8250192130 🚀 Vip Call Girls Kolkata
Low Rate Call Girls Kolkata Avani 🤌  8250192130 🚀 Vip Call Girls KolkataLow Rate Call Girls Kolkata Avani 🤌  8250192130 🚀 Vip Call Girls Kolkata
Low Rate Call Girls Kolkata Avani 🤌 8250192130 🚀 Vip Call Girls Kolkata
 
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts serviceChennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Alwarpet Phone 🍆 8250192130 👅 celebrity escorts service
 
Call Girls in East Of Kailash 9711199171 Delhi Enjoy Call Girls With Our Escorts
Call Girls in East Of Kailash 9711199171 Delhi Enjoy Call Girls With Our EscortsCall Girls in East Of Kailash 9711199171 Delhi Enjoy Call Girls With Our Escorts
Call Girls in East Of Kailash 9711199171 Delhi Enjoy Call Girls With Our Escorts
 
Rohini Sector 6 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 6 Call Girls Delhi 9999965857 @Sabina Saikh No AdvanceRohini Sector 6 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 6 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
 
Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No AdvanceRohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
 

Is it time to write unit tests?

  • 1. Why we are (not) writing tests in iOS apps by Paul Taykalo, MacPaw To write or not to write, by Paul Taykalo, #MacPaw 1
  • 2. Plan To write or not to write, by Paul Taykalo, #MacPaw 2
  • 3. Plan » Tests vs No "Tests" Fractions » Tests are not needed » Need are needed » I'm trying, but failing » Aren't we testing already? » Pivot point » How not to write tests with success To write or not to write, by Paul Taykalo, #MacPaw 3
  • 4. Tests No-Tests Some-Tests Groups To write or not to write, by Paul Taykalo, #MacPaw 4
  • 5. Tests arent't needed » My grandpa hasn't run a test » Waste of time » Just write correct code » No time » ??? To write or not to write, by Paul Taykalo, #MacPaw 5
  • 6. To write or not to write, by Paul Taykalo, #MacPaw 6
  • 7. Test all the things » It's only the right way to do it » No tests - no feature To write or not to write, by Paul Taykalo, #MacPaw 7
  • 8. Some-Tests To write or not to write, by Paul Taykalo, #MacPaw 8
  • 9. Aren't we testing already? To write or not to write, by Paul Taykalo, #MacPaw 9
  • 10. Aren't we testing already? » Debugging » Logging » QAs » End users To write or not to write, by Paul Taykalo, #MacPaw 10
  • 11. Testing is hard To write or not to write, by Paul Taykalo, #MacPaw 11
  • 12. Testing is hard » Big/Small » Very hard integration » We don't actually know how » Boring » Next time » Ther's no time atm To write or not to write, by Paul Taykalo, #MacPaw 12
  • 13. We aren't writing tests. We were writing tests, but they were too fragile, and they were breaking for no reason, so we decided not to — Unknown programmer To write or not to write, by Paul Taykalo, #MacPaw 13
  • 14. Every time new OS released, all my snapshot tests are broken. It's not worth it — Unknown programmer To write or not to write, by Paul Taykalo, #MacPaw 14
  • 15. Testing is easy To write or not to write, by Paul Taykalo, #MacPaw 15
  • 16. Testing is easy » Tests already setup » Intro/PR/Review » No commits without Tests ¯_( )_/¯ » It is not fixed unless there's a test To write or not to write, by Paul Taykalo, #MacPaw 16
  • 17. Why is there so big difference? To write or not to write, by Paul Taykalo, #MacPaw 17
  • 18. Starting Test is hard To write or not to write, by Paul Taykalo, #MacPaw 18
  • 19. To write or not to write, by Paul Taykalo, #MacPaw 19
  • 20. When do we start thinking about tests? To write or not to write, by Paul Taykalo, #MacPaw 20
  • 21. Slowing down To write or not to write, by Paul Taykalo, #MacPaw 21
  • 22. Slowing down » Not sure everything is fine » R-word (Regression) » Fixing bugs time >> Feature time To write or not to write, by Paul Taykalo, #MacPaw 22
  • 23. Slowing down » No knowledge » Huge base » Different integrations M*N » Code base/complexity » Team change » Same time expectation To write or not to write, by Paul Taykalo, #MacPaw 23
  • 24. We've slowed down To write or not to write, by Paul Taykalo, #MacPaw 24
  • 25. What did we wrong? To write or not to write, by Paul Taykalo, #MacPaw 25
  • 26. What did we wrong? To write or not to write, by Paul Taykalo, #MacPaw 26
  • 27. What did we wrong? To write or not to write, by Paul Taykalo, #MacPaw 27
  • 28. What did we wrong? To write or not to write, by Paul Taykalo, #MacPaw 28
  • 29. Time to add tests? To write or not to write, by Paul Taykalo, #MacPaw 29
  • 30. Tests Expectations vs reality To write or not to write, by Paul Taykalo, #MacPaw 30
  • 31. Tests Expectations vs reality To write or not to write, by Paul Taykalo, #MacPaw 31
  • 32. I added tests they didn't help — Unknown programmer To write or not to write, by Paul Taykalo, #MacPaw 32
  • 33. Tests are not a cure Tests are the insurance To write or not to write, by Paul Taykalo, #MacPaw 33
  • 34. I spent weeks trying to test UI and failed all deadlines — Unknown programmer To write or not to write, by Paul Taykalo, #MacPaw 34
  • 35. Some parts are really hard to test Deal with it To write or not to write, by Paul Taykalo, #MacPaw 35
  • 36. There are a lot of tests, but the code doesn't seem to be better — Unknown programmer To write or not to write, by Paul Taykalo, #MacPaw 36
  • 37. Tests won't make your code significantly better* To write or not to write, by Paul Taykalo, #MacPaw 37
  • 38. You still can write ugly code To write or not to write, by Paul Taykalo, #MacPaw 38
  • 39. Your tests can be ugly as well To write or not to write, by Paul Taykalo, #MacPaw 39
  • 40. The Good, The Bad and The Ugly To write or not to write, by Paul Taykalo, #MacPaw 40
  • 41. The Bad To write or not to write, by Paul Taykalo, #MacPaw 41
  • 42. The Bad func testImtheS() { let url = "http://agileinaflash.com/feeds/posts/default" let content = Data(withContensOfURL:URL(string:url))! XCTAssertNotNil(content) let parsedContent = parse(content)! let rss = RSS(from: parsedContent)! XCTAssertEqual(rss.title, title) } To write or not to write, by Paul Taykalo, #MacPaw 42
  • 43. The Bad func testImtheS() { let url = "http://agileinaflash.com/feeds/posts/default" let content = Data(withContensOfURL:URL(string:url))! XCTAssertNotNil(content) let parsedContent = parse(content)! let rss = RSS(from: parsedContent)! XCTAssertEqual(rss.title, title) } To write or not to write, by Paul Taykalo, #MacPaw 43
  • 44. The Bad func testImtheS() { let url = "http://agileinaflash.com/feeds/posts/default" let content = Data(withContensOfURL:URL(string:url))! XCTAssertNotNil(content) let parsedContent = parse(content)! let rss = RSS(from: parsedContent)! XCTAssertEqual(rss.title, title) } To write or not to write, by Paul Taykalo, #MacPaw 44
  • 45. The Bad func testImtheS() { let url = "http://agileinaflash.com/feeds/posts/default" let content = Data(withContensOfURL:URL(string:url))! XCTAssertNotNil(content) let parsedContent = parse(content)! let rss = RSS(from: parsedContent)! XCTAssertEqual(rss.title, title) } To write or not to write, by Paul Taykalo, #MacPaw 45
  • 46. The Ugly To write or not to write, by Paul Taykalo, #MacPaw 46
  • 47. The Ugly func testEncoding() { let path = "Foo/Bar/Baz" let info = ["Key": "Hello World"] let request1 = XPCRequest(path: path, info: info) let data1 = request1.encode() let decoded1 = XPCRequest(with: data1)! XCTAssertEqual(request1.path, decoded1.path) XCTAssertTrue(NSDictionary(dictionary: request1.info!).isEqual(to: decoded1.info!)) let request2 = XPCRequest(path: path, info: nil) let data2 = request2.encode() let decoded2 = XPCRequest(with: data2)! XCTAssertEqual(request2.path, decoded2.path) XCTAssertNil(request2.info) } To write or not to write, by Paul Taykalo, #MacPaw 47
  • 48. The Ugly func testMenuItemCreated() throws { let simulatedClickedRow = 7 let simulatedItems = ["Hello", " World!"] let mapperExpectation = expectation(description: "mapper should be called") let mapper: ([Any]) -> [String]? = { objects in mapperExpectation.fulfill() return objects as? [String] } let formatExpectation = expectation(description: "format should be called") let format: ([String], Int, Localization.Type) -> String? = { strings, clickedRow, localization in formatExpectation.fulfill() XCTAssertEqual(strings, simulatedItems) XCTAssertEqual(clickedRow, simulatedClickedRow) return strings.reduce("") { $0 + $1 } } let action: ([String], Int) -> Void = { _, _ in } let keyEquivalent: String = "Key" let builder = MenuItemBuilder<String>(keyEquivalent: keyEquivalent, mapper: mapper, format: format, action: action) let menuItem = try require(builder.item(from: simulatedItems, with: simulatedClickedRow)) XCTAssertEqual(menuItem.keyEquivalent, keyEquivalent) XCTAssertEqual(menuItem.title, "Hello World!") waitForExpectations(timeout: 0.0) { error in XCTAssertFalse(error != nil) } } To write or not to write, by Paul Taykalo, #MacPaw 48
  • 49. The Good To write or not to write, by Paul Taykalo, #MacPaw 49
  • 50. F. I. R. S. T. To write or not to write, by Paul Taykalo, #MacPaw 50
  • 51. F. I. R. S. T. » Fast — tests should be able to be executed often. » Isolated — tests on their own cannot depend on external factors or on the result of another test. » Repeatable — tests should have the same result every time we run them.(*) » Self-verifying — tests should include assertions; no human intervention needed. » Timely — tests should be written along with the production To write or not to write, by Paul Taykalo, #MacPaw 51
  • 52. The Good - (void)testAddMalwareInformationCanBeReadFromDataBase { // Given TestMalwareInfo info = [self.knowledgeBase _addMalwareInfo]; // When NSDictionary *malwareInfo = [self.knowledgeBase malwareInfoForItem:nil hash:info.hash]; // Then XCTAssertEqualObjects(malwareInfo[CMMalwareInfoKeyName], info.name); XCTAssertEqualObjects(malwareInfo[CMMalwareInfoKeyType], info.type); } To write or not to write, by Paul Taykalo, #MacPaw 52
  • 53. The Good - (void)testMalwareDetectionTasksReturnsMalwareModels { // Given MPFileSizerMockWithStubbedAnyPath(^(MPFileSize size) { CMMalwaresDetectionTask * sut = [self _sutWithItemsCount:3 malwaresCount:2]; // When CMScanResult *result = [sut scan]; CMEntity *entity = [result.items firstObject]; // Then XCTAssertTrue([entity isKindOfClass:[CMMalwareModel class]]); });} To write or not to write, by Paul Taykalo, #MacPaw 53
  • 54. The Good - (void)testMalwareDetectionTasksReturnsMalwareModels { // Given MPFileSizerMockWithStubbedAnyPath(^(MPFileSize size) { CMMalwaresDetectionTask * sut = [self _sutWithItemsCount:3 malwaresCount:2]; // When CMScanResult *result = [sut scan]; CMEntity *entity = [result.items firstObject]; // Then XCTAssertTrue([entity isKindOfClass:[CMMalwareModel class]]); });} To write or not to write, by Paul Taykalo, #MacPaw 54
  • 55. The Good - (void)testMalwareDetectionTasksReturnsMalwareModels { // Given MPFileSizerMockWithStubbedAnyPath(^(MPFileSize size) { CMMalwaresDetectionTask * sut = [self _sutWithItemsCount:3 malwaresCount:2]; // When CMScanResult *result = [sut scan]; CMEntity *entity = [result.items firstObject]; // Then XCTAssertTrue([entity isKindOfClass:[CMMalwareModel class]]); });} To write or not to write, by Paul Taykalo, #MacPaw 55
  • 56. The Good - (void)testMalwareDetectionTasksReturnsMalwareModels { // Given MPFileSizerMockWithStubbedAnyPath(^(MPFileSize size) { CMMalwaresDetectionTask * sut = [self _sutWithItemsCount:3 malwaresCount:2]; // When CMScanResult *result = [sut scan]; CMEntity *entity = [result.items firstObject]; // Then XCTAssertTrue([entity isKindOfClass:[CMMalwareModel class]]); });} To write or not to write, by Paul Taykalo, #MacPaw 56
  • 57. Why aren't we writing tests? To write or not to write, by Paul Taykalo, #MacPaw 57
  • 58. Why aren't we writing tests? » Too small (project) » Simple project » Clear code » No complaints from product owner/users To write or not to write, by Paul Taykalo, #MacPaw 58
  • 59. Some tips for those who doesn't write tests To write or not to write, by Paul Taykalo, #MacPaw 59
  • 60. Some tips for those who doesn't write tests To write or not to write, by Paul Taykalo, #MacPaw 60
  • 61. Don't show/require all data YAGNI struct User { let id: String let name: String let address: String let friends: [User] let dogName: String? let hairStyle: HairStyle ... } To write or not to write, by Paul Taykalo, #MacPaw 61
  • 62. Own Data layer Layer things out class AppApi { func getUser(by id: String) -> SignalProducer<User, AppApiError> } To write or not to write, by Paul Taykalo, #MacPaw 62
  • 63. Layer things out enum AppApiError: Error { case userNotLoggedIn case serverFeelsBad case subscriptionEnded case unknown(NetworkError) // } To write or not to write, by Paul Taykalo, #MacPaw 63
  • 64. Layer things out // Struct for showing error imeediately to the user struct UserError { let title: String let message: String // just in some really rare cases let underlyingError: Error } To write or not to write, by Paul Taykalo, #MacPaw 64
  • 65. Don't allow invalid data struct UserForm { let id: String? let name: String? let lastName: String? } struct User { let id: String let name: String let lastName: String } To write or not to write, by Paul Taykalo, #MacPaw 65
  • 66. Isolate Order Dependent Code dataSource.addItems(["1","2","3") tableView.insertItems(at indexPaths:[IndexPath]) tableView.deleteItems(at indexPaths:[]) tableView.reloadData() To write or not to write, by Paul Taykalo, #MacPaw 66
  • 67. Semantic meaning if itemsCount > 4 if user.rating > 200 && user.userName.isNotEmpty if view.tag == 13 To write or not to write, by Paul Taykalo, #MacPaw 67
  • 68. Unidirectional data flow To write or not to write, by Paul Taykalo, #MacPaw 68
  • 69. Linear code loginUser(onSuccess: { user in getAllImages(for: user, onSuccess: { images is verify(images: images, onSuccess: { verified, unverified is verifyDeletion(images: unverified, onSuccess: { shouldDelete in }, onFailure: { // TODO Handle it print(error) }) }, onFailure: { // TODO Handle it print(error) }) }, onFailure: { // TODO Handle it print(error) }) }, onFailure: { // TODO Handle it print(error) }) To write or not to write, by Paul Taykalo, #MacPaw 69
  • 70. Linear code loggeduserRequest .flatMap(.latest, { user in getAllimages(for: user)}) .flatMap(.latest, { images in verify(images: images)}) .flatMap { verified, unverified in askForDeletion(images: unverified)} .filter { shouldDelete in deleteImages(shouldDelete) } To write or not to write, by Paul Taykalo, #MacPaw 70
  • 71. Linear code loggeduserRequest .flatMap(.latest, getAllimages) .flatMap(.latest, verify) .flatMap { verified, unverified in askForDeletion(images: unverified)} .filter(deleteImages) To write or not to write, by Paul Taykalo, #MacPaw 71
  • 72. Non failable code file.open() guard something else { file.close(); return} file.read() file.close() To write or not to write, by Paul Taykalo, #MacPaw 72
  • 73. Non failable code extension File { func opened(process: (File -> Void)) { open() process(self) close(); } } file.opened { f in guard something else { return } f.read() } To write or not to write, by Paul Taykalo, #MacPaw 73
  • 74. Decrease amount of possible states » Optionals » BFO (Object) » Exponential number of states » Mutability To write or not to write, by Paul Taykalo, #MacPaw 74
  • 75. Some tips for those who doesn't write tests » Don't show/require all data » Layer things out » Don't allow invalid data » Semantic meaning » Linear flow » Decrease amount of possible states To write or not to write, by Paul Taykalo, #MacPaw 75
  • 76. More tips for those who doesn't write tests To write or not to write, by Paul Taykalo, #MacPaw 76
  • 77. More tips for those who doesn't write tests » Visual snapshots » Revealing hidden info (i.e. Analytics) » Logs To write or not to write, by Paul Taykalo, #MacPaw 77
  • 78. How (not) to fail adding tests To write or not to write, by Paul Taykalo, #MacPaw 78
  • 79. How (not) to fail adding tests » Read a lot about testing and types of testing » Try to test-first, try to test-last » Determine your core » Isolate features and test them » Start with Unit tests » For Custom UI you can run snapshot testing » Hire someone and let them help you To write or not to write, by Paul Taykalo, #MacPaw 79
  • 80. Te$t$ To write or not to write, by Paul Taykalo, #MacPaw 80
  • 81. - I won't pay additionally for tests - But there'll be bugs - They'll be there even if you write tests! To write or not to write, by Paul Taykalo, #MacPaw 81
  • 82. Tests readiness To write or not to write, by Paul Taykalo, #MacPaw 82
  • 83. There are many ways to write an application. We're not building spaceships, you know? — Unknown programmer To write or not to write, by Paul Taykalo, #MacPaw 83
  • 84. Thank you To write or not to write, by Paul Taykalo, #MacPaw 84
  • 85. Q & A To write or not to write, by Paul Taykalo, #MacPaw 85
  • 86. Why we are (not) writing tests in iOS apps by Paul Taykalo, MacPaw @TT_Kilew To write or not to write, by Paul Taykalo, #MacPaw 86
  • 87. The end To write or not to write, by Paul Taykalo, #MacPaw 87
  • 88. Bonus Building a Swift Quiz App with TDD and Modular Design https://goo.gl/cUzTkr To write or not to write, by Paul Taykalo, #MacPaw 88
  • 90. More links https://medium.com/essential-developer-ios To write or not to write, by Paul Taykalo, #MacPaw 90