ProgramingTip

XCTest를 사용하는 테스트의 파일 경로에 대한 NSURL

bestdevel 2020. 11. 3. 08:21
반응형

XCTest를 사용하는 테스트의 파일 경로에 대한 NSURL


TDD와 새로운 XCTest 프레임 워크를 사용하여 iOS 앱을 작성합니다. 내 방법 중 하나는 인터넷에서 파일을 검색하고 (NSURL 개체가 제공됨) 사용자 문서에 저장됩니다. 방법의 서명은 다음과 유사합니다.

- (void) fetchAndStoreImage:(NSURL *)imageUrl

인터넷에 연결되어 있지 않아도 그렇지 않은 방식 으로이 방법에 대한 테스트를 작성합니다. 내 접근 방식 (이전 질문 에서 가져옴)은 로컬 파일 시스템의 이미지에 대해 NSURL을 사용하여 메서드를 호출하는 것입니다.

단위 테스트가 활성화 된 새 프로젝트가 생성되면 Tests 디렉터리에 'Supporting Files'라는 하위 디렉터리가 있습니다. 나는 그것이 내 테스트 이미지가 가야 할 곳이라고 생각합니다. 내 질문은 테스트 이미지가 응용 프로그램과 함께하기 때문에 디렉토리의 이미지를 제공하기 때문에 NSURL 개체를 어떻게 얻을 수 있습니까? 도움을 주시면 감사하겠습니다.


사실, 실행 [NSBundle mainBundle]유닛 테스트는 하지 앱 경로 만 / 개발자는 / usr / 빈입니다.

단위 테스트에서 리소스를 얻는 방법은 다음과 같습니다. OCUnit 및 NSBundle

간단히 말해서 다음을 사용하십시오.

[[NSBundle bundleForClass:[self class]] resourcePath]

또는 귀하의 경우 :

[[NSBundle bundleForClass:[self class]] resourceURL]

스위프트 2 :

let testBundle = NSBundle(forClass: self.dynamicType)
let fileURL = testBundle.URLForResource("imageName", withExtension: "png")
XCTAssertNotNil(fileURL)

스위프트 3, 4 :

let testBundle = Bundle(for: type(of: self))
let fileURL = testBundle.url(forResource: "imageName", withExtension: "png")
XCTAssertNotNil(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 6 | 7 | 8 URL은 Developer/Xcode/DerivedData...

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

... Developer/CoreSimulator/DevicesURL 과는 있습니다.

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

또한 단위 테스트 실행 파일은 기본적으로 응용 프로그램 코드와 연결되어 있습니다. 그러나 단위 테스트 코드에는 많은 사람들에게 Target Membership이 있어야합니다. 애플리케이션 코드에는 애플리케이션에 대상 멤버십 만 있어야합니다. 실행시 단위 테스트 대상이 실행 을 위해 애플리케이션에 삽입 됩니다.

SPM (Swift Package Manager) 4 :

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

참고 : 기본적으로 명령 줄

swift testMyProjectPackageTests.xctest테스트를 생성합니다 . 그리고 테스트를 swift package generate-xcodeproj생성합니다 MyProjectTests.xctest. 많은 경우에는 다른 경로가 있습니다. 또한 내부 디렉토리 구조와 콘텐츠 차이 가 있습니다 .

두 경우 모두, .bundlePath그리고 .bundleURL현재 맥 OS에서 실행되는 테스트 번들의 경로를 반환합니다. 그러나 Bundle현재 Ubuntu에 대해 구현되지 않았습니다.

또한, 명령 줄 swift buildswift test현재 자원을 복사하는 메커니즘을 제공하지 않습니다.

그러나 약간의 노력을 기울이면 macOS Xcode, macOS 명령 줄 및 Ubuntu 명령 줄 환경의 리소스로 Swift Package Manger를 사용하기위한 프로세스를 설정할 수 있습니다. 한 가지 예는 여기에서 찾을 수 있습니다. 004.4'2 SW Dev Swift Package Manager (SPM) With Resources Qref

SPM (Swift Package Manager) 4.2

Swift Package Manager PackageDescription 4.2 에는 로컬 종속성 지원이 도입되었습니다 .

로컬 종속성은 경로를 사용하여 직접 참조 할 수있는 디스크의 패키지입니다. 로컬 종속성은 루트 패키지에서만 허용되며 패키지 그래프에서 동일한 이름의 모든 종속성을 재정의합니다.

참고 : SPM 4.2에서 다음과 같은 작업이 가능할 것으로 예상하지만 아직 테스트하지는 않았습니다.

// swift-tools-version:4.2
import PackageDescription

let package = Package(
    name: "MyPackageTestResources",
    dependencies: [
        .package(path: "../test-resources"),
    ],
    targets: [
        // ...
        .testTarget(
            name: "MyPackageTests",
            dependencies: ["MyPackage", "MyPackageTestResources"]
        ),
    ]
)

정답에 추가하기 위해 다음은 UnitTests / Supporting Files에서 파일에 대한 filePath를 얻는 방법의 예입니다.

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

이것은 아마도 누군가에게 유용 할 것입니다.


  1. 모든 대상에서와 같이 번들 파일을 참조 할 수 있습니다.
  2. 테스트 대상의 번들 리소스 복사 빌드 단계에서 파일이 복사되었는지 확인합니다.
  3. 로컬 파일에 액세스하려면 :

    NSURL*imageUrl=[[NSBundle mainBundle]URLForResource:@"imageName" withExtension:@"png"];
    

https://github.com/travisjeffery/TRVSMonitor를 사용하여 비동기 액세스를 만들고 응답을 기다릴 수 있습니다.

추가 한 경우 : dataset1.json테스트 대상 (2)에서 :

NSString *p=[[NSBundle mainBundle] pathForResource:@"dataset1" ofType:@"json"];
NSLog(@"%@",p);

2013-10-29 15 : 49 : 30.547 PlayerSample [13771 : 70b] WT (0) : / Users / bpds / Library / Application Support / iPhone Simulator / 7.0 / Applications / 7F78780B-684A-40E0-AA35-A3B5D8AA9DBD / PlayerSample. app.app/dataset1.json


내가 직면 한 문제는 응용 프로그램 코드가 bundleIdentifier와 같은 항목에 대한 기본 번들에 액세스하려고 시도하고 기본 번들이 내 단위 테스트 프로젝트가 아니기 때문에 nil을 반환한다는 것입니다.

Swift 3.0.1과 Objective-C 모두에서 작동하는이 문제를 해결하는 방법은 NSBundle에 Objective-C 카테고리를 만들고이를 단위 테스트 프로젝트에 포함하는 것입니다. 브리징 헤더 나 아무것도 필요하지 않습니다. 이 카테고리가로드되고 이제 애플리케이션 코드가 기본 번들을 요청하면 카테고리가 단위 테스트 번들을 반환합니다.

@interface NSBundle (MainBundle)

+(NSBundle *)mainBundle;

@end

@implementation NSBundle (Main)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+(NSBundle *)mainBundle
{
    return [NSBundle bundleForClass:[SomeUnitTest class]];
}
#pragma clang diagnostic pop

@end

Swift 수락 된 답변에 기반한 버전 :

let url = URL(fileURLWithPath: Bundle(for: type(of: self)).path(forResource: "my", ofType: "json") ?? "TODO: Proper checking for file")

여기에 Xcode 7, iOS 9 등의 Swift 버전이 있습니다.

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

참고 : someImage.jpg는 테스트 대상에 포함되어야합니다.

참고 URL : https://stackoverflow.com/questions/19309092/nsurl-to-file-path-in-test-bundle-with-xctest

반응형