81

TDD と新しい XCTest フレームワークを使用して iOS アプリを作成しようとしています。私のメソッドの 1 つは、インターネットからファイルを取得し (NSURL オブジェクトを指定)、ユーザーのドキュメントに保存します。メソッドのシグネチャは次のようになります。

- (void) fetchAndStoreImage:(NSURL *)imageUrl

インターネットに接続されていない場合でも失敗しないように、このメソッドのテストを作成しようとしています。私のアプローチ (前の質問から取得) は、NSURL を使用してローカル ファイル システム内のイメージにメソッドを呼び出すことです。

単体テストが有効になっている新しいプロジェクトが作成されると、Tests ディレクトリに「Supporting Files」という名前のサブディレクトリが作成されます。それが私のテスト画像が行くべき場所だと思います。私の質問は、テスト画像をアプリケーションにバンドルしたくないので、このディレクトリ内の画像を指す NSURL オブジェクトを取得するにはどうすればよいかということです。どんな助けでも大歓迎です。

4

8 に答える 8

60

スイフト5.3

注: Swift 5.3 には、アプリケーション バンドルおよびテスト バンドル リソースで使用できるPackage Manager Resources SE-0271機能が含まれています。

リソースは、パッケージのクライアントによる使用を常に意図しているわけではありません。リソースの 1 つの用途には、単体テストでのみ必要なテスト フィクスチャが含まれる場合があります。このようなリソースは、ライブラリ コードと共にパッケージのクライアントに組み込まれることはなく、パッケージのテストの実行中にのみ使用されます。

スウィフト 4、5:

let testBundle = Bundle(for: type(of: self))
guard var fileUrl = testBundle.url(forResource: "imageName", withExtension: "png") 
  else { fatalError() }

// path approach
guard let filePath = testBundle.path(forResource: "dataName", ofType: "csv")
  else { fatalError() }
let fileUrl = URL(fileURLWithPath: filePath)

バンドルは、構成のメイン パスとテスト パスを検出する方法を提供します。

@testable 
import Example

class ExampleTests: XCTestCase {
    
  func testExample() {
    let bundleMain = Bundle.main
    let bundleDoingTest = Bundle(for: type(of: self ))
    let bundleBeingTested = Bundle(identifier: "com.example.Example")!
    
    print("bundleMain.bundlePath : \(bundleMain.bundlePath)")
    // …/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents
    print("bundleDoingTest.bundlePath : \(bundleDoingTest.bundlePath)")
    // …/PATH/TO/Debug/ExampleTests.xctest
    print("bundleBeingTested.bundlePath : \(bundleBeingTested.bundlePath)")
    // …/PATH/TO/Debug/Example.app
    
    print("bundleMain = " + bundleMain.description) // Xcode Test Agent
    print("bundleDoingTest = " + bundleDoingTest.description) // Test Case Bundle
    print("bundleUnderTest = " + bundleBeingTested.description) // App Bundle

Xcode URL は次のDeveloper/Xcode/DerivedDataようになります...

file:///Users/
  UserName/
    Library/
      Developer/
        Xcode/
          DerivedData/
            App-qwertyuiop.../
              Build/
                Products/
                  Debug-iphonesimulator/
                    AppTests.xctest/
                      imageName.png

Developer/CoreSimulator/Devices... URLとは別のもの

file:///Users/
  UserName/
    Library/
    Developer/
      CoreSimulator/
        Devices/
          _UUID_/
            data/
              Containers/
                Bundle/
                  Application/
                    _UUID_/
                      App.app/

また、単体テストの実行可能ファイルは、デフォルトでアプリケーション コードにリンクされていることにも注意してください。ただし、単体テスト コードには、テスト バンドルのみにターゲット メンバーシップのみを含める必要があります。アプリケーション コードには、アプリケーション バンドル内のターゲット メンバーシップのみを含める必要があります。実行時に、単体テストのターゲット バンドルが実行のためにアプリケーション バンドルに挿入されます

スウィフト パッケージ マネージャー (SPM) 4:

let testBundle = Bundle(for: type(of: self)) 
print("testBundle.bundlePath = \(testBundle.bundlePath) ")

注: デフォルトでは、コマンド ラインはテスト バンドルswift testを作成します。MyProjectPackageTests.xctestそして、 はテスト バンドルswift package generate-xcodeprojを作成します。MyProjectTests.xctestこれらの異なるテスト バンドルには異なるパスがあります。また、異なるテスト バンドルには、内部ディレクトリ構造とコンテンツの違いがある場合があります。

いずれの場合も、.bundlePathand.bundleURLは、現在 macOS で実行されているテスト バンドルのパスを返します。ただし、BundleUbuntu for Swift 4 には現在実装されていません。

また、Swift 4 コマンド ラインは、リソースをコピーするメカニズムを提供swift buildswift testません。

ただし、少し努力すれば、macOS Xcode、macOS コマンド ライン、および Ubuntu コマンド ライン環境のリソースで Swift Package Manger を使用するためのプロセスをセットアップすることができます。一例はここにあります: 004.4'2 SW Dev Swift Package Manager (SPM) With Resources Qref

于 2015-06-05T19:04:45.873 に答える
15

正解に追加するだけです。これは、UnitTests/Supporting Files 内のファイルの filePath を取得する方法の例です。

NSString *filePath = [[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingPathComponent:@"YourFileName.json"];
XCTAssertNotNil(filePath);

これはおそらく誰かにとって役立つでしょう。

于 2014-11-13T18:49:10.700 に答える
1

これの Swift バージョン、Xcode 7、iOS 9 などがあります。

let testBundle = NSBundle(forClass: self.dynamicType)
let path = testBundle.pathForResource("someImage", ofType: "jpg")
XCTAssertNotNil(path)

注: someImage.jpg をテスト ターゲットに含める必要があります。


編集:スウィフト5

let testBundle = Bundle(for: type(of: self))
let path = testBundle.path(forResource: "someImage", ofType: "jpg")
XCTAssertNotNil(path)
于 2015-12-30T00:06:45.590 に答える
0

スイフト5

let testBundle = Bundle(for: self)

let testBundle = Bundle(for: type(of: self))上記の回答の一部にある を使用すると、コンパイルされず、代わりに一貫して Segmentation fault: 11 for me のエラーが発生しました。

于 2020-08-14T22:36:27.163 に答える