SlideShare a Scribd company logo
1 of 45
Download to read offline
지금 당장 (유사) BDD 시작하기
간단하게 BDD를 적용해보고 기존과 다르게 개발했던 경험
Wanted Live Talk
소개
원티드랩 iOS 개발자
@agiletalk
velog.io/@agiletalk
초보자를 위한 스위프트 8주 완성
TL;DW
• 지금 당장 (유사) BDD 시작하기 확장판
• 실제 프로젝트에서 BDD를 적용했던 경험
• (유사)인 이유는 테스트부터 작성하지 않음
TDD
Test-driven development
TDD
• 🚫 테스트 코드를 작성
• ✅ 구현 코드를 작성
• 🛠 리팩토링 단계
do(TDD!)
do(TDD!)
Fatal error: Unexpectedly found nil while unwrapping on Optional value
BDD
Behavior-driven development
BDD
• Feature: 테스트 대상의 기능/책임을 명시합니다.
• Scenario: 테스트 목적에 대한 상황을 설명합니다.
• Given: 시나리오 진행에 필요한 값을 설정합니다.
• When: 시나리오를 진행하는데 필요한 조건을 명시합니다.
• Then: 시나리오를 완료했을 때 보장해야 하는 결과를 명시합니다.
describe("Given the User repository") {
var userRepository: UserRepository!
beforeEach {
userRepository = UserRepository(mode: .inMemory)
}
context("When a user is saved") {
beforeEach {
userRepository.deleteAll()
userRepository.populateTestUsers()
let user = User()
user.email = "user.test@sampleemail.com"
userRepository.save(user)
}
it("Should be recoverable") {
let recoveredUser = userRepository.findOne(
email: "user.test@sampleemail.com"
)
expect(recoveredUser).toNot(beNil())
}
}
}
Clean Swift
Clean Swift
• ViewController (UI 디자인)
• 뷰 이벤트를 Interactor에 전달, Presenter가 주는 데이터 표시
• Interactor (이벤트 처리)
• 이벤트 처리, 상태 관리, 모든 비즈니스 로직을 담당 / Worker와 협력
• Presenter (ViewModel 생성)
• Interactor에서 받은 데이터를 ViewModel로 바꿔서 View에 전달
!// MARK: EventTalkRequestLogic definition
protocol EventTalkRequestLogic {
!!/// 외부매개변수는 제외하기
func process(_ request: EventTalk.Request.OnLoad)
}
!// MARK: EventTalkWorkingLogic definition
protocol EventTalkWorkingLogic {
!!/// 자유롭게 매개변수 추가하기 (Add parameters freely)
func doSomeWork()
}
!// MARK: EventTalkPresentationLogic definition
protocol EventTalkPresentationLogic: class {
!!/// 외부매개변수는 제외하기
func present(_ response: EventTalk.Response)
}
!// MARK: EventTalkDisplayLogic definition
protocol EventTalkDisplayLogic: class {
!!/// 외부매개변수는 제외하기
func display(_ viewModel: EventTalk.ViewModel.Something)
}
EVENT TALK
관심 주제 알림톡 신청
개발 순서
• 프로젝트 기획서
• 디자인 가이드
• UI 구현
• 기능 구현
• API 연결
Use Case부터 정리하자
User Flow
사용자 관점에서 시나리오를 Use Case로 정리하고,
Use Case 별로 Jira 태스크를 생성,
개발하고 Test Case를 작성하여 확인했습니다.
예제로 배우는
BDD
키워드 불러오기
describe("뷰가 로드되었을 때") {
var interactor: EventKeywordNoticeInteractor!
var presenter: EventKeywordNoticePresenterMock!
let worker = EventKeywordNoticeWorkerMock()
beforeEach {
interactor = EventKeywordNoticeInteractor(worker: worker)
presenter = EventKeywordNoticePresenterMock()
interactor.presenter = presenter
worker.setSuccess(true)
}
context("이전에 선택한 관심 키워드를 가져오는데 성공하면") {
beforeEach {
let request = EventKeywordNotice.Request.OnLoad()
interactor.process(request)
}
it("이전에 선택한 관심 키워드를 표시한다") {
expect(presenter.displayInterestKeywordsCalled).to(beTrue())
}
}
context("이전에 선택한 관심 키워드를 가져오는데 실패하면") {
beforeEach {
worker.setSuccess(false)
let request = EventKeywordNotice.Request.OnLoad()
interactor.process(request)
}
it("경고창으로 에러 메시지를 표시한다") {
expect(presenter.displayErrorAlert).to(beTrue())
}
}
context("저장된 휴대폰 번호를 가져오는데 성공하면") {
it("저장된 휴대폰 번호를 표시한다") {
let request = EventKeywordNotice.Request.OnLoad()
interactor.process(request)
expect(presenter.displayMobilePhoneNumberCalled).to(beTrue())
}
}
}
키워드 선택하기
describe("키워드를 선택했을 때") {
var interactor: EventKeywordNoticeInteractor!
var presenter: EventKeywordNoticePresenterMock!
let worker = EventKeywordNoticeWorkerMock()
let selectedKeywords = [
EventKeyword.Keyword(id: 1, kind: "EVENT", keyword: "a.b.c", title: "키워드1"),
EventKeyword.Keyword(id: 2, kind: "EVENT", keyword: "d.e.f", title: "키워드2")
]
beforeEach {
interactor = EventKeywordNoticeInteractor(keywords: selectedKeywords, worker: worker)
presenter = EventKeywordNoticePresenterMock()
interactor.presenter = presenter
}
context("키워드 선택이 완료되면") {
it("선택한 키워드를 표시한다") {
interactor.selectedItems(selected: selectedKeywords.map { $0.title })
expect(presenter.displayInterestKeywordsCalled).to(beTrue())
expect(presenter.displayInterestKeywords.count).to(equal(selectedKeywords.count))
}
}
}
키워드 삭제하기
describe("키워드를 삭제했을 때") {
var interactor: EventKeywordNoticeInteractor!
var presenter: EventKeywordNoticePresenterMock!
let worker = EventKeywordNoticeWorkerMock()
let selectedKeywords = [
EventKeyword.Keyword(id: 1, kind: "EVENT", keyword: "a.b.c", title: "키워드1"),
EventKeyword.Keyword(id: 2, kind: "EVENT", keyword: "d.e.f", title: "키워드2")
]
beforeEach {
interactor = EventKeywordNoticeInteractor(keywords: selectedKeywords, worker: worker)
presenter = EventKeywordNoticePresenterMock()
interactor.presenter = presenter
interactor.selectedItems(selected: selectedKeywords.map { $0.title })
}
context("키워드 삭제가 완료되면") {
it("남아있는 키워드를 표시한다") {
let request = EventKeywordNotice.Request.RemoveKeyword(index: 0)
interactor.process(request)
expect(presenter.displayInterestKeywordsCalled).to(beTrue())
expect(presenter.displayInterestKeywords.count).to(equal(selectedKeywords.count - 1))
}
}
}
휴대폰 번호 입력하기
describe("휴대폰 번호 입력했을 때") {
var interactor: EventKeywordNoticeInteractor!
var presenter: EventKeywordNoticePresenterMock!
let worker = EventKeywordNoticeWorkerMock()
beforeEach {
interactor = EventKeywordNoticeInteractor(worker: worker)
presenter = EventKeywordNoticePresenterMock()
interactor.presenter = presenter
}
context("유효한 휴대폰 번호이면") {
it("휴대폰 번호를 통과 처리한다") {
let request = EventKeywordNotice.Request.InputMobileNumber(value: "01012345678")
interactor.process(request)
expect(presenter.displayMobilePhoneNumberCalled).to(beTrue())
expect(presenter.displayMobilePhoneNumber).to(equal("01012345678"))
expect(presenter.displayMobilePhoneNumberValidation).to(beTrue())
}
}
context("유효한 휴대폰 번호가 아니면") {
it("휴대폰 번호를 실패 처리한다") {
let request = EventKeywordNotice.Request.InputMobileNumber(value: "010-1234-567")
interactor.process(request)
expect(presenter.displayMobilePhoneNumberCalled).to(beTrue())
expect(presenter.displayMobilePhoneNumber).to(equal("010-1234-567"))
expect(presenter.displayMobilePhoneNumberValidation).to(beFalse())
}
}
}
알림 신청하기
describe("알림 신청하기 눌렀을 때") {
var interactor: EventKeywordNoticeInteractor!
var presenter: EventKeywordNoticePresenterMock!
let worker = EventKeywordNoticeWorkerMock()
let selectedKeywords = [
EventKeyword.Keyword(id: 1, kind: "EVENT", keyword: "a.b.c", title: "키워드1"),
EventKeyword.Keyword(id: 2, kind: "EVENT", keyword: "d.e.f", title: "키워드2")
]
beforeEach {
interactor = EventKeywordNoticeInteractor(keywords: selectedKeywords, worker: worker)
presenter = EventKeywordNoticePresenterMock()
interactor.presenter = presenter
interactor.selectedItems(selected: selectedKeywords.map { $0.title })
}
context("신청하기가 정상적으로 호출되면") {
beforeEach {
let request = EventKeywordNotice.Request.RequestNotice()
interactor.process(request)
}
it("확인 팝업을 보여준다") {
expect(presenter.displayCompletionCalled).to(beTrue())
}
}
context("신청하기가 정상적으로 호출되지 않으면") {
beforeEach {
worker.setSuccess(false)
let request = EventKeywordNotice.Request.RequestNotice()
interactor.process(request)
}
it("토스트로 메시지를 표시한다") {
expect(presenter.displayErrorToast).to(beTrue())
}
}
}
초기화하기
describe("초기화했을 때") {
var interactor: EventKeywordNoticeInteractor!
var presenter: EventKeywordNoticePresenterMock!
let worker = EventKeywordNoticeWorkerMock()
let selectedKeywords = [
EventKeyword.Keyword(id: 1, kind: "EVENT", keyword: "a.b.c", title: "키워드1"),
EventKeyword.Keyword(id: 2, kind: "EVENT", keyword: "d.e.f", title: "키워드2")
]
beforeEach {
interactor = EventKeywordNoticeInteractor(keywords: selectedKeywords, worker: worker)
presenter = EventKeywordNoticePresenterMock()
interactor.presenter = presenter
interactor.selectedItems(selected: selectedKeywords.map { $0.title })
}
it("선택한 키워드를 초기화한다") {
let request = EventKeywordNotice.Request.ResetKeywords()
interactor.process(request)
expect(presenter.displayInterestKeywordsCalled).to(beTrue())
expect(presenter.displayInterestKeywords.count).to(equal(0))
}
}
마치며
최종 사용자의 행동 중심 테스트
비즈니스 요구사항의 검증
작성된 테스트는 그 자체로도 문서화
(+ QA와 버그 감소)
🔖
여러분도 BDD를 한번 해보세요!

More Related Content

What's hot

Why SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptWhy SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptmartinlippert
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Patterngoodfriday
 
Rapid development tools for java ee 8 [tut2998]
Rapid development tools for java ee 8 [tut2998]Rapid development tools for java ee 8 [tut2998]
Rapid development tools for java ee 8 [tut2998]Payara
 
Introduction to Google Guice
Introduction to Google GuiceIntroduction to Google Guice
Introduction to Google GuiceKnoldus Inc.
 
Hybrid apps - Your own mini Cordova
Hybrid apps - Your own mini CordovaHybrid apps - Your own mini Cordova
Hybrid apps - Your own mini CordovaAyman Mahfouz
 
Jug Guice Presentation
Jug Guice PresentationJug Guice Presentation
Jug Guice PresentationDmitry Buzdin
 
Dependency Injection with Unity Container
Dependency Injection with Unity ContainerDependency Injection with Unity Container
Dependency Injection with Unity ContainerMindfire Solutions
 
Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8Peter Lehto
 
Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right wayThibaud Desodt
 
Functional Dependency Injection in C#
Functional Dependency Injection in C#Functional Dependency Injection in C#
Functional Dependency Injection in C#Thomas Jaskula
 
Reactive Model-View-ViewModel Architecture
Reactive Model-View-ViewModel ArchitectureReactive Model-View-ViewModel Architecture
Reactive Model-View-ViewModel ArchitectureGyuwon Yi
 
IndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsIndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsAdégòkè Obasá
 
Quick Start to iOS Development
Quick Start to iOS DevelopmentQuick Start to iOS Development
Quick Start to iOS DevelopmentJussi Pohjolainen
 
JavaScripters Event Oct 22, 2016 · 2:00 PM: Common Mistakes made by Angular D...
JavaScripters Event Oct 22, 2016 · 2:00 PM: Common Mistakes made by Angular D...JavaScripters Event Oct 22, 2016 · 2:00 PM: Common Mistakes made by Angular D...
JavaScripters Event Oct 22, 2016 · 2:00 PM: Common Mistakes made by Angular D...JavaScripters Community
 
JavaFX for Business Application Developers
JavaFX for Business Application DevelopersJavaFX for Business Application Developers
JavaFX for Business Application DevelopersMichael Heinrichs
 
Dependency injection Drupal Camp Wrocław 2014
Dependency injection Drupal Camp Wrocław 2014Dependency injection Drupal Camp Wrocław 2014
Dependency injection Drupal Camp Wrocław 2014Greg Szczotka
 
Sharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SFSharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SFPierre-Yves Ricau
 

What's hot (20)

Why SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptWhy SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScript
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Pattern
 
Rapid development tools for java ee 8 [tut2998]
Rapid development tools for java ee 8 [tut2998]Rapid development tools for java ee 8 [tut2998]
Rapid development tools for java ee 8 [tut2998]
 
Introduction to Google Guice
Introduction to Google GuiceIntroduction to Google Guice
Introduction to Google Guice
 
Hybrid apps - Your own mini Cordova
Hybrid apps - Your own mini CordovaHybrid apps - Your own mini Cordova
Hybrid apps - Your own mini Cordova
 
Jug Guice Presentation
Jug Guice PresentationJug Guice Presentation
Jug Guice Presentation
 
Dependency Injection with Unity Container
Dependency Injection with Unity ContainerDependency Injection with Unity Container
Dependency Injection with Unity Container
 
Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8
 
Google Guice
Google GuiceGoogle Guice
Google Guice
 
Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right way
 
Functional Dependency Injection in C#
Functional Dependency Injection in C#Functional Dependency Injection in C#
Functional Dependency Injection in C#
 
Human Talks - StencilJS
Human Talks - StencilJSHuman Talks - StencilJS
Human Talks - StencilJS
 
Reactive Model-View-ViewModel Architecture
Reactive Model-View-ViewModel ArchitectureReactive Model-View-ViewModel Architecture
Reactive Model-View-ViewModel Architecture
 
IndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsIndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web Apps
 
Quick Start to iOS Development
Quick Start to iOS DevelopmentQuick Start to iOS Development
Quick Start to iOS Development
 
JavaScripters Event Oct 22, 2016 · 2:00 PM: Common Mistakes made by Angular D...
JavaScripters Event Oct 22, 2016 · 2:00 PM: Common Mistakes made by Angular D...JavaScripters Event Oct 22, 2016 · 2:00 PM: Common Mistakes made by Angular D...
JavaScripters Event Oct 22, 2016 · 2:00 PM: Common Mistakes made by Angular D...
 
JavaFX for Business Application Developers
JavaFX for Business Application DevelopersJavaFX for Business Application Developers
JavaFX for Business Application Developers
 
Solid OOPS
Solid OOPSSolid OOPS
Solid OOPS
 
Dependency injection Drupal Camp Wrocław 2014
Dependency injection Drupal Camp Wrocław 2014Dependency injection Drupal Camp Wrocław 2014
Dependency injection Drupal Camp Wrocław 2014
 
Sharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SFSharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SF
 

Similar to 지금 당장 (유사) BDD 시작하기

TDD by Controlling Dependencies
TDD by Controlling DependenciesTDD by Controlling Dependencies
TDD by Controlling DependenciesJorge Ortiz
 
Behaviour Driven Development V 0.1
Behaviour Driven Development V 0.1Behaviour Driven Development V 0.1
Behaviour Driven Development V 0.1willmation
 
TDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidTDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidCodemotion
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2Leonid Maslov
 
Delegateless Coordinators - take 2
Delegateless Coordinators - take 2Delegateless Coordinators - take 2
Delegateless Coordinators - take 2Tales Andrade
 
Effective JavaFX architecture with FxObjects
Effective JavaFX architecture with FxObjectsEffective JavaFX architecture with FxObjects
Effective JavaFX architecture with FxObjectsSrikanth Shenoy
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorDavid Rodenas
 
Mobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve MobileMobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve MobileKonstantin Loginov
 
Matteo Vaccari - TDD per Android | Codemotion Milan 2015
Matteo Vaccari - TDD per Android | Codemotion Milan 2015Matteo Vaccari - TDD per Android | Codemotion Milan 2015
Matteo Vaccari - TDD per Android | Codemotion Milan 2015Codemotion
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Paco de la Cruz
 
Intro to IndexedDB (Beta)
Intro to IndexedDB (Beta)Intro to IndexedDB (Beta)
Intro to IndexedDB (Beta)Mike West
 
Will your code blend? : Toronto Code Camp 2010 : Barry Gervin
Will your code blend? : Toronto Code Camp 2010 : Barry GervinWill your code blend? : Toronto Code Camp 2010 : Barry Gervin
Will your code blend? : Toronto Code Camp 2010 : Barry GervinBarry Gervin
 
Android accessibility for developers and QA
Android accessibility for developers and QAAndroid accessibility for developers and QA
Android accessibility for developers and QATed Drake
 
So What Do Cucumbers Have To Do With Testing
So What Do Cucumbers Have To Do With TestingSo What Do Cucumbers Have To Do With Testing
So What Do Cucumbers Have To Do With Testingsjmarsh
 
Front End Development: The Important Parts
Front End Development: The Important PartsFront End Development: The Important Parts
Front End Development: The Important PartsSergey Bolshchikov
 

Similar to 지금 당장 (유사) BDD 시작하기 (20)

TDD by Controlling Dependencies
TDD by Controlling DependenciesTDD by Controlling Dependencies
TDD by Controlling Dependencies
 
Evolve your coding with some BDD
Evolve your coding with some BDDEvolve your coding with some BDD
Evolve your coding with some BDD
 
Behaviour Driven Development V 0.1
Behaviour Driven Development V 0.1Behaviour Driven Development V 0.1
Behaviour Driven Development V 0.1
 
TDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidTDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with Android
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
 
Delegateless Coordinators - take 2
Delegateless Coordinators - take 2Delegateless Coordinators - take 2
Delegateless Coordinators - take 2
 
Coding Naked 2023
Coding Naked 2023Coding Naked 2023
Coding Naked 2023
 
WOdka
WOdkaWOdka
WOdka
 
Effective JavaFX architecture with FxObjects
Effective JavaFX architecture with FxObjectsEffective JavaFX architecture with FxObjects
Effective JavaFX architecture with FxObjects
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD Calculator
 
Mobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve MobileMobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve Mobile
 
Matteo Vaccari - TDD per Android | Codemotion Milan 2015
Matteo Vaccari - TDD per Android | Codemotion Milan 2015Matteo Vaccari - TDD per Android | Codemotion Milan 2015
Matteo Vaccari - TDD per Android | Codemotion Milan 2015
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)
 
Intro to IndexedDB (Beta)
Intro to IndexedDB (Beta)Intro to IndexedDB (Beta)
Intro to IndexedDB (Beta)
 
Will your code blend? : Toronto Code Camp 2010 : Barry Gervin
Will your code blend? : Toronto Code Camp 2010 : Barry GervinWill your code blend? : Toronto Code Camp 2010 : Barry Gervin
Will your code blend? : Toronto Code Camp 2010 : Barry Gervin
 
Android accessibility for developers and QA
Android accessibility for developers and QAAndroid accessibility for developers and QA
Android accessibility for developers and QA
 
So What Do Cucumbers Have To Do With Testing
So What Do Cucumbers Have To Do With TestingSo What Do Cucumbers Have To Do With Testing
So What Do Cucumbers Have To Do With Testing
 
D3_Tuto_GD
D3_Tuto_GDD3_Tuto_GD
D3_Tuto_GD
 
D3_Tuto_GD
D3_Tuto_GDD3_Tuto_GD
D3_Tuto_GD
 
Front End Development: The Important Parts
Front End Development: The Important PartsFront End Development: The Important Parts
Front End Development: The Important Parts
 

Recently uploaded

From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 

Recently uploaded (20)

From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 

지금 당장 (유사) BDD 시작하기

  • 1. 지금 당장 (유사) BDD 시작하기 간단하게 BDD를 적용해보고 기존과 다르게 개발했던 경험 Wanted Live Talk
  • 3. TL;DW • 지금 당장 (유사) BDD 시작하기 확장판 • 실제 프로젝트에서 BDD를 적용했던 경험 • (유사)인 이유는 테스트부터 작성하지 않음
  • 4. TDD
  • 6. TDD • 🚫 테스트 코드를 작성 • ✅ 구현 코드를 작성 • 🛠 리팩토링 단계
  • 7.
  • 8.
  • 9.
  • 11. do(TDD!) Fatal error: Unexpectedly found nil while unwrapping on Optional value
  • 12. BDD
  • 14. BDD • Feature: 테스트 대상의 기능/책임을 명시합니다. • Scenario: 테스트 목적에 대한 상황을 설명합니다. • Given: 시나리오 진행에 필요한 값을 설정합니다. • When: 시나리오를 진행하는데 필요한 조건을 명시합니다. • Then: 시나리오를 완료했을 때 보장해야 하는 결과를 명시합니다.
  • 15. describe("Given the User repository") { var userRepository: UserRepository! beforeEach { userRepository = UserRepository(mode: .inMemory) } context("When a user is saved") { beforeEach { userRepository.deleteAll() userRepository.populateTestUsers() let user = User() user.email = "user.test@sampleemail.com" userRepository.save(user) } it("Should be recoverable") { let recoveredUser = userRepository.findOne( email: "user.test@sampleemail.com" ) expect(recoveredUser).toNot(beNil()) } } }
  • 16.
  • 18.
  • 19. Clean Swift • ViewController (UI 디자인) • 뷰 이벤트를 Interactor에 전달, Presenter가 주는 데이터 표시 • Interactor (이벤트 처리) • 이벤트 처리, 상태 관리, 모든 비즈니스 로직을 담당 / Worker와 협력 • Presenter (ViewModel 생성) • Interactor에서 받은 데이터를 ViewModel로 바꿔서 View에 전달
  • 20. !// MARK: EventTalkRequestLogic definition protocol EventTalkRequestLogic { !!/// 외부매개변수는 제외하기 func process(_ request: EventTalk.Request.OnLoad) } !// MARK: EventTalkWorkingLogic definition protocol EventTalkWorkingLogic { !!/// 자유롭게 매개변수 추가하기 (Add parameters freely) func doSomeWork() } !// MARK: EventTalkPresentationLogic definition protocol EventTalkPresentationLogic: class { !!/// 외부매개변수는 제외하기 func present(_ response: EventTalk.Response) } !// MARK: EventTalkDisplayLogic definition protocol EventTalkDisplayLogic: class { !!/// 외부매개변수는 제외하기 func display(_ viewModel: EventTalk.ViewModel.Something) }
  • 21. EVENT TALK 관심 주제 알림톡 신청
  • 22.
  • 23. 개발 순서 • 프로젝트 기획서 • 디자인 가이드 • UI 구현 • 기능 구현 • API 연결 Use Case부터 정리하자
  • 25. 사용자 관점에서 시나리오를 Use Case로 정리하고, Use Case 별로 Jira 태스크를 생성, 개발하고 Test Case를 작성하여 확인했습니다.
  • 26.
  • 29. describe("뷰가 로드되었을 때") { var interactor: EventKeywordNoticeInteractor! var presenter: EventKeywordNoticePresenterMock! let worker = EventKeywordNoticeWorkerMock() beforeEach { interactor = EventKeywordNoticeInteractor(worker: worker) presenter = EventKeywordNoticePresenterMock() interactor.presenter = presenter worker.setSuccess(true) } context("이전에 선택한 관심 키워드를 가져오는데 성공하면") { beforeEach { let request = EventKeywordNotice.Request.OnLoad() interactor.process(request) } it("이전에 선택한 관심 키워드를 표시한다") { expect(presenter.displayInterestKeywordsCalled).to(beTrue()) } }
  • 30. context("이전에 선택한 관심 키워드를 가져오는데 실패하면") { beforeEach { worker.setSuccess(false) let request = EventKeywordNotice.Request.OnLoad() interactor.process(request) } it("경고창으로 에러 메시지를 표시한다") { expect(presenter.displayErrorAlert).to(beTrue()) } } context("저장된 휴대폰 번호를 가져오는데 성공하면") { it("저장된 휴대폰 번호를 표시한다") { let request = EventKeywordNotice.Request.OnLoad() interactor.process(request) expect(presenter.displayMobilePhoneNumberCalled).to(beTrue()) } } }
  • 32. describe("키워드를 선택했을 때") { var interactor: EventKeywordNoticeInteractor! var presenter: EventKeywordNoticePresenterMock! let worker = EventKeywordNoticeWorkerMock() let selectedKeywords = [ EventKeyword.Keyword(id: 1, kind: "EVENT", keyword: "a.b.c", title: "키워드1"), EventKeyword.Keyword(id: 2, kind: "EVENT", keyword: "d.e.f", title: "키워드2") ] beforeEach { interactor = EventKeywordNoticeInteractor(keywords: selectedKeywords, worker: worker) presenter = EventKeywordNoticePresenterMock() interactor.presenter = presenter } context("키워드 선택이 완료되면") { it("선택한 키워드를 표시한다") { interactor.selectedItems(selected: selectedKeywords.map { $0.title }) expect(presenter.displayInterestKeywordsCalled).to(beTrue()) expect(presenter.displayInterestKeywords.count).to(equal(selectedKeywords.count)) } } }
  • 34. describe("키워드를 삭제했을 때") { var interactor: EventKeywordNoticeInteractor! var presenter: EventKeywordNoticePresenterMock! let worker = EventKeywordNoticeWorkerMock() let selectedKeywords = [ EventKeyword.Keyword(id: 1, kind: "EVENT", keyword: "a.b.c", title: "키워드1"), EventKeyword.Keyword(id: 2, kind: "EVENT", keyword: "d.e.f", title: "키워드2") ] beforeEach { interactor = EventKeywordNoticeInteractor(keywords: selectedKeywords, worker: worker) presenter = EventKeywordNoticePresenterMock() interactor.presenter = presenter interactor.selectedItems(selected: selectedKeywords.map { $0.title }) } context("키워드 삭제가 완료되면") { it("남아있는 키워드를 표시한다") { let request = EventKeywordNotice.Request.RemoveKeyword(index: 0) interactor.process(request) expect(presenter.displayInterestKeywordsCalled).to(beTrue()) expect(presenter.displayInterestKeywords.count).to(equal(selectedKeywords.count - 1)) } } }
  • 36. describe("휴대폰 번호 입력했을 때") { var interactor: EventKeywordNoticeInteractor! var presenter: EventKeywordNoticePresenterMock! let worker = EventKeywordNoticeWorkerMock() beforeEach { interactor = EventKeywordNoticeInteractor(worker: worker) presenter = EventKeywordNoticePresenterMock() interactor.presenter = presenter } context("유효한 휴대폰 번호이면") { it("휴대폰 번호를 통과 처리한다") { let request = EventKeywordNotice.Request.InputMobileNumber(value: "01012345678") interactor.process(request) expect(presenter.displayMobilePhoneNumberCalled).to(beTrue()) expect(presenter.displayMobilePhoneNumber).to(equal("01012345678")) expect(presenter.displayMobilePhoneNumberValidation).to(beTrue()) } }
  • 37. context("유효한 휴대폰 번호가 아니면") { it("휴대폰 번호를 실패 처리한다") { let request = EventKeywordNotice.Request.InputMobileNumber(value: "010-1234-567") interactor.process(request) expect(presenter.displayMobilePhoneNumberCalled).to(beTrue()) expect(presenter.displayMobilePhoneNumber).to(equal("010-1234-567")) expect(presenter.displayMobilePhoneNumberValidation).to(beFalse()) } } }
  • 39. describe("알림 신청하기 눌렀을 때") { var interactor: EventKeywordNoticeInteractor! var presenter: EventKeywordNoticePresenterMock! let worker = EventKeywordNoticeWorkerMock() let selectedKeywords = [ EventKeyword.Keyword(id: 1, kind: "EVENT", keyword: "a.b.c", title: "키워드1"), EventKeyword.Keyword(id: 2, kind: "EVENT", keyword: "d.e.f", title: "키워드2") ] beforeEach { interactor = EventKeywordNoticeInteractor(keywords: selectedKeywords, worker: worker) presenter = EventKeywordNoticePresenterMock() interactor.presenter = presenter interactor.selectedItems(selected: selectedKeywords.map { $0.title }) }
  • 40. context("신청하기가 정상적으로 호출되면") { beforeEach { let request = EventKeywordNotice.Request.RequestNotice() interactor.process(request) } it("확인 팝업을 보여준다") { expect(presenter.displayCompletionCalled).to(beTrue()) } } context("신청하기가 정상적으로 호출되지 않으면") { beforeEach { worker.setSuccess(false) let request = EventKeywordNotice.Request.RequestNotice() interactor.process(request) } it("토스트로 메시지를 표시한다") { expect(presenter.displayErrorToast).to(beTrue()) } } }
  • 42. describe("초기화했을 때") { var interactor: EventKeywordNoticeInteractor! var presenter: EventKeywordNoticePresenterMock! let worker = EventKeywordNoticeWorkerMock() let selectedKeywords = [ EventKeyword.Keyword(id: 1, kind: "EVENT", keyword: "a.b.c", title: "키워드1"), EventKeyword.Keyword(id: 2, kind: "EVENT", keyword: "d.e.f", title: "키워드2") ] beforeEach { interactor = EventKeywordNoticeInteractor(keywords: selectedKeywords, worker: worker) presenter = EventKeywordNoticePresenterMock() interactor.presenter = presenter interactor.selectedItems(selected: selectedKeywords.map { $0.title }) } it("선택한 키워드를 초기화한다") { let request = EventKeywordNotice.Request.ResetKeywords() interactor.process(request) expect(presenter.displayInterestKeywordsCalled).to(beTrue()) expect(presenter.displayInterestKeywords.count).to(equal(0)) } }
  • 43.
  • 44. 마치며 최종 사용자의 행동 중심 테스트 비즈니스 요구사항의 검증 작성된 테스트는 그 자체로도 문서화 (+ QA와 버그 감소)