Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Testes_-_A_que_será_que_se_destina__-_V2.pdf
Search
Ronan Rodrigo Nunes
November 29, 2021
Programming
130
0
Share
Testes_-_A_que_será_que_se_destina__-_V2.pdf
Ronan Rodrigo Nunes
November 29, 2021
More Decks by Ronan Rodrigo Nunes
See All by Ronan Rodrigo Nunes
Audio Capture
ronanrodrigo
0
83
Testes - A que será que se destina?
ronanrodrigo
1
150
Métodos, Técnicas e Ferramentas de Desenvolvimento de Software
ronanrodrigo
1
67
Uma decisão pode custar caro
ronanrodrigo
1
160
Crie aplicativos adiando decisões
ronanrodrigo
0
52
Por que eu criei uma biblioteca Open Source?
ronanrodrigo
0
160
Com quantas views se faz uma APP?
ronanrodrigo
0
84
VIPER - Arquitetura limpa em nossos APPs
ronanrodrigo
1
720
Other Decks in Programming
See All in Programming
Don't Prompt Harder, Structure Better
kitasuke
0
800
Spec-Driven Development with AI Agents (Workshop, May 2026)
antonarhipov
2
230
Spec Driven Development | AI Summit Vilnius
danielsogl
PRO
1
130
PCOVから学ぶコードカバレッジ #phpcon_odawara
o0h
PRO
0
290
2026_04_15_量子計算をパズルとして解く
hideakitakechi
0
130
2026-04-15 Spring IO - I Can See Clearly Now
jonatan_ivanov
1
150
mruby on C#: From VM Implementation to Game Scripting (RubyKaigi 2026)
hadashia
2
1.4k
Symfony AI in Action - SymfonyLive Berlin 2026
chr_hertel
1
110
Explore CoroutineScope
tomoeng11
0
140
「Linuxサーバー構築標準教科書」を読んでみた #ツナギメオフライン.7
akase244
0
1.4k
書籍「ユーザーストーリーマッピング」が私のバイブル
asumikam
4
460
Liberating Ruby's Parser from Lexer Hacks
ydah
2
2.4k
Featured
See All Featured
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
380
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
120
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
190
Building Flexible Design Systems
yeseniaperezcruz
330
40k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
180
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
330
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.1k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
180
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.7k
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
1
530
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
9.9k
Transcript
Testes: A que será que se destina? Breve história sobre
testes, boas e más práticas no ecossistema Apple Ronan Rodrigo Nunes
Arqueologia
None
None
2005 Xcode 2.1 OCUnit 2013 Xcode 5.0 XCTest 2015 Xcode
7.0 XCUITest
Cultura
None
Não vejo benefício “
Meu código funciona perfeitamente, por que eu testaria? “
Até APP com testes tem bugs “
Até APP com testes tem bugs “
Não sei como, nem o que testar “
Não sei como, nem o que testar “ classona classinha
extrair injetar testar ✔
Não temos tempo “
É difícil e complicado “
Meu time não tem a cultura de testar “ mobster.cc
O que ganho com isso?
👃 Cheiro de que?
🏰 Arquitete-se
🧘 Equilibrio
⛹ Domínio
✍ Documentação
Boas práticas & Smells & Armadilhas
func test_primaryButtonTapped_doesRouteToFullSheet() { // given XCTAssertTrue(router.routeToFullSheetCallCount == 0) // when
interactor.primaryButtonTapped() // then XCTAssertTrue(router.routeToFullSheetCallCount == 1) } ✘
func test_primaryButtonTapped_doesRouteToFullSheet() { XCTAssertTrue(router.routeToFullSheetCallCount == 0) interactor.primaryButtonTapped() XCTAssertTrue(router.routeToFullSheetCallCount == 1)
} ✘
func test_primaryButtonTapped_doesRouteToFullSheet() { interactor.primaryButtonTapped() XCTAssertTrue(router.routeToFullSheetCallCount == 1) } ✘
func test_primaryButtonTapped_doesRouteToFullSheet() { interactor.primaryButtonTapped() XCTAssertEqual(router.routeToFullSheetCallCount, 1) } ✔︎
func test_startReport_doesRouteToReportFlow() { interactor.startReport() XCTAssertEqual(router.routeToReportFlowCallCount, 1) } ✔︎
func test_allByMonth_existingMonth_callCompletionWithItems() { var expectedGroupedFoods: [GroupedFoods]? // ... guard let
expectedGroupedFoods = expectedGroupedFoods, firstGroup = expectedGroupedFoods.first else { XCTFail("empty expectedGroupedFoods") } XCTAssertFalse(firstGroup.foods.isEmpty) } ✘
func test_allByMonth_existingMonth_callCompletionWithItems() { var expectedGroupedFoods: [GroupedFoods]? // ... XCTAssertFalse(expectedGroupedFoods!.first!.foods.isEmpty) }
✘
func test_allByMonth_existingMonth_callCompletionWithItems() { var expectedGroupedFoods: [GroupedFoods]? // ... if let
expectedGroupedFoods = expectedGroupedFoods { if let firstGroup = expectedGroupedFoods.first { XCTAssertFalse(firstGroup.foods.isEmpty) } } } ✘
func test_allByMonth_existingMonth_callCompletionWithItems() { var expectedGroupedFoods: [GroupedFoods]? // ... XCTAssertEqual(expectedGroupedFoods?.first?.foods.isEmpty, false)
XCTAssertEqual(expectedGroupedFoods?.first?.foods.count, 4) } ✔︎
func test_allByMonth_existingMonth_callCompletionWithItems() { var expectedGroupedFoods: [GroupedFoods]? let month = MonthGatewayFactory.make().month(number:
1) gateway.all(byMonth: month) { expectedGroupedFoods = $0.data } XCTAssertEqual(expectedGroupedFoods?.isEmpty, false) } ✘
func test_allByMonth_existingMonth_callCompletionWithItems() { var expectedGroupedFoods: [GroupedFoods]? let month = MonthGatewayFactory.make().month(number:
1) gateway.all(byMonth: month) { expectedGroupedFoods = $0.data } XCTAssertEqual(expectedGroupedFoods?.isEmpty, false) } ✔︎
func test_finishReport_completeFlow() { var completed = false interactor.myEventStream().subscribe { _
in completed = true } .disposed(by: disposeBag) interactor.finish() XCTAssertTrue(completed) } ✘
func test_finishReport_completeFlow() { var completed = false onCompleteFlow(completed = true)
interactor.finish() XCTAssertTrue(completed) } func onCompleteFlow(_ fn: @escaping @autoclosure () -> ()) { interactor.myEventStream() .subscribe { _ in fn() } .disposeOnTearDown(testCase: self) } ✔︎
class ReportTripInteractorTests: XCTestCase class ReportTripInteractor_StartTripTests: ReportTripInteractorTests class ReportTripInteractor_FinishingTripTests: ReportTripInteractorTests class
ReportTripInteractor_SearchingTripTests: ReportTripInteractorTests class ReportTripInteractor_WaintingTripTests: ReportTripInteractorTests ✔︎
func test_start_validInteractor_createEventAtStream() { let expectedResponse = Response(uuid: "id") shareService.fetchHandler =
{ _ in .just(expectedResponse) } worker.start(interactor) someStream.dataSubject .subscribe(onNext: { eventResponse in XCTAssertEqual(expectedResponse, eventResponse) }) .disposed(by: disposeBag) } ✘
class Worker { func start(_ interactor: AnyInteractor) { someObservable .subscribe(someStream.dataSubject)
.disposeOnStop(self) } } .subscribe(someStream.dataSubject)
class Worker { func start(_ interactor: AnyInteractor) { someObservable .disposeOnStop(self)
} }
func test_start_validInteractor_createEventAtStream() { let expectedResponse = Response(uuid: "id") shareService.fetchHandler =
{ _ in .just(expectedResponse) } var eventResponse: Response? someStream.dataSubject .subscribe(onNext: { eventResponse = $0 }) .disposed(by: disposeBag) worker.start(interactor) XCTAssertEqual(expectedResponse, eventResponse) } ✔︎
func test_schedule_createEvent() { // ... } ✘
func test_givenMonthExist_whenContainsMeeting_thenCreateEvent() { // ... } func test_monthExist_containsMeeting_createEvent() { //
... } func testScheduleEvent_monthExist_containsMeeting_createEvent() { // ... } func test_itMonthExist_andContainsMeeting_shouldCreateEvent() { // ... } ✔︎
Obrigado
Obrigado ronanrodrigo.dev
Obrigado ronanrodrigo.dev ronanrodrigo.dev/slides