Xcode 12에서 시작하는 StoreKit Testing.

개요


지금까지 iOS의 앱 내 유료로 처리된 유닛 테스트는 쓰기 어려웠고, 쓰려면 실제로 앱스토어와 통신해야 했다.
또한 어플리케이션 내 유료 설치를 시작하기 전에 시간(AppStore Connect에서 다양한 준비가 있기 때문)이 소요되며, 샌드박스 환경에서 구매 처리를 하면 구매 처리 테스트를 다시 시작하기 전에 간격이 생겨 앱 내 유료 설치가 어려울 것 같다.
그러나 Xcode12에서 도입한 새로운 기능은 다양한 문제를 해결했다.
이번에 소개한 것은 Xcode12가 도입한 새로운 기능과 쓰기 응용 프로그램 내 유료 처리 단위 테스트StoreKit Test의 구조다.

StoreKit Configuration


엑스코드12에서 앱을 구매하는 것과 관련해서는 엑스코드 안에서 다양한 설정을 할 수 있다.
이 기능을 사용하면 앱스토어의 샌드박스와 프로덕션 환경에 액세스하지 않고 로컬 환경에서만 동작 확인과 테스트를 할 수 있다.

StoreKit Configuration File


확장자가 StoreKit Configuration File인 파일을 생성할 수 있습니다.storeKit.
이 파일에 상품 정보(제품 ID와 가격 등)를 설정하고, 앱스토어 커넥트에서 각종 정보를 로그인하지 않고도 유료 처리 동작을 확인할 수 있다.
결국 로컬 환경에서의 동작 확인이기 때문에 샌드박스와 프로덕션 환경에서 작동하기 위해서는 앱스토어 커넥트에서 정보를 로그인해야 한다.
문서의 제작 방법과 설정 방법은 다음과 같다.

(1) 파일의 새 화면에서 storekit으로 필터링하면 StoreKit Configuration File이 나타나므로 파일을 선택합니다.



(2) 만든 파일을 선택하고 왼쪽 아래에 있는 단추를 누릅니다.



설치할 In-App Purchase의 종류는 다음과 같습니다.
  • Add Consuumable In-Pap Purchase: 소모형
  • AddNon-Consuumable In-App Purchase: 비소모형
  • Add Auto-Renewable Subscription: 정기 구독형
  • 이번에는 Add Non-Consuumable In-App Purchase를 선택합니다.

    (3) 아래 그림과 같이 상품 정보를 기술한다.



    여기에 설정된 내용은 구매 처리가 가능합니다.물론 구매 시 로그인 인증은 필요 없습니다.

    (4) 를 사용하여 생성된 프로파일을 설정합니다.


    Edit Schome에서 StoreKit Configuration 프로젝트에서 만든 StoreKit Configuration File을 선택합니다.

    이렇게 설정이 완성되었습니다!이후 StoreKit로 앱 내 유료를 설치하면 바로 동작을 확인할 수 있다.
    github에 조작 가능한 코드가 설치되어 있으니 가능하면 확인하세요.

    StoreKit Transaction Manager


    StoreKit Transaction Manager는 로컬 테스트 환경에서 과거의 구매 기록을 볼 수 있고 (엄밀히 말하면 구매 거래) 그것들을 제어할 수 있는 새로운 기능이다.
    예를 들어 현지 환경에서 구매 처리를 한 번 한 뒤 팩스와 오류 수정 등을 위해 구매 처리를 다시 수행하고 싶은 일이 있다.
    이제 StoreKit Transaction Manager에서 구매 기록을 제거하고 미구매 상태로 돌아갈 수 있습니다.
    먼저 Xcode 아래의 버튼을 클릭합니다.

    그런 다음 Transaction Manager 화면을 엽니다.거래를 삭제하면 미구매 상태로 돌아가거나 환불된 상태로 바뀔 수 있다.

    또한 파일.storekit을 연 상태에서 Xcode의 Edit 태그를 선택하면 구매 실패, Ask To Buy 유효, Time Rate로 가입 기간을 변경하는 등 Enable Interupted Purchases에서 다양한 상태를 생성할 수 있습니다.

    이렇게 하면 구매 거래의 상태 변경과 오류가 의식적으로 발생할 수 있기 때문에 개발 효율이 현저히 높아진다.

    StoreKit Testing


    StoreKit Configuration File을 사용하면 유닛 테스트도 쓰기 쉬워집니다.
    In-App Purchase에 대한 유닛 테스트를 작성하려면 StoreKit Test iOS 14에서 사용할 수 있는 프레임워크를 사용합니다.

    SKTestSession


    코드에서 In-App Purchase 처리를 수행할 때 거래를 처리할 때 사용하는 설정의 클래스를 제어합니다.
    SKTestSession의 특정 인스턴스 메서드를 호출할 때마다SKTestTransaction 생성됩니다.
    이 외에도 SKPaymentTransactionObserver를 통해 실거래SKPaymentTransaction가 생성됐다.
    StoreKit의 테스트 환경은 하나이고 모든SKTestSession은 하나뿐인 테스트 환경을 제어합니다.즉, 병렬 처리에서 각 인스턴스의 API에서 제어하더라도 여러 인스턴스SKTestSession를 생성합니다.상세한 사례는 뒤에 서술할 것이다.
    다음은 InApp Purchase 유닛 테스트를 작성하는 데 필요한 최소 설정입니다.
    import XCTest
    import StoreKitTest
    
    private var session: SKTestSession!
    
    override func setUpWithError() throws {
        // 接続先をローカル環境に設定し、Configuration.storekitで設定した内容にアクセスするようにします.
        session = try SKTestSession(configurationFileNamed: "Configuration")
        // テスト中はユーザーからの操作を無くすため、すべてのダイアログを無効にします.
        session.disableDialogs = true
        // 過去のトランザクションをすべて削除します.
        session.clearTransactions()
    }
    
    마지막으로 특정 예외 시스템 테스트를 작성하는 데 필요한 API 몇 개를 소개합니다.

    Failed Transactions


    실패한 거래를 강제로 하려면 속성failTransactionsEnabled에 진짜를 설정하십시오.
    func testPurchaseBerryBlue_failed() {
        guard let product = product else {
            XCTFail("Must fetch product")
    	return
        }
        // trueにすることで、トランザクションが必ず失敗するようにしている.	
        session.failTransactionsEnabled = true
        purchase(product: product)
        
        wait(for: [purchaseProductExp], timeout: 3.0)
        XCTAssertTrue(transactionState == .failed, "\(transactionState.rawValue) is not failed")
    }
    
    한 테스트 용례failTransactionsEnabled에서 진짜로 설정하고 다른 테스트 용례에서 거래를 시작하면 실패할 수 있습니다.위에서 말한 바와 같이 테스트 환경은 하나이고 SKTestSession은 하나뿐인 환경을 제어한다.따라서 한 번failTransactionsEnabled을 진짜로 만들면 이후에도 거래가 실패할 수밖에 없다.기본값을 성공 상태로 설정하려면 setUp에 명시적으로 설정session.failTransactionsEnabled = false합니다.
    뒤에 서술한 interruptedPurchasesEnabled를 진짜로 설정한 경우도 마찬가지다.

    Interrupted Purchases


    구매 처리가 중단된 상태에서 테스트를 진행하려면 interruptedPurchasesEnabled 속성을 진짜로 설정하십시오.
    그리고 사용자가 필요한 수속을 마치고 테스트를 한 후resolveIssueForTransaction 실행하는 방법을 원한다.
    func testPurchaseBerryBlue_successAfterInterrupted() {
        guard let product = product else {
            XCTFail("Must fetch product")
    	return
        }
        // トランザクションが必ず中断されるようにしている.
        session.interruptedPurchasesEnabled = true
        purchase(product: product)
        
        wait(for: [purchaseProductExp], timeout: 3.0)
        session.allTransactions().forEach { transaction in
            do {
    	    // トランザクションが中断された原因を、ユーザーが解決したことをシミュレートするようにしています.
    	    try session.resolveIssueForTransaction(identifier: transaction.identifier)
    	} catch {
    	    XCTFail()
    	}
        }
        
        purchaseProductExp = XCTestExpectation(description: "Purchase product item")
        // SKPaymentTransactionObserverでトランザクションの状態が通知されるのを待ちます.
        wait(for: [purchaseProductExp], timeout: 3.0)
    
        XCTAssertTrue(transactionState == .purchased, "\(transactionState.rawValue) is not purchased")
        SKPaymentQueue.default().finishTransaction(transaction!)
    }
    
    다양한 상황을 모의하는 API도 제공합니다. SKTestSession의 참고에서 작성하고자 하는 테스트 용례에 대응하는 API를 찾으십시오.
    정상 시스템과 이상 시스템의 테스트 용례만 있고 이쪽도 github에 코드를 올렸으니 가능하면 확인해 주세요.

    총결산


    Xcode12와 iOS 14에서 InApp Purchase까지 설치가 쉬워졌다.
    나는 개인적으로 예매 동작을 확인할 시간을 기다리지 않아서 매우 기쁘다.또 다른 잘못이 있으면 메시지를 남겨 주세요.

    참조 링크

  • https://developer.apple.com/videos/play/wwdc2020/10659/
  • https://developer.apple.com/documentation/storekittest/sktestsession
  • 좋은 웹페이지 즐겨찾기