SlideShare uma empresa Scribd logo
1 de 90
Baixar para ler 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

Mais conteúdo relacionado

Semelhante a 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
 

Semelhante a 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
 

Mais de 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
 

Mais de 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...
 

Último

Top Rated Pune Call Girls Daund ⟟ 6297143586 ⟟ Call Me For Genuine Sex Servi...
Top Rated  Pune Call Girls Daund ⟟ 6297143586 ⟟ Call Me For Genuine Sex Servi...Top Rated  Pune Call Girls Daund ⟟ 6297143586 ⟟ Call Me For Genuine Sex Servi...
Top Rated Pune Call Girls Daund ⟟ 6297143586 ⟟ Call Me For Genuine Sex Servi...Call Girls in Nagpur High Profile
 
Call Girls In Model Towh Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Model Towh Delhi 💯Call Us 🔝8264348440🔝Call Girls In Model Towh Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Model Towh Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
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
 
Russian Call girl in Ajman +971563133746 Ajman Call girl Service
Russian Call girl in Ajman +971563133746 Ajman Call girl ServiceRussian Call girl in Ajman +971563133746 Ajman Call girl Service
Russian Call girl in Ajman +971563133746 Ajman Call girl Servicegwenoracqe6
 
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...APNIC
 
₹5.5k {Cash Payment}New Friends Colony Call Girls In [Delhi NIHARIKA] 🔝|97111...
₹5.5k {Cash Payment}New Friends Colony Call Girls In [Delhi NIHARIKA] 🔝|97111...₹5.5k {Cash Payment}New Friends Colony Call Girls In [Delhi NIHARIKA] 🔝|97111...
₹5.5k {Cash Payment}New Friends Colony Call Girls In [Delhi NIHARIKA] 🔝|97111...Diya Sharma
 
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779Delhi Call girls
 
Russian Call girls in Dubai +971563133746 Dubai Call girls
Russian  Call girls in Dubai +971563133746 Dubai  Call girlsRussian  Call girls in Dubai +971563133746 Dubai  Call girls
Russian Call girls in Dubai +971563133746 Dubai Call girlsstephieert
 
✂️ 👅 Independent Andheri Escorts With Room Vashi Call Girls 💃 9004004663
✂️ 👅 Independent Andheri Escorts With Room Vashi Call Girls 💃 9004004663✂️ 👅 Independent Andheri Escorts With Room Vashi Call Girls 💃 9004004663
✂️ 👅 Independent Andheri Escorts With Room Vashi Call Girls 💃 9004004663Call Girls Mumbai
 
Call Girls In Pratap Nagar Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Pratap Nagar Delhi 💯Call Us 🔝8264348440🔝Call Girls In Pratap Nagar Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Pratap Nagar Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine ServiceHot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Servicesexy call girls service in goa
 
SEO Growth Program-Digital optimization Specialist
SEO Growth Program-Digital optimization SpecialistSEO Growth Program-Digital optimization Specialist
SEO Growth Program-Digital optimization SpecialistKHM Anwar
 
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Moving Beyond Twitter/X and Facebook - Social Media for local news providers
Moving Beyond Twitter/X and Facebook - Social Media for local news providersMoving Beyond Twitter/X and Facebook - Social Media for local news providers
Moving Beyond Twitter/X and Facebook - Social Media for local news providersDamian Radcliffe
 
Radiant Call girls in Dubai O56338O268 Dubai Call girls
Radiant Call girls in Dubai O56338O268 Dubai Call girlsRadiant Call girls in Dubai O56338O268 Dubai Call girls
Radiant Call girls in Dubai O56338O268 Dubai Call girlsstephieert
 
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
 
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Call Girls in Mayur Vihar ✔️ 9711199171 ✔️ Delhi ✔️ Enjoy Call Girls With Our...
Call Girls in Mayur Vihar ✔️ 9711199171 ✔️ Delhi ✔️ Enjoy Call Girls With Our...Call Girls in Mayur Vihar ✔️ 9711199171 ✔️ Delhi ✔️ Enjoy Call Girls With Our...
Call Girls in Mayur Vihar ✔️ 9711199171 ✔️ Delhi ✔️ Enjoy Call Girls With Our...sonatiwari757
 

Último (20)

Top Rated Pune Call Girls Daund ⟟ 6297143586 ⟟ Call Me For Genuine Sex Servi...
Top Rated  Pune Call Girls Daund ⟟ 6297143586 ⟟ Call Me For Genuine Sex Servi...Top Rated  Pune Call Girls Daund ⟟ 6297143586 ⟟ Call Me For Genuine Sex Servi...
Top Rated Pune Call Girls Daund ⟟ 6297143586 ⟟ Call Me For Genuine Sex Servi...
 
Call Girls In Model Towh Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Model Towh Delhi 💯Call Us 🔝8264348440🔝Call Girls In Model Towh Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Model Towh Delhi 💯Call Us 🔝8264348440🔝
 
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)
 
Russian Call girl in Ajman +971563133746 Ajman Call girl Service
Russian Call girl in Ajman +971563133746 Ajman Call girl ServiceRussian Call girl in Ajman +971563133746 Ajman Call girl Service
Russian Call girl in Ajman +971563133746 Ajman Call girl Service
 
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
 
₹5.5k {Cash Payment}New Friends Colony Call Girls In [Delhi NIHARIKA] 🔝|97111...
₹5.5k {Cash Payment}New Friends Colony Call Girls In [Delhi NIHARIKA] 🔝|97111...₹5.5k {Cash Payment}New Friends Colony Call Girls In [Delhi NIHARIKA] 🔝|97111...
₹5.5k {Cash Payment}New Friends Colony Call Girls In [Delhi NIHARIKA] 🔝|97111...
 
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
 
Russian Call girls in Dubai +971563133746 Dubai Call girls
Russian  Call girls in Dubai +971563133746 Dubai  Call girlsRussian  Call girls in Dubai +971563133746 Dubai  Call girls
Russian Call girls in Dubai +971563133746 Dubai Call girls
 
✂️ 👅 Independent Andheri Escorts With Room Vashi Call Girls 💃 9004004663
✂️ 👅 Independent Andheri Escorts With Room Vashi Call Girls 💃 9004004663✂️ 👅 Independent Andheri Escorts With Room Vashi Call Girls 💃 9004004663
✂️ 👅 Independent Andheri Escorts With Room Vashi Call Girls 💃 9004004663
 
Call Girls In Pratap Nagar Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Pratap Nagar Delhi 💯Call Us 🔝8264348440🔝Call Girls In Pratap Nagar Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Pratap Nagar Delhi 💯Call Us 🔝8264348440🔝
 
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
 
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine ServiceHot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
 
SEO Growth Program-Digital optimization Specialist
SEO Growth Program-Digital optimization SpecialistSEO Growth Program-Digital optimization Specialist
SEO Growth Program-Digital optimization Specialist
 
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
 
Moving Beyond Twitter/X and Facebook - Social Media for local news providers
Moving Beyond Twitter/X and Facebook - Social Media for local news providersMoving Beyond Twitter/X and Facebook - Social Media for local news providers
Moving Beyond Twitter/X and Facebook - Social Media for local news providers
 
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
 
Radiant Call girls in Dubai O56338O268 Dubai Call girls
Radiant Call girls in Dubai O56338O268 Dubai Call girlsRadiant Call girls in Dubai O56338O268 Dubai Call girls
Radiant Call girls in Dubai O56338O268 Dubai Call girls
 
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
 
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
 
Call Girls in Mayur Vihar ✔️ 9711199171 ✔️ Delhi ✔️ Enjoy Call Girls With Our...
Call Girls in Mayur Vihar ✔️ 9711199171 ✔️ Delhi ✔️ Enjoy Call Girls With Our...Call Girls in Mayur Vihar ✔️ 9711199171 ✔️ Delhi ✔️ Enjoy Call Girls With Our...
Call Girls in Mayur Vihar ✔️ 9711199171 ✔️ Delhi ✔️ Enjoy Call Girls With Our...
 

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