0

私はView Controllerに対して単体テストを実行しています。このスイートには2つのビューコントローラがあり、そのうちの1つはストーリーボードファイル内の別のビューコントローラにつながります。UIStoryboardSceneは保持カウントを変更せずにコントローラを予期せずに割り当て解除します

両方のコントローラのテストでは、私は同じ方法でテスト対象を作成します。にstoryboardWithName:factory:bundle:(依存性注入のための台風は工場出荷時のものを使用します)を取得します。次に、storyboard.instantiateViewControllerWithIdentifier:を使用してVCを取得します。

私の最初のView Controllerのテストでは、すべてのテストに合格します。重要なのは、ビュー・コントローラのdeinitメソッドは、vc自体がテスト・ケース内のスコープから外れるか、または新しいインスタンスがサブジェクトになり、古いインスタンスの保持カウントが0に減少した場合にのみ呼び出されることです。

ただし、 2番目のVCでは、何らかの理由で[UIStoryboardScene dealloc]にコールが発信され、コントローラのdeinitがコールされるため、これらのいずれの場合もテストは失敗します(VCが範囲外になるか、新しいVCが対象外になる)その保持カウントは依然として1でなければならない(テストケースによって保持される)。 ARCは、新しいインスタンスをサブジェクトとして設定すると、VCに別のリリースメッセージを送信し、EXC_BAD_ACCESS (CODE=i386, GPFLT)を取得します。

[UIStoryboardScene dealloc]は、XCTestフレームワーク(ここではコピーされています)でコンパイルされたコードの集まりで発生しますが、テストケースが終了しているために起こっていると思います。

だから、
* thread #1: tid = 0x57cf91, 0x00000001089953a3 sbprod`Mode2ViewController.__deallocating_deinit(self=0x00007fd2bbdde5d0) + 19 at Mode2ViewController.swift:68, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1 
* frame #0: 0x00000001089953a3 sbprod`Mode2ViewController.__deallocating_deinit(self=0x00007fd2bbdde5d0) + 19 at Mode2ViewController.swift:68 
frame #1: 0x0000000108995492 sbprod`@objc Mode2ViewController.__deallocating_deinit + 34 at Mode2ViewController.swift:0 
frame #2: 0x000000010a1ff702 UIKit`-[UIStoryboardScene dealloc] + 36 
frame #3: 0x000000010b04dafe libobjc.A.dylib`objc_object::sidetable_release(bool) + 232 
frame #4: 0x000000010b04e0b8 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 488 
frame #5: 0x0000000115841f37 XCTest`__24-[XCTestCase invokeTest]_block_invoke_2 + 430 
frame #6: 0x0000000115876613 XCTest`-[XCTestContext performInScope:] + 190 
frame #7: 0x0000000115841d78 XCTest`-[XCTestCase invokeTest] + 169 
frame #8: 0x00000001158423a2 XCTest`-[XCTestCase performTest:] + 459 
frame #9: 0x000000011583fcf7 XCTest`-[XCTestSuite performTest:] + 396 
frame #10: 0x000000011583fcf7 XCTest`-[XCTestSuite performTest:] + 396 
frame #11: 0x000000011583fcf7 XCTest`-[XCTestSuite performTest:] + 396 
frame #12: 0x000000011582cb10 XCTest`__25-[XCTestDriver _runSuite]_block_invoke + 51 
frame #13: 0x000000011584db4c XCTest`-[XCTestObservationCenter _observeTestExecutionForBlock:] + 640 
frame #14: 0x000000011582ca55 XCTest`-[XCTestDriver _runSuite] + 453 
frame #15: 0x000000011582d7d1 XCTest`-[XCTestDriver _checkForTestManager] + 259 
frame #16: 0x0000000115877a9a XCTest`_XCTestMain + 628 

  1. UIStoryboardSceneが全く作成されているのはなぜ?私は、私のテストのためにシーン、VCだけを望んでいません。以前のテストケースでは発生していないようです。ストーリーボードが2つのVCの間で気にする限り、唯一の違いは、そのうちの1つがその中に入り組んでいることと、もう1つがそれから出ていることです。 UIStoryboardSceneは両方のケースでは、既存の事実であるならば、なぜそれがdeinitは、それがするべき前に私のVCをINGの

  2. のですか?

  3. 私のテストケースにも適用範囲内で互いに非常に異なっていない、しかし、このテストケースは場所にいくつかのクロージャを渡し、私は、クロージャがARCにどのような影響を与えるかについては100%ではないです。


EDIT:ここに示す関連するコード。

override func spec() { 

    var subject: Mode2ViewController! 

    let presentDisplayString = "DesiredString" 

    describe("Mode2ViewController") { 
     describe("loading") { 
      describe("date and location") { 
       context("when location is available") { 
        beforeEach { 
         let system = MockSystemComponents.CreateWith(location: true, groups: nil) 

         let assembly = ApplicationAssembly().activateWithCollaboratingAssemblies([ 
           system 
          ]) 

         //crash occurs on next line, before the 2nd test case, because the 
         //old subject has already been deallocated (by UIStoryboardScene) 
         //but reassigning this var, which had retains it, triggers a release 

         subject = assembly.mode2ViewController() as! Mode2ViewController 
         let _ = subject.view 
        } 

        it("records the location") { 
         expect(subject).notTo(beNil()) 
        } 

        it("displays the location as a meaningful string") { 
         expect(subject.locationLabel.text).to(equal(presentDisplayString)) 
        } 
       } 
      } 
     } 
    } 
} 

注:クイック用いて行われる私のテストケースにおいて

(最初の編集)上記で与えられたスタックトレースは、私はMode2ViewController.deinit()に挿入されたブレークポイントです。

+0

コードを表示する必要があります。 – jtbandes

+0

@jtbandes第2(クラッシュ)リリースを呼び出すコードを追加しました。他のコードが必要な場合はお知らせください。 – Quintana

答えて

0

問題点は、目的のcが、キーワード「new」で始まるものを保持カウントに関して処理するという問題でした。この理由で台風はnewで始まるメソッドを処理できません(issue参照)。

解決方法:台風法の名前を変更し、生成されるオブジェクトに正しい保持カウントが設定されている。

関連する問題