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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Ronan Rodrigo Nunes
November 29, 2021
Programming
120
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
80
Testes - A que será que se destina?
ronanrodrigo
1
150
Métodos, Técnicas e Ferramentas de Desenvolvimento de Software
ronanrodrigo
1
64
Uma decisão pode custar caro
ronanrodrigo
1
160
Crie aplicativos adiando decisões
ronanrodrigo
0
50
Por que eu criei uma biblioteca Open Source?
ronanrodrigo
0
160
Com quantas views se faz uma APP?
ronanrodrigo
0
80
VIPER - Arquitetura limpa em nossos APPs
ronanrodrigo
1
710
Other Decks in Programming
See All in Programming
SkillがSkillを生む:QA観点出しを自動化した
sontixyou
4
2.4k
Migration to Signals, Signal Forms, Resource API, and NgRx Signal Store @Angular Days 03/2026 Munich
manfredsteyer
PRO
0
230
AI時代の脳疲弊と向き合う ~言語学としてのPHP~
sakuraikotone
1
1.8k
ローカルで稼働するAI エージェントを超えて / beyond-local-ai-agents
gawa
1
240
Claude Codeログ基盤の構築
giginet
PRO
7
3.9k
AIコードレビューの導入・運用と AI駆動開発における「AI4QA」の取り組みについて
hagevvashi
0
600
Everything Claude Code OSS詳細 — 5層構造の中身と導入方法
targe
0
160
レガシーPHP転生 〜父がドメインエキスパートだったのでDDD+Claude Codeでチート開発します〜
panda_program
0
190
煩雑なSkills管理をSoC(関心の分離)により解決する――関心を分離し、プロンプトを部品として育てるためのOSSを作った話 / Solving Complex Skills Management Through SoC (Separation of Concerns)
nrslib
3
360
Mastering Event Sourcing: Your Parents Holidayed in Yugoslavia
super_marek
0
140
安いハードウェアでVulkan
fadis
1
880
一度始めたらやめられない開発効率向上術 / Findy あなたのdotfilesを教えて!
k0kubun
4
2.8k
Featured
See All Featured
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
230
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
1.8k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
1k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
2.7k
Navigating Team Friction
lara
192
16k
Evolving SEO for Evolving Search Engines
ryanjones
0
170
WENDY [Excerpt]
tessaabrams
9
37k
The SEO identity crisis: Don't let AI make you average
varn
0
430
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