4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

iOSアプリでテストを書く前に知っておきたいこと

Posted at

はじめに

こんにちは、iOSエンジニアの dayossi です。

家族が幸せになれるサービスを提供したいと思って、
HaloHaloという家族日記アプリをリリースしています。

今回は、ユニットテストについて
よくわかっていなかった前提条件を整理したいと思います。

そもそもユニットテストとは?

アプリが起動した状態でも
コードが作用するのか、継続的にチェックするための手法です。

print()でのデバッグでは、単一の処理結果や変数の値をチェックすることはできますが
他の場面で同様の処理があった場合、
ふたたびprint()を記述する必要があります。

また、同じ処理が何度も出てくるのであれば、
統一したフォーマットで繰り返し使用可能な状態に管理するほうが
可読性が上がり、何をテストしているのかが明確になります。

ユニットテストは、統一したフォーマット下で
繰り返し行う処理の結果を、自動的に繰り返し得られるように
作ることができるツールなのだそうです。

(参考図書 : iOSテスト全書(2019) 第1章より)

ユニットテスト導入前に知っておきたいこと

ここからが本題となります。

ユニットテストのメリットはわかったのですが、
逆に「処理を繰り返し呼び出せる設計で書けてないと、テストできない」
とも考えられそうです。

この点を私はよくわかっていなかったので、
以下、順に整理していきます。

ユニットテストができるアプリ設計か?

例えば、特定のクラスにある処理を
毎回そのクラスをインスタンス化して、処理を呼び出している場合。

これはクラスに依存しているケースであり、
処理とクラスが分離できていない状態です。

以下のように、ViewController内に記述したsortAscendData()を
OtherViewCotrollerで使用したい場合、

このままだとViewControllerをわざわざインスタンス化して呼び出したり
同じコードをOtherViewCotrollerに記述する手間が発生します。

同じ様な手間がいくつも発生すると、記述するコード量がムダに増えたり、
アプリ全体の挙動をチェックするときに、どこでバグが起こったのか把握しづらくなります。

// 参照されるViewController
import UIKit

class ViewController: UIViewController {

    
    var userDataCollection:[String] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
      
        // Viewの描画
        setupView()
    }

    func setupView(){
        // Viewを描画
        self.view.addSubview(<#T##view: UIView##UIView#>)
    }
    
    func getUserData(){
        // ユーザーデータ取得処理
    }
    
    func reloadView(){
        // Viewの再描画
    }
    
    func didTacAction(){
        // タップ動作の検知
    }
    
    func sortAscendData(_ userDataCollection:Array<String>){
        // データの並べ替え処理
    }
}
// 参照したいViewController

class OtherViewController: UIViewController {
    
    // 表示用データが格納されていて、並び替えたい...
    var otherUserData: [String] = []

    let vc = ViewController()
    vc.sortAscendData(self.otherUserData)

    // MARK:- ホントに必要なのは、コレだけなのに...    
    func sortAscendData(_ userDataCollection:Array<String>){
        // データの並べ替え処理
    }
}

さまざまな場面で使われている共通の処理は
protocolで抽象化しておくと、

特定のクラスに依存することなく、
またprotocolで共通化した処理があることも明確になるので
よりアプリ全体の挙動をチェックしやすくなります。

そのため、ファイルごとに責務が分担できていないと
テストしたい処理を抽出することが難しくなるので、

まずは「どこで、どんな責務を担っているのか?」が明確にできる設計を
考えておくことが重要と思います。

まとめ

設計を意識するということは、
どの役割をどのファイルで管理しているのかを明確にすることと言えそうです。

管理するファイル数は必然的に多くなると思いますが、
テストユニットによる自動検証と目視でのチェックの両方がやりやすくなるので
開発スピードを意識する場面でも有効そうだと思います。

ユニットテスト、どんどん書いていきます!

(「ここ、こう考えてもいいんじゃない?」など、温かいツッコミをいただけますと幸いです)

参考書籍・記事

松尾 和昭, 細沼 祐介,田中 賢治 他.iOSテスト全書(2019)
Swiftユニットテスト入門
コードを書きながら同時に設計していくためのiOSアプリ開発方針
今更MVCとかでiOSアプリつくってみた(Swift)・改

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?