iPhoneアプリ開発 デバッグと自動テスト

作成日:2020/07/01

お役立ちコラム

iPhoneアプリ開発 デバッグと自動テスト

前回は「iPhoneアプリ開発のはじめかた」と題して、iPhoneアプリの開発に必要なもの、必要な知識、その習得方法をご紹介しました。
今回はアプリ開発を始めたらまず必要となるデバッグについて解説します。
加えて単体テストの自動化についても触れます。
本コラムでは、前回同様、オンライン講座や市販の書籍では得にくい情報を含めて紹介していきます。

説明のために簡単なアプリを使いましょう。
花の名前とサムネイルの一覧を表示し、いずれかをクリックすると写真と花の名前と写真家の名前を表示するようにします。

このアプリのプログラムは Flowerというクラスを使います。
Flowerクラスは花の名前(name)、写真(photo)、写真家(photographer)という3つのプロパティーとイニシャライザ(init)を持ちます。
イニシャライザは花の名前が空だとオブジェクトの生成を失敗させてnilを返します。

ブレークポイント

上記コードの23行目に青い矢印がありますが、これはブレークポイントです。
行の左をクリックするとブレークポイントを追加できます。
もう一度クリックするとブレークポイントの色が薄くなり無効になります。
削除するには青い矢印を右側にドラッグするか、副ボタンでクリックしメニューを出して Delete Breakpoint を選びます。

プログラムを実行するとブレークポイントの行で停止します。
バラのサムネイルが表示されてないのでデバッグしてみましょう。
ここで Xcode のデバッガの最も基本的な4つのボタンを紹介します。

  1. Continue Program Execution:実行を継続します。
  2. Step over:現在の行を実行し、次の行に移って停止します。
  3. Step into:関数で停止している時は、その関数の中に入ります。
  4. Step out:現在いる関数のreturn行まで実行し関数を出ます。

ここで 2. Step overを3回クリックします。
変数の上にカーソルを持ってくると変数の値がポップアップされます。
name変数(=の右側のnameはイニシャライザの引数)には「ガーベラ」と入っていることが分かります。

photo変数にカーソルを持ってくるとオブジェクトIDが表示されます。
iボタンをクリックするとUIImageクラスのオブジェクトであることがわかります。

目のアイコンをクリックすると、photo変数に入っている画像を表示できます。

ブレークポイントはドラッグして移動できます。
ブレークポイントを23行目から26行目に移動します。
次いでname変数が「バラ」になるまで、1. Continue Program Executionを何度かクリックします。
バラのphoto変数の値を見ると nil になっています。

バラのサムネイルが表示されていなかったのは、バラの画像データが入っていなかったためとわかります。
原因にあたりがついている場合は、もっと効率よく調べることもできます。
例えばイニシャライザの最後の行にブレークポイントを追加し、副ボタンで Edit Breakpoint…を選びます。
そして Condition に

  photo == nil

と記述すると、photo変数がnilの場合にこの行で停止します。

ActionにはSound(音を出す)やDebugger Commandなど、ブレークポイントでのアクションを指定できます。
ここでは Log Messageを選び、name変数を表示するように指定しました。

  %B name = @name@

%Bはブレークポイントの名前、@name@はname変数の表示です。
このブレークポイント設定により、photo変数がnilであるFlowerオブジェクトのname変数をログに出力できます。(下記画面の下部右側がログ出力)

ブレークポイントの設定で、
Options □ Automatically continue after evaluating actions
にチェックを入れると、ブレークポイントで止まらずに実行を継続しますので、該当データが複数ある場合にすべて一括でログに出力できて便利です。

クラッシュの解析

アプリがクラッシュする場合も、デバッガがあると簡単に解析できます。
クラッシュした箇所で実行が止まり、デバッガ下部の左に変数一覧、右にログが表示されるため、容易にクラッシュの原因がわかります。
この場合は133行目でオプショナル型のflowerオブジェクトをアンラップする際に、flowerオブジェクトがnilなのでクラッシュしています。

デバッガーで132行目のname変数を見ると“”(空文字)になっています。
Flowerクラスのイニシャライザでは花の名前が空だとオブジェクトの生成を失敗させてnilを返していましたね。

  if name.isEmpty {
     return nil
  }


プログラムを修正し、オブジェクト生成に成功した時だけflower変数を配列に追加し、オブジェクト生成に失敗したときはエラーメッセージを出すようにします。
これでクラッシュはしません。

単体テストの自動化

次に自動テストについて見ていきましょう。
プロジェクトを作る際に

□ Include Unit Tests
□ Include UI Test

にチェックを入れると自動テストのターゲットとテストコードのテンプレートが作成されます。
下記の例では単体テスト(Unit Tests)だけにチェックを入れています。

自動テストのテンプレートには

  override func setUp() {}
  override func tearDown() {}


という空の関数が用意されています。
各テスト関数が呼ばれる前に setup()が呼ばれ、終了後にtearDown()が呼ばれます。
例えばテストにアプリケーションサーバーへの接続・切断が必要な場合などに使います。
今回は必要ないのでこれらの関数は削除しました。

下記がFlowerクラスのイニシャライザのテストコードを実行したところです。
Xcodeのメニュー Product → Test で自動テストを実行すると、テストコードのうち成功したクラスと関数に緑色のチェックが付きます。
画面左は Test navigator というツールで、ここからもテストの実行指示や結果のサマリー表示ができます。
テストケース数が多い場合は、テストコードよりもTest navigatorでサマリーを見た方が素早く結果を確認できます。

testFlowerInitializerSucceeds()という関数ではイニシャライザが成功するケースをテストします。
XCTAssertNotNilにはオブジェクトの生成に成功するはずのgerberaFlower変数を入れます。

  XCTAssertNotNil(gerberaFlower)

XCTAssert関数ではプロパティーのphotographerに正しく値が入っているかを確認します。

  XCTAssert(gerberaFlower?.photographer == "Andrew Small")

testFlowerInitializerFails()ではイニシャライザが失敗するケースをテストします。
XCTAssertNilにはオブジェクトの生成に成功するはずのnilFlower変数を入れます。

  XCTAssertNil(nilFlower)

もしもイニシャライザにバグがある場合、例えば花の名前が空である場合のチェックを忘れたときは、下記のようにテストコードの失敗したクラス、関数、XCTAssertに、赤い×マークが表示されます。

主要なクラスにデグレードがあるとアプリの広範囲に影響が出ます。せめて主要なクラスや構造体は自動テストのテストケースを作っておくことをお勧めします。
私自身はUIテストまでは自動化してないのですが、ご興味のある方は下記のような書籍が出版されていますので参考になさってください。

iOSアプリ開発自動テストの教科書
XCTestによる単体テスト・UIテストから、CI/CD、デバッグ技術まで
ISBN-13: 978-4297106294

いかがでしたでしょうか? 少しでもiPhoneアプリ開発入門のお役に立てれば幸いです。
次回はXcodeを使ったGitでのバージョン管理、および、XcodeとGitHubの連携について解説する予定です。
お楽しみに。

お問い合わせ

Xcodeでの開発用にはMacレンタルをご利用ください。

追加で開発用機材が必要な時にご利用ください。

開発用ワークステーションはこちら

お気軽にお問い合わせください

ページの先頭に戻る