単体テストの作成。 モックオブジェクト

単体テストが必要なのは誰ですか? あなたのためではありません-あなたのコードは完璧です。 それでも、この記事を読むだけで、Swiftでの単体テストの記述について詳しく説明できます。 突然、これは後で便利になります。

ユニットテストは、完璧なコードを書くための素晴らしい方法です。 テストは、プロジェクト作成の初期段階でエラーの大部分を見つけるのに役立ちます。 経験が示すように、コードのテストが困難な場合、そのサポートまたはデバッグが困難になります。

単体テストは、孤立した「マイクロコンポーネント」で動作します。 多くの場合、クラスを「ウェット」にする必要があります。つまり、テストできるように、特定のマイクロコンポーネントを分離するための偽の機能実装を提供します。 Objective-Cには、これを実装するのに役立ついくつかのサードパーティフレームワークがあります。 しかし、 Swiftではまだ利用できません。

このガイドでは、お友達の誕生日を思い出すのに役立つ簡単なアプリケーションをテストでカバーするために、独自のモックオブジェクト、偽物、およびスタブを作成する方法を学習します。

さあ始めましょう

スタータープロジェクトをダウンロードするこれは連絡先ストレージアプリケーションです。 基本アプリケーションの機能には取り組みません。 むしろ、アプリケーションが正常に動作していることを確認するためのテストをいくつか作成します。

アプリケーションをコンパイルして実行し、動作をテストします。 プラスボタンをクリックして、 John Appleseedを共有連絡先リストに追加します。

画像

連絡先を保存するために、アプリケーションはCore Dataを使用します。

画像

パニックにならないでください! このチュートリアルではコアデータの経験は必要ありません。 このため、特別なスキルは必要ありません。

単体テストの長所と短所

テストの作成に関しては、良いニュースと悪いニュースの両方に出くわします。 残念なことに、ユニットテストには次のような欠点があります。



完全な解決策はありませんが、明るい面があります。テストを書くことには、次の利点があります。



基本的なアプリケーション構造

アプリケーションの大量のコードは、 コアデータが有効になっているマスター/詳細アプリケーションテンプレートに基づいています。 ただし、コードテンプレートにはいくつかの重要な改善点があります。 Xcodeでプロジェクトを開き、プロジェクトナビゲーターを確認します。

画像

以下の詳細を考慮してください。


PeopleView内のファイルのコレクションは、大きなView Controllerを回避します。 大きなView Controllerを回避するために、単純なプロトコルを介してView Controllerに接続する他のクラスに一部の責任をシフトできます。 古い興味深い記事ではありますが、この興味深い記事を読むことで、大規模なView Controllerとその回避方法について学ぶことができます。

この場合、プロトコルはPeopleListDataProviderProtocol.swiftで定義されています。 それを開いて見てください。 このプロトコルに準拠するクラスには、プロパティmanagedObjectContextおよびtableViewが必要であり、 addPerson(_ :)およびfetch()メソッドを定義する必要があります。 さらに、 UITableViewDataSourceプロトコルに準拠する必要があります。

ビューコントローラーPeopleListViewControllerには、 PeopleListDataProviderProtocolプロトコルに準拠するdataProviderプロパティがあります。 このプロパティは、AppDelegate.swiftファイルのPeopleListDataProviderインスタンスに設定されます。

ABPeoplePickerNavigationControllerを使用して、連絡先リストに新しい人を追加します。 このクラスを使用すると、開発者は許可なしにユーザーの連絡先にアクセスできます。

PeopleListDataProviderは 、Table Viewにデータを取り込み、 Core Dataにアクセスする役割を果たします。

注:プロジェクト内のいくつかのクラスとメソッドはパブリックとして宣言されています。 テストターゲットがクラスとメソッドにアクセスできるようにします。 テストの対象は、アプリケーションモジュールの外部です。 アクセス修飾子を追加しない場合、クラスとメソッドはinternalとして定義されます。 これは、同じモジュールでのみ利用できることを意味します。 モジュールの外部から(たとえば、テストのターゲットから)それらにアクセスするには、 パブリックアクセス修飾子を追加する必要があります。

それでは、テストを作成しましょう!

モックオブジェクトの作成

モックオブジェクトを使用すると、メソッド呼び出しが行われたか、プロパティが設定されているかを確認できます。 たとえば、 PeopleListViewControllerのviewDidLoad()では、テーブルビューがdataProviderの tableViewプロパティに設定されます

実際に何が起こっているのかを確認するテストを作成します。

テスト用のアプリケーションの準備

まず、テストを作成するためのプロジェクトを準備する必要があります。

プロジェクトナビゲータでプロジェクトを選択し、誕生日テストターゲットでビルド設定を選択します。 以下に示すように、 Definesモジュールを見つけて、設定をYesに変更します。

画像

次に、 BirthdaysTestsフォルダーを選択し、 File \ New \ File ...を参照します。 iOS \ Source \ Test Case Classを選択して、Nextをクリックし、 PeopleListViewControllerTestsという名前を付け、 Swiftファイルを作成したことを確認し、もう一度NextをクリックしてからCreateをクリックします

Xcodeで結合ヘッダーを作成するように求められたら、[ いいえ]を選択します これは、ターゲットにファイルがなく、新しいSwiftファイルを追加したときに発生するXcodeのエラーです。

新しく作成したPeopleListViewControllerTests.swiftを開きます。 以下に示すように、 import Birthdaysステートメントを他のimportステートメントの直後に追加して、オンにしたばかりのモジュールをインポートします。

import UIKit import XCTest import Birthdays 

次の2つの定型的な方法を削除します。

 func testExample() { // This is an example of a functional test case. XCTAssert(true, "Pass") } func testPerformanceExample() { // This is an example of a performance test case. self.measureBlock() { // Put the code you want to measure the time of here. } } 

PeopleListViewControllerのインスタンスが必要になったため、テストで使用できます。

PeopleListViewControllerTestsの上部に次の行を追加します

 var viewController: PeopleListViewController! 

次に、setUp()メソッドを次のコードに置き換えます。

 override func setUp() { super.setUp() viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("PeopleListViewController") as! PeopleListViewController } 

ストーリーボードを使用してPeopleListViewControllerをインスタンス化し、それをviewControllerに割り当てます。

Product \ Testを選択します。 Xcodeはプロジェクトをコンパイルし、既存のテストを実行します。 テストはまだありませんが、これにより、すべてが正しく構成されていることを確認できます。 数秒後、 Xcodeはすべてのテストが成功したことを報告するはずです。

これで、最初のモックオブジェクトを作成する準備ができました。

最初のMockオブジェクトを書く

Core Dataで作業するため、 Birthishsインポート行の直後にPeopleListViewControllerTests.swiftまで次のインポートを追加します。

 import CoreData 

次に、次のコードをPeopleListViewControllerTestsクラス定義に追加します。

 class MockDataProvider: NSObject, PeopleListDataProviderProtocol { var managedObjectContext: NSManagedObjectContext? weak var tableView: UITableView! func addPerson(personInfo: PersonInfo) { } func fetch() { } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { return UITableViewCell() } } 

これはかなり複雑なモックオブジェクトのようです。 ただし、このモッククラスのインスタンスをPeopleListViewController dataProviderプロパティに割り当てるため、これは単に最低限必要な最小限のものです。 モッククラスは、 PeopleListDataProviderProtocolおよびUITableViewDataSourceプロトコルにも準拠する必要があります。

Product \ Testを選択します。 プロジェクトが再度コンパイルされ、テストがUrに合格します。 しかし、モックオブジェクトを使用した最初のユニットテスト用にすべてを設定できました。

単体テストは、3つの部分に分け、名前を付け、 指定されたいつ 、およびの順にする必要があります。 ' Given 'は環境を設定します。 ' when 'は、テストする必要のあるコードを実行します。 「then」は期待される結果を確認します。

テストでは、 viewDidLoad()メソッドの実行後にデータプロバイダーのtableViewプロパティが設定されいることを確認します。

PeopleListViewControllerTestsに次のテストを追加します

 func testDataProviderHasTableViewPropertySetAfterLoading() { // given // 1 let mockDataProvider = MockDataProvider() viewController.dataProvider = mockDataProvider // when // 2 XCTAssertNil(mockDataProvider.tableView, "Before loading the table view should be nil") // 3 let _ = viewController.view // then // 4 XCTAssertTrue(mockDataProvider.tableView != nil, "The table view should be set") XCTAssert(mockDataProvider.tableView === viewController.tableView, "The table view should be set to the table view of the data source") } 

上記のテストの仕組みは次のとおりです。
  1. MockDataProviderのインスタンスを作成し、dataProviderのView Controllerプロパティに設定します。
  2. テストを開始する前に、tableViewプロパティがnilであることを確認します。
  3. viewDidLoad()を実行するビューにアクセスできます。
  4. テストクラスtableViewのプロパティがnilではなく、プロパティがView ControllerのtableViewに設定されていることを確認します。


次に、 Product \ Testを再度選択します。 テストが完了したらすぐに、ナビゲーターを開きます( Cmd + 5-便利なショートカットキー)。 次のように表示されます。

画像

モックオブジェクトを使用した最初のテストは成功しました!

addPerson(_ :)メソッドのテスト

次のテストでは、リストから連絡先を選択するとaddPerson(_ :)メソッドが呼び出されることを確認します

次のプロパティをMockDataProviderクラスに追加します。

 var addPersonGotCalled = false 

次に、 addPerson(_ :)メソッドを次のものに置き換えます。

 func addPerson(personInfo: PersonInfo) { addPersonGotCalled = true } 

ここで、 addPerson(_ :)を呼び出すときに、 trueMockDataProviderに設定してインスタンスに登録します。

この動作をテストするメソッドを追加する前に、 AddressBookUIフレームワークをインポートする必要があります。

PeopleListViewControllerTests.swiftに次のインポートを追加します。

 import AddressBookUI 

次のテストメソッドを残りのテストスクリプトに追加します。

 func testCallsAddPersonOfThePeopleDataSourceAfterAddingAPersion() { // given let mockDataSource = MockDataProvider() // 1 viewController.dataProvider = mockDataSource // when // 2 let record: ABRecord = ABPersonCreate().takeRetainedValue() ABRecordSetValue(record, kABPersonFirstNameProperty, "TestFirstname", nil) ABRecordSetValue(record, kABPersonLastNameProperty, "TestLastname", nil) ABRecordSetValue(record, kABPersonBirthdayProperty, NSDate(), nil) // 3 viewController.peoplePickerNavigationController(ABPeoplePickerNavigationController(), didSelectPerson: record) // then // 4 XCTAssert(mockDataSource.addPersonGotCalled, "addPerson should have been called") } 

ここで何が起こっているのでしょうか?

  1. 最初に、View Controllerデータプロバイダーを偽のデータプロバイダーのインスタンスにインストールします。
  2. 次に、 ABPersonCreate()を使用して連絡先を作成します。
  3. ここでは、デリゲートメソッドpeoplePickerNavigationController(_:didSelectPerson :)を手動で呼び出します。 デリゲートメソッドを手動で手動で呼び出すことは、悪いコードの兆候ですが、テストの目的には適しています。
  4. 最後に、 addPerson(_ :)が呼び出されたことを確認し、 addPersonGotCalledがtrueであることを確認します。


Product \ Testを選択して、 テストを実行します。 これは非常に簡単な作業であることがわかりました!

しかし、待ってください! 時間をかけてください! テストが実際にあなたがテストしたと思うものをテストすることをどうやって知っていますか

画像

テストを確認する

テストが実際に何かをチェックしていることを確認する簡単な方法は、テストがチェックしているオブジェクトを削除することです。

PeopleListViewController.swiftを開き 、次の行peoplePickerNavigationController(_:didSelectPerson :)をコメントアウトします

 dataProvider?.addPerson(person) 

テストを再度実行します。 今書いた最後のテストは失敗するはずです。 傑作-あなたのテストは実際に何かをテストしていることを知っています。 テストを確認してください。 少なくとも、最も複雑なテストをチェックして、それらが機能することを確認する必要があります。

画像

行のコメントを解除して、コードを動作状態に戻します。 テストを再度実行して、すべてが機能していることを確認します。

Apple Frameworkクラスのモック

NSUserDefaults.standardUserDefaults()NSNotificationCenter.defaultCenter()などのシングル トーンを使用できますが、デフォルト値をどのようにテストしますか? Appleは、これらのクラスのステータスを確認することを許可していません。

期待される結果のオブザーバーとしてテストクラスを追加できます。 ただし、これらのクラスの実装に依存するため、テストの速度が低下し、信頼性が低下する可能性があります。 または、コードの別の部分から値を設定でき、孤立した動作をテストしませんでした。

これらの制限を回避するには、これらのシングルトーンの代わりにモックオブジェクトを使用できます。

注: Appleクラスを模擬オブジェクトに置き換える場合、実装の詳細はいつでも変更される可能性があるため、そのクラスの動作ではなく、そのクラスとの相互作用を確認することが非常に重要です。

アプリケーションをコンパイルして実行します。 John AppleseedDavid Taylorを人のリストに追加し、 「姓」 名」の間でソートを切り替えます。 リスト内の連絡先の順序は並べ替えに依存することがわかります。

ソートを担当するコードは、 PeopleListViewController.swiftのchangeSort()メソッドにあります。

 @IBAction func changeSorting(sender: UISegmentedControl) { userDefaults.setInteger(sender.selectedSegmentIndex, forKey: "sort") dataProvider?.fetch() } 

NSUserDefaultsのキーでソートするために選択されたセグメントインデックスを追加し、 fetch()メソッドを呼び出します。 fetch()メソッドは、 NSUserDefaultsでこの新しいソート順を読み取り、 PeopleListDataProviderで示されている連絡先リストを更新する必要があります。

 let sortKey = NSUserDefaults.standardUserDefaults().integerForKey("sort") == 0 ? "lastName" : "firstName" let sortDescriptor = NSSortDescriptor(key: sortKey, ascending: true) let sortDescriptors = [sortDescriptor] fetchedResultsController.fetchRequest.sortDescriptors = sortDescriptors var error: NSError? = nil if !fetchedResultsController.performFetch(&error) { println("error: \(error)") } tableView.reloadData() } 

PeopleListDataProviderNSFetchedResultsControllerを使用してCore Dataからデータを取得します。 リストの並べ替えを置き換えるには、 fetch()は並べ替え記述子を使用して配列を作成し、選択した結果コントローラーの選択クエリに設定します。 その後、フェッチしてリストを更新し、テーブルでreloadData()メソッドを呼び出します。

NSUserDefaultsでユーザーの優先ソート順が正しく設定されていることを確認するテストを追加します

PeopleListViewControllerTests.swiftを開きMockdataproviderクラス定義の下に次のクラス定義を追加します。
 class MockUserDefaults: NSUserDefaults { var sortWasChanged = false override func setInteger(value: Int, forKey defaultName: String) { if defaultName == "sort" { sortWasChanged = true } } } 

MockUserDefaultsNSUserDefaultsのサブクラスです。 デフォルト値がfalseの booleanプロパティsortWasChangedがあります。 また、 setInteger(_:forKey :)メソッドをオーバーライドし、 sortWasChanged値をtrueに変更します

PeopleListViewControllerTestsクラスの最後のテストの下に次のテストを追加します。

 func testSortingCanBeChanged() { // given // 1 let mockUserDefaults = MockUserDefaults(suiteName: "testing")! viewController.userDefaults = mockUserDefaults // when // 2 let segmentedControl = UISegmentedControl() segmentedControl.selectedSegmentIndex = 0 segmentedControl.addTarget(viewController, action: "changeSorting:", forControlEvents: .ValueChanged) segmentedControl.sendActionsForControlEvents(.ValueChanged) // then // 3 XCTAssertTrue(mockUserDefaults.sortWasChanged, "Sort value in user defaults should be altered") } 

このチェックのレポートは次のとおりです。
  1. 最初にMockUserDefaultsのインスタンスをView ControllerのuserDefaultsに割り当てます。 この手法は、依存性注入として知られています。
  2. 次に、 UISegmentedControlのインスタンスを作成し、View Controllerを.ValueChangedのターゲットとして追加します。
  3. 最後に、 setInteger(_:forKey :)ユーザーのモックがデフォルトで呼び出されたことを確認します。 値が実際にNSUserDefaultsに保存されたかどうかを確認していることに注意してください。


テストスイートを実行します。すべてが正常に完了するはずです。

本当に複雑なAPIまたはフレームワークを持っているが、小さなコンポーネントを本当にテストしたい場合は、フレームワークを深く掘り下げないでください。

それは、あなたがそれを「偽造」し、作成しないときです! :]

偽物オブジェクトの作成

偽物オブジェクトは、偽物のクラスの完全な実装のように動作します。 それらは、扱いにくいクラスまたは構造の代わりとして使用します。

アプリケーションの場合、レコードを追加してCore Dataで選択する必要はありません。 そのため、代わりにCore Dataを偽造します。 少し恐ろしいですね。

BirthdaysTestsフォルダーを選択し、 File \ New \ File ...に移動します。 iOS \ Source \ Test Case Classテンプレートを選択し、 Nextをクリックします。 クラスにPeopleListDataProviderTestsという名前を付け、「 次へ」をクリックしてから 作成 をクリックします

作成したテストクラスの不要なテストを再度削除します。

 func testExample() { // ... } func testPerformanceExample() { // ... } 

次の2つのインポートを新しいクラスに追加します。

 import Birthdays import CoreData 

次に、次のプロパティを追加します。

 var storeCoordinator: NSPersistentStoreCoordinator! var managedObjectContext: NSManagedObjectContext! var managedObjectModel: NSManagedObjectModel! var store: NSPersistentStore! var dataProvider: PeopleListDataProvider! 

プロパティには、 コアデータスタックで使用される主要コンポーネントが含まれています。 Core Dataの使用を開始するには、 Core Dataチュートリアルをご覧ください。

次のコードをsetUp()メソッドに追加します。

 // 1 managedObjectModel = NSManagedObjectModel.mergedModelFromBundles(nil) storeCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel) store = storeCoordinator.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil, error: nil) managedObjectContext = NSManagedObjectContext() managedObjectContext.persistentStoreCoordinator = storeCoordinator // 2 dataProvider = PeopleListDataProvider() dataProvider.managedObjectContext = managedObjectContext 

上記のコードで起こることは次のとおりです。

  1. setUp()は、メモリ内のストレージを使用して管理対象オブジェクトのコンテキストを作成します。 通常、 コアデータはデバイスのファイルシステム内のファイルです。 これらのテストでは、デバイスのメモリに「永続的な」ストレージを作成します。
  2. 次に、PeopleListDataProviderのインスタンスと、管理対象オブジェクトコンテキストを作成し、管理対象オブジェクトコンテキストを管理対象オブジェクトコンテキストとして設定されたメモリに保存します。 これは、新しいデータプロバイダーが実際のように動作することを意味しますが、Core Dataでオブジェクトを追加または削除しません。


次の2つのプロパティをPeopleListDataProviderTestsに追加します。

 var tableView: UITableView! var testRecord: PersonInfo! 

次に、 setUp()メソッドの最後に次のコードを追加します。
 let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("PeopleListViewController") as! PeopleListViewController viewController.dataProvider = dataProvider tableView = viewController.tableView testRecord = PersonInfo(firstName: "TestFirstName", lastName: "TestLastName", birthday: NSDate()) 

これにより、ストーリーボードでView Controllerをインスタンス化してTable Viewをセットアップし、テストで使用するPersonInfoのインスタンスを作成します。

テストが完了したら、管理対象エンティティのコンテキストを「リセット」する必要があります。

tearDown()メソッド次のコードに置き換えます。

 override func tearDown() { managedObjectContext = nil var error: NSError? = nil XCTAssert(storeCoordinator.removePersistentStore(store, error: &error), "couldn't remove persistent store: \(error)") super.tearDown() } 

このコードは、managedObjectContextをnilに設定してメモリを解放し、ストアコーディネーターから永続ストアを削除します。 新しいテストリポジトリを使用して各テストを実行できます。

今-テストを書くことができます! 次のテストをテストクラスに追加します。

 func testThatStoreIsSetUp() { XCTAssertNotNil(store, "no persistent store") } 

このテストでは、ストレージが空ではないことを確認します。 新しいテストを実行します-すべてが成功するはずです。

次のテストでは、データソースが予想される行数を提供するかどうかを確認します。

次のテストをテストクラスに追加します。

 func testOnePersonInThePersistantStoreResultsInOneRow() { dataProvider.addPerson(testRecord) XCTAssertEqual(tableView.dataSource!.tableView(tableView, numberOfRowsInSection: 0), 1, "After adding one person number of rows is not 1") } 

最初に連絡先をテストリポジトリに追加してから、行数が1であることを確認します。
テストを実行します-すべて成功するはずです。

偽の「永続的な」ストレージを作成することにより、迅速なテストを提供し、ディスクをクリーンな状態に保つことができるため、起動時にアプリケーションが期待どおりに動作することを確認できます。

テストを書いた2つ以上のテスト連絡先を追加した後、セクションと行の数を確認することもできます。 それはすべて、プロジェクトで達成しようとしている自信のレベルに依存します。

プロジェクトで一度に複数のチームと作業したことがある場合、プロジェクトのすべての部分が同時に準備ができているわけではないことを知っていますが、すでにコードをテストする必要があります。 しかし、Webサービスなど、存在しないものについてコードの一部をどのようにテストできますか?

スタブがあなたの助けになります!

スタブを書く

スタブはオブジェクトメソッド呼び出しへの応答を偽装します。 スタブを使用して、まだ開発中のWebサービス呼び出しコードをテストします。

プロジェクトのWebチームは、アプリケーションと同じ機能を備えたWebサービスの作成を任されました。 ユーザーはサービスにアカウントを作成し、アプリケーションとサービス間でデータを同期できます。 しかし、Webチームは作業の一部を開始することさえしなかったため、ほぼ完了です。 スタブを作成してWebサーバーコンポーネントを置き換える必要があるようです。

このセクションでは、2つのメソッドのテストの作成に焦点を当てます。1つはサイトに追加された連絡先を選択する方法、もう1つはアプリケーションからWebサービスに連絡先を追加する方法です。 実際のシナリオでは、ユーザー名とアカウント、およびエラー処理が必要になりますが、別のときに行います。

APICommunicatorProtocol.swiftを開きます 。 このプロトコルは、Webサービスから連絡先を受信し、連絡先を追加するための2つのメソッドを宣言します。

Personのインスタンスを移動できますが、管理対象エンティティには別のコンテキストが必要です。 この場合、構造の使用がはるかに簡単になりました。

次に、スタブを作成して、View ControllerとAPICommunicatorインスタンスの相互作用をサポートします。

PeopleListViewControllerTests.swiftを開き、 PeopleListViewControllerTestsクラス内に次のクラス定義を追加します。

 // 1 class MockAPICommunicator: APICommunicatorProtocol { var allPersonInfo = [PersonInfo]() var postPersonGotCalled = false // 2 func getPeople() -> (NSError?, [PersonInfo]?) { return (nil, allPersonInfo) } // 3 func postPerson(personInfo: PersonInfo) -> NSError? { postPersonGotCalled = true return nil } } 

注意すべきこと:
  1. APICommunicatorが構造体であっても、モックの実装はクラスです。 この場合、テストではデータを変更する必要があるため、クラスを使用する方が便利です。 これは、構造よりもクラスで行う方が少し簡単です。
  2. getPeople()メソッドは、allPersonInfoに保存されているものを返します。 ネットワークからデータをダウンロードする代わりに、単純な配列に連絡先情報を保存するだけです。
  3. postPerson(_ :)メソッドは、postPersonGotCalledにtrueを設定します。


スタブAPIをテストして、 addPerson()メソッドを呼び出したときに、APIから返されるすべての連絡先がリポジトリに追加されることを確認します

PeopleListViewControllerTestsに次のテストメソッドを追加します。

 func testFetchingPeopleFromAPICallsAddPeople() { // given // 1 let mockDataProvider = MockDataProvider() viewController.dataProvider = mockDataProvider // 2 let mockCommunicator = MockAPICommunicator() mockCommunicator.allPersonInfo = [PersonInfo(firstName: "firstname", lastName: "lastname", birthday: NSDate())] viewController.communicator = mockCommunicator // when viewController.fetchPeopleFromAPI() // then // 3 XCTAssert(mockDataProvider.addPersonGotCalled, "addPerson should have been called") } 

上記のコードで起こることは次のとおりです。
  1. 最初に、テストで使用するmockDataProviderおよびmockCommunicatorシミュレートオブジェクトを構成します。
  2. 次に、偽の連絡先を作成し、 fetchPeopleFromAPI()メソッドを呼び出して偽のネットワーク呼び出しを行います。
  3. 最後に、 addPerson(_ :)メソッドをテストします。

テストをコンパイルして実行します。

それでは、次は何ですか?

プロジェクトの最終バージョンをダウンロードします 。このバージョンには、この記事では説明しなかった追加のテストも含まれています。

アプリケーションのマイクロコンポーネントをテストするための模擬オブジェクト、偽物、およびスタブの作成方法を学び、 Swiftで XCTestがどのように機能するかを理解しました。

この記事では、テストの最初の理解のみを示します。 アプリケーションのテストを作成するためのアイデアがすでにあると確信しています。

単体テストの詳細については、 テスト駆動開発(TDD)および動作駆動開発(BDD)をご覧ください。 これらは、コードを書く前にテストを書くアプリケーション開発方法論です(そして、率直に言って、まったく新しい考え方を表します)。

単体テストは、完全なテストスイートの一部にすぎません。 包括的なテストは次の論理的なステップです。 包括的なテストを開始する簡単な方法は、 UIAutomationを使用することです。 アプリケーションのテストを真剣に考えている場合は、 UIAutomationを使用する必要があります。

psこの記事は2015年9月9日より前に作成されたため、サンプルの作成にはSwiftバージョン1.2が使用されました。 Swift言語の新しいバージョンのリリースに関連して、例にいくつかの変更を加えました。 プロジェクトのソースコードは、 こちらこちらにあります

Source: https://habr.com/ru/post/J267255/


All Articles