i osデバイスの実機テストの自動化 swift-

22
iOSデバイスの実機 テストの自動化 - Swift -

Upload: shusaku-fukumine

Post on 10-May-2015

474 views

Category:

Technology


3 download

DESCRIPTION

iOSデバイスの実機テストの自動化(Swift編)

TRANSCRIPT

iOSデバイスの実機 テストの自動化 - Swift -

自己紹介• 福嶺 秀策: Shusaku FUKUMINE

• Twitter:@shumach217

• レイヤ2より上のやわらかいモノ好き

!

今年は実機テストの自動化が

(何故か)自分のテーマとなっています!!

Turnipと出会ったから??

テストの自動化について• 石橋を高速に叩いて渡る。

• テストコードは成果物の動作を保証するもの。

• PCでは無いデバイスだと。。。

• iOSデバイスでも、シミュレータと挙動が異なる。

!

シミュレータはとっくに諦めています!!

実機動作確認をいかに効率よくやるか!!

本日は、Swiftで記述されているプログラムの

実機テストの自動化の話をします。

(Turnipで実機を動かす話)

Swiftとは• Developers Conference (WWDC) 2014で発表された、iOS8より使用可能な言語。

• Objective-Cと共存が可能。

!

!

ShumachTurnipとは• Objective-Cで記述。

• iOSデバイスをTCP/IPサーバとして起動。

• 文字列でオブジェクトの操作が可能。

• 関数実行

• インスタンス変数セット・ゲット

• プロパティセット・ゲット

• https://github.com/shumach217/ShumachTurnip

実現方法• テスト記述は ruby のTurnipをPC上で動作。

• iOS側に、ShumachTurnipをバックグラウンドで動作。

• PC - iOSデバイス間はTCP/IP。

• JSONにてやりとり!!

!

!

!

!

• WiFiを介して通信します。

• テザリングで通信します。

• デバイス側のIP アドレス:172.20.10.1

構成JSON on TCP/IP

Swift !class MainController: NSObject { ! var window: UIWindow? var turnip: ShumachTurnip? var boolValue: Bool = false var intValue: Int = 1234567890 var myClass : MyClass? !! init() { super.init() self.boolValue = false self.intValue = 1234567890 ! self.turnip = ShumachTurnip(port: 8000) self.turnip!.currentObject = self; } !! func reset() { self.boolValue = false self.intValue = 1234567890 ! self.myClass!.reset() } !! func testBOOL(val: Bool) -> Bool { return val } }

Turnip feature !Feature: Test ! Scenario: Test Given Connection Establishment Given Application Reset Then Method BOOL Test Then Get Instance BOOL Test "false" Given Set Instance BOOL Test "true" Then Get Instance BOOL Test “true" Then Get Instance Int Test "1234567890" Given Set Instance Int Test "1234" Then Get Instance Int Test “1234" Given Connection Release

Swift !class MainController: NSObject { ! var window: UIWindow? var turnip: ShumachTurnip? var boolValue: Bool = false var intValue: Int = 1234567890 var myClass : MyClass? !! init() { super.init() self.boolValue = false self.intValue = 1234567890 ! self.turnip = ShumachTurnip(port: 8000) self.turnip!.currentObject = self; } !! func reset() { self.boolValue = false self.intValue = 1234567890 ! self.myClass!.reset() } !! func testBOOL(val: Bool) -> Bool { return val } }

Turnip feature !Feature: Test ! Scenario: Test Given Connection Establishment Given Application Reset Then Method BOOL Test Then Get Instance BOOL Test "false" Given Set Instance BOOL Test "true" Then Get Instance BOOL Test “true" Then Get Instance Int Test "1234567890" Given Set Instance Int Test "1234" Then Get Instance Int Test “1234" Given Connection Release

2行で準備完了 (インデックスを張っている)

Swift !class MainController: NSObject { ! var window: UIWindow? var turnip: ShumachTurnip? var boolValue: Bool = false var intValue: Int = 1234567890 var myClass : MyClass? !! init() { super.init() self.boolValue = false self.intValue = 1234567890 ! self.turnip = ShumachTurnip(port: 8000) self.turnip!.currentObject = self; } !! func reset() { self.boolValue = false self.intValue = 1234567890 ! self.myClass!.reset() } !! func testBOOL(val: Bool) -> Bool { return val } }

Turnip feature !Feature: Test ! Scenario: Test Given Connection Establishment Given Application Reset Then Method BOOL Test Then Get Instance BOOL Test "false" Given Set Instance BOOL Test "true" Then Get Instance BOOL Test “true" Then Get Instance Int Test "1234567890" Given Set Instance Int Test "1234" Then Get Instance Int Test “1234" Given Connection Release

!step "Connection Establishment" do ! @adapter = ShumachTurnip::ConnectionAdapters::TCPAdapter.new '172.20.10.1', 8000 !end

!step "Method BOOL Test" do ! msg = “{\"target\":\"\",\”action\":{\”type\":\"method\",\"methodName\":\"testBOOL:\",\"args\":[\"YES\"]}}" @adapter.write msg ! response = @adapter.gets expect(response).to match '{"type":"method","methodName":"testBOOL:","return":true}' end

!step "Method BOOL Test" do ! @adapter.write msg ! response = @adapter.gets expect(response).to match '{"type":"method","methodName":"testBOOL:","return":true}' end

Turnip feature !Feature: Test ! Scenario: Test Given Connection Establishment Given Application Reset Then Method BOOL Test Then Get Instance BOOL Test "false" Given Set Instance BOOL Test "true" Then Get Instance BOOL Test “true" Then Get Instance Int Test "1234567890" Given Set Instance Int Test "1234" Then Get Instance Int Test “1234" Given Connection Release

Swift !class MainController: NSObject { ! var window: UIWindow? var turnip: ShumachTurnip? var boolValue: Bool = false var intValue: Int = 1234567890 var myClass : MyClass? !! init() { super.init() self.boolValue = false self.intValue = 1234567890 ! self.turnip = ShumachTurnip(port: 8000) self.turnip!.currentObject = self; } !! func reset() { self.boolValue = false self.intValue = 1234567890 ! self.myClass!.reset() } !! func testBOOL(val: Bool) -> Bool { return val } }

!step "Get Instance Int Test :value" do |val| ! msg = "{\"target\":\"\",\"action\":{\"type\":\"getInstanceValue\",\"args\":[{\"name\":\"intValue\",\"type\":\"i\"}]}}" @adapter.write msg ! response = @adapter.gets ! idx = response.length response.slice!(idx, 1) expect(response).to match '{\"type\":\"getInstanceValue\",\"success\":\"true\",\"return\":' + val + '}' end

!step "Get Instance Int Test :value" do |val| ! @adapter.write msg ! response = @adapter.gets ! idx = response.length response.slice!(idx, 1) expect(response).to match '{\"type\":\"getInstanceValue\",\"success\":\"true\",\"return\":' + val + '}' end

Turnip feature !Feature: Test ! Scenario: Test Given Connection Establishment Given Application Reset Then Method BOOL Test Then Get Instance BOOL Test "false" Given Set Instance BOOL Test "true" Then Get Instance BOOL Test “true" Then Get Instance Int Test "1234567890" Given Set Instance Int Test "1234" Then Get Instance Int Test “1234" Given Connection Release

Swift !class MainController: NSObject { ! var window: UIWindow? var turnip: ShumachTurnip? var boolValue: Bool = false var intValue: Int = 1234567890 var myClass : MyClass? !! init() { super.init() self.boolValue = false self.intValue = 1234567890 ! self.turnip = ShumachTurnip(port: 8000) self.turnip!.currentObject = self; } !! func reset() { self.boolValue = false self.intValue = 1234567890 ! self.myClass!.reset() } !! func testBOOL(val: Bool) -> Bool { return val } }

• https://github.com/shumach217/ShumachTurnip にサンプルがあるので見て下さい

ShumachTurnip• objective-cのruntimeな関数を使用して、

• 文字列からメソッドの実行

• 文字列からインスタンスの取得

• objective-cとSwiftは共存可能なので、Swiftでも実行可能!!

自動化のメリット• コマンド一つでiOSデバイスの操作を!!

• bundle exec rspec

• 複数のテストも!!

• 画面遷移のためのボタンを押さなくていい!!

• キーボードの入力をしなくていい!!

• iOS6 Betaはクセがあってめんどいですが、動作しています!!

• デモも可能ですので、興味ある方は声を掛けて下さい!!

御静聴、ありがとうございます。