SlideShare a Scribd company logo
効果的なBDDテスト
Effective BDD Testing [iOS]
iOS Test Night #11
デレック・リー @derekleerock
[ GitHub・Twitter・FB・LinkedIn ]
1
自己紹介
→ Full-Stack XP/TDD/Pair Pro
Engineer @ Pivotal Labs Tokyo
→ Swift, Objective-C, JavaScript/
React, Java/Kotlin/Spring
→ Tokyo iOS Meetup Co-Facilitator
→ Aspiring Drummer/Educator
→ Weight Training, Hiking, SUP,
Ping Pong, Spikeball
→ Meditation, Essentialism (Book),
Tim Ferriss Show Podcast
2
BDDの特徴
→ テスト名は文書で書く Test names as sentences
→ 自然言語 Natural language
→ ユーザー観点 User perspective
→ 振る舞いにフォーカス Focus on behavior
3
iOSのBDD Frameworkといえば? → QUICK
describe("some object") {
context("when some condition") {
it("behaves the way I expect") {
// 準備 Arrange // GIVEN
// 実行 Act // WHEN
// 期待 Assert // THEN
}
}
}
4
iOSのBDD Frameworkといえば? → QUICK
describe("some object") {
context("when some condition") {
it("behaves the way I expect") {
// 準備 Arrange // GIVEN
// 実行 Act // WHEN
// 期待 Assert // THEN
}
}
}
4
iOSのBDD Frameworkといえば? → QUICK
describe("some object") {
context("when some condition") {
it("behaves the way I expect") {
// 準備 Arrange // GIVEN
// 実行 Act // WHEN
// 期待 Assert // THEN
}
}
}
4
iOSのBDD Frameworkといえば? → QUICK
describe("some object") {
context("when some condition") {
it("behaves the way I expect") {
// 準備 Arrange // GIVEN
// 実行 Act // WHEN
// 期待 Assert // THEN
}
}
}
4
iOSのBDD Frameworkといえば? → QUICK
describe("some object") {
context("when some condition") {
it("behaves the way I expect") {
// 準備 Arrange // GIVEN
// 実行 Act // WHEN
// 期待 Assert // THEN
}
}
}
4
"Outside-In" BDDの
ViewControllerテストの事例
テスト駆動型開発で説明する
5
テスト:実装のクラスの関数を直接呼び出す方法
describe("ログイン") {
context("ログインボタンをタップするとき") {
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
logonVC.didTapLogonButton()
expect(...)
}
}
}
6
テスト:実装のクラスの関数を直接呼び出す方法
describe("ログイン") {
context("ログインボタンをタップするとき") {
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
logonVC.didTapLogonButton()
expect(...)
}
}
}
6
テスト:実装のクラスの関数を直接呼び出す方法
describe("ログイン") {
context("ログインボタンをタップするとき") {
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
logonVC.didTapLogonButton()
expect(...)
}
}
}
6
テスト:実装のクラスの関数を直接呼び出す方法
describe("ログイン") {
context("ログインボタンをタップするとき") {
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
logonVC.didTapLogonButton()
expect(...)
}
}
}
6
コード:関数を定義しても、
UIButtonのtargetは設定していない
class LogonViewController: UIViewController {
func didTapLogonButton(sender: UIButton) {
// ...
}
}
7
テスト:ボタンをタップのふりをする方法
describe("ログイン") {
context("ログインボタンをタップするとき") {
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
logonVC.logonButton.sendActions(for: .touchUpInside)
expect(...)
}
}
}
8
コード:UIButtonのtargetを設定して、
関数をprivateに変更できるようになる
class LogonViewController: UIViewController {
let logonButton: UIButton!
init() {
super.init(nibName: nil, bundle: nil)
logonButton.addTarget(
self,
action: #selector(didTapLogonButton(sender:)),
for: .touchUpInside
)
}
↓ ↓
@objc private func didTapLogonButton(sender: UIButton) {
// ...
}
}
9
コード:UIButtonのtargetを設定して、
関数をprivateに変更できるようになる
class LogonViewController: UIViewController {
let logonButton: UIButton!
init() {
super.init(nibName: nil, bundle: nil)
logonButton.addTarget(
self,
action: #selector(didTapLogonButton(sender:)),
for: .touchUpInside
)
}
↓ ↓
@objc private func didTapLogonButton(sender: UIButton) {
// ...
}
}
9
テスト:リファクタリング
extension UIButton {
func tap() {
sendActions(for: .touchUpInside)
}
}
logonVC.logonButton.sendActions(for: .touchUpInside)
↓ ↓
logonVC.logonButton.tap()
10
テスト:リファクタリング
extension UIButton {
func tap() {
sendActions(for: .touchUpInside)
}
}
logonVC.logonButton.sendActions(for: .touchUpInside)
↓ ↓
logonVC.logonButton.tap()
10
コード:理想なのは、UIButtonもprivateにしたい
class LogonViewController: UIViewController {
↓ ↓
private let logonButton: UIButton!
...
@objc private func didTapLogonButton(sender: UIButton) {
// ...
}
}
11
テスト:リファクタリング
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
logonVC.logonButton.tap()
expect(...)
}
12
テスト:リファクタリング
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
logonVC.logonButton.tap()
expect(...)
}
12
テスト:リファクタリング
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
for subview in logonVC.view.subviews {
}
expect(...)
}
13
テスト:リファクタリング
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
for subview in logonVC.view.subviews {
if let button = subview as? UIButton {
}
}
expect(...)
}
14
テスト:リファクタリング
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
for subview in logonVC.view.subviews {
if let button = subview as? UIButton {
button.tap()
break
}
}
expect(...)
}
15
テスト:ボタンのテキストのテストを改善
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
for subview in logonVC.view.subviews {
if let button = subview as? UIButton {
if button.titleLabel?.text == "Logon" {
button.tap()
break
}
}
}
expect(...)
}
16
テスト:ボタンのテキストのテストを改善
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
for subview in logonVC.view.subviews {
if let button = subview as? UIButton {
if button.titleLabel?.text == "Logon" {
button.tap()
break
}
}
}
expect(...)
}
16
テスト:リファクタリング
it("ユーザーの認証を確認する") {
let logonVC = LogonViewController(...)
logonVC.tapButton(withText: "Logon")
expect(...)
}
17
コード:subviewに追加する
class LogonViewController: UIViewController {
private let logonButton: UIButton!
init() {
super.init(nibName: nil, bundle: nil)
logonButton.addTarget(...)
view.addSubview(logonButton)
}
...
}
18
UIButtonDecouple Repo
github.com/derekleerock/UIButtonDecouple
19
これは面白いけど、
ちょっと大変じゃない?
20
サシンクト(Succinct)を紹介!
github.com/derekleerock/Succinct
21
サシンクトのゴール ①
→ 単体テストの速さでUIもテストできるようになる
UI tests at the speed of unit tests
→ Swiftのクラスをちゃんとキャプセルカできる
Proper encapsulation
22
サシンクトのゴール ②
→ どんなアーキテクチャを使っても構わない
Architecture agnostic (MVC, MVVM, MVPなど)
→ リファクタリングの自由度が高い
Freedom to refactor
23
サシンクトの特徴
→ UIViewControllerのUIViewを回帰でViewを検索
→ テスト駆動型開発で作ったので、
テスト方法にも参考になる
→ 改善・新機能はGitHub Issueで管理している
→ OpenSource - PRs Welcome!
24
25
ご静聴ありがとうございました!
Derek Lee
@derekleerock
github.com/derekleerock/Succinct
26

More Related Content

Similar to Effective BDD Testing 効果的なBDDテスト [iOS]

Mongodb
MongodbMongodb
Mongodb
Satoru Mikami
 
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
Let's build a simple app with  .net 6 asp.net core web api, react, and elasti...Let's build a simple app with  .net 6 asp.net core web api, react, and elasti...
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
Shotaro Suzuki
 
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
Fumiya Sakai
 
Entity Framework 5.0 deep dive
Entity Framework 5.0 deep diveEntity Framework 5.0 deep dive
Entity Framework 5.0 deep dive
Atsushi Fukui
 
Ansible 2.0を使って組む kubernetesクラスタ vol.1
Ansible 2.0を使って組む kubernetesクラスタ vol.1Ansible 2.0を使って組む kubernetesクラスタ vol.1
Ansible 2.0を使って組む kubernetesクラスタ vol.1
Hidetoshi Hirokawa
 
少しずつ手厚くして不具合や仕様漏れを防ぐために
少しずつ手厚くして不具合や仕様漏れを防ぐために少しずつ手厚くして不具合や仕様漏れを防ぐために
少しずつ手厚くして不具合や仕様漏れを防ぐために
Fumiya Sakai
 
iOSアプリケーションの Unit Test
iOSアプリケーションの Unit TestiOSアプリケーションの Unit Test
iOSアプリケーションの Unit Test
Katsumi Kishikawa
 
もう怖くないモバイルアプリ開発!
もう怖くないモバイルアプリ開発!もう怖くないモバイルアプリ開発!
もう怖くないモバイルアプリ開発!
Toshiki Iga
 
ReduxとSwiftの組み合わせ:改訂版
ReduxとSwiftの組み合わせ:改訂版ReduxとSwiftの組み合わせ:改訂版
ReduxとSwiftの組み合わせ:改訂版
Fumiya Sakai
 
Driverについて
DriverについてDriverについて
Driverについて
幸雄 村上
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
Toru Yamaguchi
 
Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...
Shotaro Suzuki
 
Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.
Yuki Higuchi
 
エンタープライズIT環境での OpenID Connect / SCIM の具体的実装方法 idit2014
エンタープライズIT環境での OpenID Connect / SCIM の具体的実装方法 idit2014エンタープライズIT環境での OpenID Connect / SCIM の具体的実装方法 idit2014
エンタープライズIT環境での OpenID Connect / SCIM の具体的実装方法 idit2014
Takashi Yahata
 
ボット開発でも DevOps! BotBuilder のテスト手法
ボット開発でも DevOps! BotBuilder のテスト手法ボット開発でも DevOps! BotBuilder のテスト手法
ボット開発でも DevOps! BotBuilder のテスト手法
Kenichiro Nakamura
 
初めての Data api
初めての Data api初めての Data api
初めての Data api
Yuji Takayama
 
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
Yoshifumi Kawai
 
13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejsTakayoshi Tanaka
 
cocos2d-xにおけるBox2Dの利用方法および便利なツール
cocos2d-xにおけるBox2Dの利用方法および便利なツールcocos2d-xにおけるBox2Dの利用方法および便利なツール
cocos2d-xにおけるBox2Dの利用方法および便利なツールTomoaki Shimizu
 
Tech talk salesforce mobile sdk
Tech talk   salesforce mobile sdkTech talk   salesforce mobile sdk
Tech talk salesforce mobile sdkKazuki Nakajima
 

Similar to Effective BDD Testing 効果的なBDDテスト [iOS] (20)

Mongodb
MongodbMongodb
Mongodb
 
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
Let's build a simple app with  .net 6 asp.net core web api, react, and elasti...Let's build a simple app with  .net 6 asp.net core web api, react, and elasti...
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
 
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
 
Entity Framework 5.0 deep dive
Entity Framework 5.0 deep diveEntity Framework 5.0 deep dive
Entity Framework 5.0 deep dive
 
Ansible 2.0を使って組む kubernetesクラスタ vol.1
Ansible 2.0を使って組む kubernetesクラスタ vol.1Ansible 2.0を使って組む kubernetesクラスタ vol.1
Ansible 2.0を使って組む kubernetesクラスタ vol.1
 
少しずつ手厚くして不具合や仕様漏れを防ぐために
少しずつ手厚くして不具合や仕様漏れを防ぐために少しずつ手厚くして不具合や仕様漏れを防ぐために
少しずつ手厚くして不具合や仕様漏れを防ぐために
 
iOSアプリケーションの Unit Test
iOSアプリケーションの Unit TestiOSアプリケーションの Unit Test
iOSアプリケーションの Unit Test
 
もう怖くないモバイルアプリ開発!
もう怖くないモバイルアプリ開発!もう怖くないモバイルアプリ開発!
もう怖くないモバイルアプリ開発!
 
ReduxとSwiftの組み合わせ:改訂版
ReduxとSwiftの組み合わせ:改訂版ReduxとSwiftの組み合わせ:改訂版
ReduxとSwiftの組み合わせ:改訂版
 
Driverについて
DriverについてDriverについて
Driverについて
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
 
Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...
 
Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.
 
エンタープライズIT環境での OpenID Connect / SCIM の具体的実装方法 idit2014
エンタープライズIT環境での OpenID Connect / SCIM の具体的実装方法 idit2014エンタープライズIT環境での OpenID Connect / SCIM の具体的実装方法 idit2014
エンタープライズIT環境での OpenID Connect / SCIM の具体的実装方法 idit2014
 
ボット開発でも DevOps! BotBuilder のテスト手法
ボット開発でも DevOps! BotBuilder のテスト手法ボット開発でも DevOps! BotBuilder のテスト手法
ボット開発でも DevOps! BotBuilder のテスト手法
 
初めての Data api
初めての Data api初めての Data api
初めての Data api
 
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
 
13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs
 
cocos2d-xにおけるBox2Dの利用方法および便利なツール
cocos2d-xにおけるBox2Dの利用方法および便利なツールcocos2d-xにおけるBox2Dの利用方法および便利なツール
cocos2d-xにおけるBox2Dの利用方法および便利なツール
 
Tech talk salesforce mobile sdk
Tech talk   salesforce mobile sdkTech talk   salesforce mobile sdk
Tech talk salesforce mobile sdk
 

More from Derek Lee Boire

Why I ❤️ Kotlin Multiplatform (and want YOU to also ❤️ Kotlin Multiplatform)
Why I ❤️ Kotlin Multiplatform (and want YOU to also ❤️ Kotlin Multiplatform)Why I ❤️ Kotlin Multiplatform (and want YOU to also ❤️ Kotlin Multiplatform)
Why I ❤️ Kotlin Multiplatform (and want YOU to also ❤️ Kotlin Multiplatform)
Derek Lee Boire
 
Standing the Test of Time: The Date Provider Pattern
Standing the Test of Time: The Date Provider PatternStanding the Test of Time: The Date Provider Pattern
Standing the Test of Time: The Date Provider Pattern
Derek Lee Boire
 
Minimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team ProductivityMinimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team Productivity
Derek Lee Boire
 
Writing Clean Code in Swift
Writing Clean Code in SwiftWriting Clean Code in Swift
Writing Clean Code in Swift
Derek Lee Boire
 
Common Challenges & Best Practices for TDD on iOS
Common Challenges & Best Practices for TDD on iOSCommon Challenges & Best Practices for TDD on iOS
Common Challenges & Best Practices for TDD on iOS
Derek Lee Boire
 
Adjusting to Auto Layout (Tutorial / Tips for iOS Auto Layout)
Adjusting to Auto Layout (Tutorial / Tips for iOS Auto Layout)Adjusting to Auto Layout (Tutorial / Tips for iOS Auto Layout)
Adjusting to Auto Layout (Tutorial / Tips for iOS Auto Layout)
Derek Lee Boire
 

More from Derek Lee Boire (6)

Why I ❤️ Kotlin Multiplatform (and want YOU to also ❤️ Kotlin Multiplatform)
Why I ❤️ Kotlin Multiplatform (and want YOU to also ❤️ Kotlin Multiplatform)Why I ❤️ Kotlin Multiplatform (and want YOU to also ❤️ Kotlin Multiplatform)
Why I ❤️ Kotlin Multiplatform (and want YOU to also ❤️ Kotlin Multiplatform)
 
Standing the Test of Time: The Date Provider Pattern
Standing the Test of Time: The Date Provider PatternStanding the Test of Time: The Date Provider Pattern
Standing the Test of Time: The Date Provider Pattern
 
Minimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team ProductivityMinimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team Productivity
 
Writing Clean Code in Swift
Writing Clean Code in SwiftWriting Clean Code in Swift
Writing Clean Code in Swift
 
Common Challenges & Best Practices for TDD on iOS
Common Challenges & Best Practices for TDD on iOSCommon Challenges & Best Practices for TDD on iOS
Common Challenges & Best Practices for TDD on iOS
 
Adjusting to Auto Layout (Tutorial / Tips for iOS Auto Layout)
Adjusting to Auto Layout (Tutorial / Tips for iOS Auto Layout)Adjusting to Auto Layout (Tutorial / Tips for iOS Auto Layout)
Adjusting to Auto Layout (Tutorial / Tips for iOS Auto Layout)
 

Effective BDD Testing 効果的なBDDテスト [iOS]