단위 테스트중인 일부 코드는 리소스 파일을로드해야합니다. 다음 줄이 포함되어 있습니다.
NSString *path = [[NSBundle mainBundle] pathForResource:@"foo" ofType:@"txt"];
응용 프로그램에서는 제대로 실행되지만 단위 테스트 프레임 워크 pathForResource:
로 실행하면 nil을 반환하여 찾을 수 없음을 의미합니다 foo.txt
.
유닛 테스트 대상 foo.txt
의 Copy Bundle Resources 빌드 단계에 포함되어 있는지 확인했는데 왜 파일을 찾을 수 없습니까?
답변
단위 테스트 장치가 코드를 실행할 때 단위 테스트 번들이 기본 번들 이 아닙니다 .
애플리케이션이 아닌 테스트를 실행하더라도 애플리케이션 번들은 여전히 기본 번들입니다. (이것은 아마도 테스트중인 코드가 잘못된 번들을 검색하지 못하게합니다.) 따라서 단위 테스트 번들에 자원 파일을 추가하면 기본 번들을 검색해도 찾을 수 없습니다. 위의 줄을 다음과 같이 바꾸면 :
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *path = [bundle pathForResource:@"foo" ofType:@"txt"];
그런 다음 코드는 단위 테스트 클래스가있는 번들을 검색하고 모든 것이 잘됩니다.
답변
스위프트 구현 :
스위프트 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 filePath = testBundle.path(forResource: "imageName", ofType: "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 | 9에서 단위 테스트 번들 경로 는 Developer/Xcode/DerivedData
다음과 같습니다.
/Users/
UserName/
Library/
Developer/
Xcode/
DerivedData/
App-qwertyuiop.../
Build/
Products/
Debug-iphonesimulator/
AppTests.xctest/
foo.txt
… Developer/CoreSimulator/Devices
일반 (비 테스트) 번들 경로 와 별도입니다 .
/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
. 이러한 다른 테스트 번들에는 다른 경로가 있습니다. 또한 다른 테스트 번들은 내부 디렉토리 구조 및 내용 차이 가있을 수 있습니다 .
두 경우 모두, .bundlePath
그리고 .bundleURL
현재 맥 OS에서 실행되는 테스트 번들의 경로를 반환합니다. 그러나 Bundle
현재 Ubuntu Linux에는 구현되어 있지 않습니다.
또한, 명령 줄 swift build
및 swift test
현재 자원을 복사하는 메커니즘을 제공하지 않습니다.
그러나 약간의 노력으로 macOS Xcode, macOS 명령 행 및 Ubuntu 명령 행 환경의 자원과 함께 Swift Package Manger를 사용하기위한 프로세스를 설정할 수 있습니다. 한 가지 예는 여기에서 찾을 수 있습니다 : 004.4’2 SW 개발자 스위프트 패키지 관리자 (SPM)을 자원 Qref으로
참조 : 사용 자원을 스위프트 패키지 관리자와 단위 테스트에
스위프트 패키지 관리자 (SPM) 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"]
),
]
)
답변
swift Swift 3에서는 구문 self.dynamicType
이 더 이상 사용되지 않습니다. 대신 이것을 사용하십시오
let testBundle = Bundle(for: type(of: self))
let fooTxtPath = testBundle.path(forResource: "foo", ofType: "txt")
또는
let fooTxtURL = testBundle.url(forResource: "foo", withExtension: "txt")
