単䜓テストの䜜成。 モックオブゞェクト

単䜓テストが必芁なのは誰ですか あなたのためではありたせん-あなたのコヌドは完璧です。 それでも、この蚘事を読むだけで、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_ :)を呌び出すずきに、 trueをMockDataProviderに蚭定しおむンスタンスに登録したす。



この動䜜をテストするメ゜ッドを远加する前に、 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 AppleseedずDavid 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() }
      
      





PeopleListDataProviderはNSFetchedResultsControllerを䜿甚しお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 } } }
      
      





MockUserDefaultsはNSUserDefaultsのサブクラスです。 デフォルト倀が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蚀語の新しいバヌゞョンのリリヌスに関連しお、䟋にいく぀かの倉曎を加えたした。 プロゞェクトの゜ヌスコヌドは、 こちらずこちらにありたす 。



All Articles