Ruby Motionチュートリアルやってみた(8)


Ruby Motionチュートリアルをやってます。前回の記事はこちら。

Ruby Motionチュートリアルはこちら。

▼開発環境
Ruby 2.5.3
Xcode 10.1
Ruby Motion 5.16

さてさて、今回の章ではテストの自動化をやって行きましょう。

テストってめんどくさくて生産的じゃないからあんま好きじゃないけど、まぁ重要だよね。。。頑張ろう!!

とりあえず、テストするために新しいプロジェクト作ろうか。

$ motion create Tests
$ cd Tests

RubyMotionでは、specフォルダの*.rbファイルの一つ一つからテストを読み込むそうです。デフォルトでは、./spec/main_spec.rbファイルがあると思います。

describe "Application 'Tests'" do
 before do
   @app = UIApplication.sharedApplication
 end
 it "has one window" do
   @app.windows.size.should == 1
 end
end

このデフォルトのコードを読み解いて行きましょう!

クラスの代わりに、「describe」が定義されてますね。これは、itを複数書くことができるブロックになっているそうです。ちなみに、describeは入れ子にすることもできるそうです。

次は「before」ブロックをみましょう。基本的に「it」ブロックでテストを実行するのですが、このitを実行する前に処理をするのがbeforeになりますね。まぁ、名前のままだね。普通にオブジェクトをリセットするとかテスト項目の初期化する場所ですね。

beforeブロックの中身は、「UIApplication.sharedApplication」が定義されています。これはアプリケーションのインスタンスを返すメソッドになっています。

次に、itブロックの中身をみてみましょう。@app.windows.size.should == 1となっていますね。

「==」は比較演算子なので、true、falseのどちらかが帰ってくるはずです。ちなみに、「@app.windows.size.should == 1」は「もしsizeが1と等しくなければテストが失敗する」という意味になるそうです。

shouldは、多分テストに対して使うメソッドかな?んで、テストの失敗か成功を返すメソッドだと思います。(コンソールでは使えなかったので)

では、実際にテストを実行してみましょう!「rake spec」を実行してみます。

うん!failuresも、errorsも0になってるね!いい感じ♪

次は何かイベントが起きた時のテストをどのようにやって行くのかをみていきましょう!

なんか、RubyMotionではコールバックイベントを呼び出すんじゃなくて、「tap button」みたいな記述でテストできるらしいですよ?

実際の中身はコールバックしてるのかもしれないけど。

ちなみに、単一のUIViewControllerをテストすることしかできず、複数のコントローラを使うことはできないそうです。

では、ボタンをタップした時のテストをするために、そもそもボタンをタップしたら何か動作するようにアプリケーションを作っていきましょう。

./app/ButtonController.rbを用意して次のコードを記述していきます。

class ButtonController < UIViewController
 def viewDidLoad
   super
   @button = UIButton.buttonWithType(UIButtonTypeRoundedRect)
   @button.setTitle("Test me title!", forState:UIControlStateNormal)
   @button.accessibilityLabel = "Test me!"
   @button.sizeToFit
   self.view.addSubview(@button)
   @button.addTarget(self, action:'tapped', forControlEvents:UIControlEventTouchUpInside)
 end
 def tapped
   p "I'm tapped!"
   @was_tapped = true
 end
end

うん、「accessibilityLabel」以外は特に説明なくても大丈夫かな?

んで、「accessibilityLabel」はそれぞれのUIViewで利用できる文字列を扱うプロパティだそうです。

なんかデバイスのVoiceOver機能を利用する際にオペレーティングシステムによって読み上げられるテキストとして使用されるそうです。よくわかんないけど、アプリの読み上げ機能に使われるってこと??

んで、なんでこれを入れているかっていうと、RubyMotionの機能テストは「accessibilityLabel」を元にビューを探すからだそうです!

最後に、AppDelegateにButtonControllerを関連付けましょう。

def application(application, didFinishLaunchingWithOptions:launchOptions)
 @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.applicationFrame)
 @window.backgroundColor = UIColor.whiteColor
 @window.makeKeyAndVisible
 @view_controller = ButtonController.alloc.initWithNibName(nil, bundle:nil)
 @window.rootViewController = @view_controller
 true
end

さぁ、rakeを実行して、表示された「Test me title!」をタップしてみましょう!

うん!タップしたら、ちゃんとターミナルに「I'm tapped!」って表示された!

次に変数が用意されているか確認するためにTestを書いていきましょう!

main_spe.rbで新しくdescribeブロックを追加します。

describe "button controller" do
 tests ButtonController
 it "changes instance variable when button is tapped" do
   tap 'Test me!'
   controller.instance_variable_get("@was_tapped").should == true
 end
end

「tests <class>」はdescribeと指定されたUIViewControllerのクラスと結びつけるそうです。その時、UIWindowとテストするコントローラをインスタンス化するそうです。

要するに、テスト内でウィンドウとコントローラはそれぞれ、「window」と「contorller」でアクセス可能ってことですね。

コントローラをテストするにはSpecを用意し、itブロックでアサーションを行うということになるわけですね!ちなみに、アサーションって何?って方はこちら。

次は、tapメソッドですね。これは、UIViewのオブジェクトからaccessibilityLavelの値を取るそうです。

UIButtonとUILabelではデフォルトで自分のtitleの値をaccwssibilityLabelとして使用できるそうです。

tapの他にも、flick、drag、pinch_close、pinch_open,rotateも使うことができるそうです。

まぁ、個人的にはゲームでもない限りピンチアウト/インとか回転とか使ったことないけどね〜。

ちなみに、詳細は以下にあるらしい。

(このサイトがあれば、この章での説明っていらなくね...?)
さぁ、最後にrake specを実行して、テストが成功することを確認しましょう!

ふぇ??失敗したんだけどwww

「@was_tapped」がtrueになっていない...だと?

んー、色々やってみたけど、わからんなぁ。。。スペルミスを調べたけど、間違ってるとこなさそうだし...。

んー、そもそもtapの動きがよくわからんなぁ。実機のように動作するのであれば、「p "I'm tapped!"」でコンソールにメッセージが表示されても良さそうなんだけど...。

うん!わからん!!!!誰か教えてくださいwww

というわけど、テストの章は終了でーす!

いつか、理解したら追記しますね♪

では、いつものまとめ。

Wrapping Up
私たちは RubyMotion で難なくテストを書くことができます。もし、みなさんがこれまでプロジェクトでテストを書かれていないのでしたら、今から始めない理由はありません。

今日はテストについてどんなことを学んだでしょう?

・RubyMotion は ./spec ディレクトリからテストを読み込みます。
・テストは describe と it ブロックの集まりです。これらはラベルを引数に取り、同じようなテストをグループ分けするのに役に立ちます。
・<any object>.should は値が等しいかチェックする際に用います。 例 : greeting.should == "hello"
・UIViewController には機能テストがあり、tap や pinch のようなイベントをシミュレートしてくれます。describe ブロックで、これらの機能を有効にするために tests <controller class> を用います。
・tap <accessibility label> は、ビューに設定した accessibilityLabel プロパティを引数に設定し、tap をコードから実行します。

さ〜て、次の章はHTTPリクエストを実行する方法について勉強していきましょう!!





サポートしていただけると、泣いて喜びます! 嬉しくて仕事をめちゃめちゃ頑張れます。