테스트 및 디버그 - Swift SDK
이 페이지의 내용
테스트
기본 Realm을 사용하여 테스트
영역 기반 애플리케이션을 사용하고 테스트하는 가장 쉬운 방법은 기본 영역을 사용하는 것입니다. 애플리케이션 데이터의 재정의를 방지하고 테스트 간 상태 유출을 막기 위해, 각 테스트마다 기본 영역을 새 파일로 설정하는 것이 좋습니다.
// A base class which each of your Realm-using tests should inherit from rather // than directly from XCTestCase class TestCaseBase: XCTestCase { override func setUp() { super.setUp() // Use an in-memory Realm identified by the name of the current test. // This ensures that each test can't accidentally access or modify the data // from other tests or the application itself, and because they're in-memory, // there's nothing that needs to be cleaned up. Realm.Configuration.defaultConfiguration.inMemoryIdentifier = self.name } }
Realm 인스턴스 주입
영역 관련 코드를 테스트하는 또 다른 방법은 테스트하려는 모든 메서드가 영역 인스턴스를 인수로 받아들이도록 하는 것입니다. 이를 통해 앱을 실행하고 테스트할 때 다양한 영역을 전달할 수 있습니다.
예를 들어 앱에 JSON API에서 사용자 프로필을 GET
처리하는 메서드가 있다고 가정해 보겠습니다. 로컬 프로필이 제대로 생성되었는지 테스트하려고 합니다:
// Application Code func updateUserFromServer() { let url = URL(string: "http://myapi.example.com/user") URLSession.shared.dataTask(with: url!) { data, _, _ in let realm = try! Realm() createOrUpdateUser(in: realm, with: data!) } } public func createOrUpdateUser(in realm: Realm, with data: Data) { let object = try! JSONSerialization.jsonObject(with: data) as? [String: String] try! realm.write { realm.create(User.self, value: object, update: .modified) } } // Test Code let realmPath = URL(fileURLWithPath: "...") func testThatUserIsUpdatedFromServer() { let config = Realm.Configuration(fileURL: realmPath) let testRealm = try! Realm(configuration: config) let jsonData = "{\"email\": \"help@realm.io\"}".data(using: .utf8)! // In our test, we're passing in the testRealm. This is where we'd // pass in our "real" realm in the application code above. createOrUpdateUser(in: testRealm, with: jsonData) XCTAssertEqual(testRealm.objects(User.self).first!.email, "help@realm.io", "User was not properly updated from server.") }
클래스 프로젝션으로 테스트 간소화
버전 10.21.0의 새로운 기능
테스트를 위해 객체 속성의 하위 집합으로 작업하려는 경우 클래스 프로젝션을 생성할 수 있습니다. 클래스 프로젝션은 모델 추상화의 한 형태로, 영역 객체의 속성을 전달하거나 이름을 변경하거나 제외할 수 있게 해줍니다. 이 기능은 뷰 모델 구현을 단순화하는 동시에 영역을 사용한 테스트도 단순화합니다.
예시
이 예시에서는 클래스 프로젝션 정의 및 사용 페이지에서 객체 모델 및 클래스 프로젝션을 사용합니다.
이 예에서는 전체 객체 모델을 사용하여 영역 객체를 만듭니다. 그런 다음 객체를 클래스 프로젝션으로 검색하여 해당 속성의 하위 집합만 사용하는 것을 확인합니다.
이 클래스 프로젝션을 사용하면 테스트할 필요가 없는 속성에 액세스하거나 설명할 필요가 없습니다.
func testWithProjection() { let realm = try! Realm() // Create a Realm object, populate it with values let jasonBourne = Person(value: ["firstName": "Jason", "lastName": "Bourne", "address": [ "city": "Zurich", "country": "Switzerland"]]) try! realm.write { realm.add(jasonBourne) } // Retrieve all class projections of the given type `PersonProjection` // and filter for the first class projection where the `firstName` property // value is "Jason" let person = realm.objects(PersonProjection.self).first(where: { $0.firstName == "Jason" })! // Verify that we have the correct PersonProjection XCTAssert(person.firstName == "Jason") // See that `homeCity` exists as a projection property // Although it is not on the object model XCTAssert(person.homeCity == "Zurich") // Change a value on the class projection try! realm.write { person.firstName = "David" } // Verify that the projected property's value has changed XCTAssert(person.firstName == "David") }
테스트 대상
Realm 프레임워크를 테스트 대상에 직접 연결하지 마세요. 이로 인해 '객체 유형 'YourObject'가 Realm에서 관리되지 않습니다'라는 예외 메시지와 함께 테스트가 실패할 수 있습니다. 테스트 대상에서 Realm의 연결을 해제하면 이 문제가 해결됩니다.
애플리케이션 또는 프레임워크 대상에서 모델 클래스 파일을 컴파일합니다. 단위 테스트 대상에 추가하지 마세요. 그렇지 않으면 테스트 시 해당 클래스가 중복되어 디버깅하기 어려운 문제가 발생할 수 있습니다.
테스트에 필요한 모든 코드를 단위 테스트 대상에 노출하세요.public
액세스 한정자 또는 @testable을 사용합니다.
Realm을 동적 프레임워크로 사용하기 때문에 단위 테스트 대상이 Realm을 찾을 수 있는지 확인해야 합니다. 단위 테스트의 "프레임워크 검색 경로" 에 RealmSwift.framework
의 상위 경로를 추가합니다.
디버깅
Realm Studio를 사용한 디버깅
영역 Studio를 사용하면 로컬 영역을 열고 편집할 수 있습니다. Mac, Windows, Linux를 지원합니다.
LLDB
Realm의 Swift API를 사용하는 앱의 디버깅은 LLDB 콘솔을 통해 수행해야 합니다.
LLDB 스크립트를 사용하면 Xcode의 UI에서 영역 변수의 내용을 검사할 수 있지만, 아직 Swift에서는 이 기능이 작동하지 않습니다. 이러한 변수는 잘못된 데이터를 표시합니다. 대신 LLDB의 po
명령을 사용하여 영역에 저장된 데이터의 내용을 검사하세요.
문제 해결
빌드 문제 해결
일부 개발자는 CocoaPods 또는 Carthage를 통해 Realm Swift SDK를 설치한 후 빌드 문제를 경험합니다. 이러한 문제의 일반적인 원인은 다음과 같습니다:
설치 문제:
초기 설치에 실패했습니다.
지원되지 않는 버전의 종속성 관리자 사용하기
빌드 도구 문제:
빌드 도구에 오래된 캐시가 있습니다.
빌드 도구 버전 업데이트
다음과 같이 프로젝트 설정을 변경합니다:
새 대상 추가
대상 간에 종속성 공유
이러한 문제는 파생 데이터를 삭제하고 Xcode 빌드 폴더를 정리하면 해결되는 경우가 많습니다.
UI 로드 전 Realm 열기 문제
영역을 열 때 선택적 또는 필수 속성과 관련된 오류 메시지로 인해 즉시 충돌이 발생할 수 있습니다. 객체 모델에 문제가 있으면 이러한 유형의 충돌이 발생할 수 있습니다. 이러한 오류는 영역을 연 후 UI에 도달하기 전에 발생합니다.
장치에서 영역이 열리는 경우, '스키마 검색' 단계가 진행됩니다. 이때 Realm은 관리하는 모든 객체에 대한 스키마를 검사합니다. 특정 영역이 애플리케이션에서 객체의 하위 집합만 관리하도록 지정할 수 있습니다.
스키마 검색 중에 속성과 관련된 오류가 표시되는 경우, 이는 특정 객체의 데이터 문제가 아니라 스키마 문제로 인한 것일 수 있습니다. 예를 들어 to-one 관계를 선택 사항이 아닌 필수 사항으로 정의하면 스키마 검색 오류가 표시될 수 있습니다.
이러한 충돌을 디버그하려면 정의한 스키마를 확인하세요.
이는 UI가 로딩되기 전에 발생하므로 스키마 검색 문제임을 알 수 있습니다. 즉, 속성을 잘못 사용하려는 UI 요소가 없으며 잘못된 데이터를 포함할 수 있는 객체가 메모리에 존재하지 않습니다. UI가 로딩된 이후 속성과 관련된 오류가 발생하는 경우 잘못된 스키마 때문일 수 있습니다. 대신 이러한 오류는 부정확하거나 잘못 입력되었거나 누락된 데이터로 인해 발생했을 가능성이 높습니다.
모델에 대해 정의된 속성 없음
Realm Swift SDK는 런타임에 모델의 속성을 결정하기 위해 Swift 언어의 리플렉션 기능을 사용합니다. 다음과 비슷한 충돌이 발생하면 프로젝트에서 리플렉션 메타데이터를 비활성화하지 않았는지 확인하세요.
Terminating app due to uncaught exception 'RLMException', reason: 'No properties are defined for 'ObjectName'.
SWIFT_REFLECTION_METADATA_LEVEL = none
를 설정하면 Realm은 속성 및 열거형과 같은 하위 유형을 검색할 수 없습니다. 리플렉션은 프로젝트가 이 세팅에 대한 레벨을 구체적으로 설정하지 않는 경우 기본적으로 활성화됩니다.
할당 불량/사용 가능한 메모리 부족
메모리가 부족한 iOS 또는 iPad 장치나 다수의 영역 또는 많은 알림을 사용하는 메모리 집약적인 애플리케이션을 사용하는 경우 다음과 같은 오류가 발생할 수 있습니다.
libc++abi: terminating due to an uncaught exception of type std::bad_alloc: std::bad_alloc
이 오류는 일반적으로 사용 가능한 메모리가 부족하여 리소스를 할당할 수 없음을 나타냅니다.
iOS + 또는 iPad +용으로 빌드하는 경우 확장 15 15 가상 주소 지정 권한 을 추가할 수 있습니다. 을(를) 클릭하여 이 문제를 해결하세요.
속성 목록에 다음 키를 추가하고 값을 true
으로 설정합니다.
<key>com.apple.developer.kernel.extended-virtual-addressing</key> <true/> <key>com.apple.developer.kernel.increased-memory-limit</key> <true/>
Swift 패키지 대상을 동적으로 빌드할 수 없음
버전 10.49.3에서 변경되었습니다.
Swift SDK v10.49.3 Swift Package Manager(SPM)로 패키지를 설치하기 위한 세부 정보를 변경했습니다. 패키지의 이전 버전에서 v10.49.3 이상으로 업데이트하면 다음과 유사한 빌드 오류가 발생할 수 있습니다.
Swift package target `Realm` is linked as a static library by `TargetName` and `Realm`, but cannot be built dynamically because there is a package product with the same name.
이 오류를 해결하려면 빌드 대상에서 Realm
또는 RealmSwift
패키지 의 연결을 해제합니다. 다음 단계에 따라 Xcode에서 이 작업을 수행할 수 있습니다.
Targets 프로젝트 에서 빌드 대상을 선택합니다.
Build Phases 탭으로 이동합니다.
Link Binary With Libraries 요소를 확장합니다.
Realm
또는RealmSwift
을(를) 선택하고 항목 제거(-) 버튼을 클릭하여 불필요한 바이너리를 제거 합니다.Swift 또는 Swift 및 Objective-C API를 사용하는 경우
RealmSwift
을(를) 유지합니다.Objective-C API만 사용하는 경우
Realm
을(를) 유지합니다.
이제 대상이 이 오류 없이 빌드 되어야 합니다.