माना मेरे पास कोड की ये पंक्तियां हैं:

func reset() {
    initializeAnythingElse() {
        // AnythingElse
    }

    initializeHomeData() {
        // HomeData
    }
}

func initializeHomeData(callback: @escaping (()-> Void)) {
    getHomeConfig() {
        callback()
    }
}

func initializeAnythingElse(callback: @escaping (()-> Void)) {
    getAnythingElse() {
        callback()
    }
}

और मैं उस कोड के लिए एक यूनिट टेस्ट लिखना चाहूंगा। initializeHomeData और initializeAnythingElse के लिए, मैं यूनिट टेस्ट लिख सकता हूं जैसे:

func testInitializeHomeData() {
    let successExpectation = expectation(description: "")

    sut.initializeHomeData {
        successExpectation.fulfill()
    }

    waitForExpectations(timeout: 1.0, handler: nil)

    // Validation goes here
}

func testInitializeAnythingElse() {
    let successExpectation = expectation(description: "")

    sut.initializeAnythingElse {
        successExpectation.fulfill()
    }

    waitForExpectations(timeout: 1.0, handler: nil)

    // Validation goes here
}

मेरा प्रश्न है, reset() का परीक्षण कैसे करें? क्या मुझे उन्हें testReset() के अंदर कॉल करना चाहिए जैसे:

func testReset() {
    testInitializeHomeData()
    testInitializeAnythingElse()
}

लेकिन मुझे लगता है कि यह उसके लिए उचित कार्यान्वयन नहीं है।

8
mrjimoy_05 17 जुलाई 2017, 06:37

2 जवाब

सबसे बढ़िया उत्तर

तुम सही हो। reset का परीक्षण करने के लिए आपको reset को कॉल करना होगा, न कि यह आंतरिक तरीके।

कहा जा रहा है, reset वर्तमान में इस तरह से लिखा गया है जो इसे परीक्षण योग्य नहीं बनाता है। अन्य स्टैंडअलोन विधियों को इतनी आसानी से परखने का कारण यह है कि callback तर्क दोनों स्वीकार करते हैं।

मैं आपको दो वैकल्पिक कॉलबैक की अनुमति देने के लिए रीसेट को फिर से लिखने की सलाह दूंगा:

typealias Callback = () -> ()

func reset(
    homeDataCallback: @escaping Callback? = nil,
    anythingElseCallback: @escaping Callback? = nil) {
    initializeAnythingElse() {
       anythingElseCallback?()
    }
    initializeHomeData() {
       homeDataCallback?()
    }
}

ध्यान दें कि यह परिवर्तन आपको उन दो आंतरिक कॉलों के पूर्ण होने पर, async में सूचित करने की अनुमति देता है।

अब, आपकी परीक्षण पद्धति को किसी प्रकार के सिंक्रोनाइज़ेशन आदिम को ध्यान में रखते हुए लिखने की आवश्यकता है, क्योंकि तार्किक रूप से, रीसेट केवल तभी पूरा होता है जब होम डेटा और कुछ भी किया जाता है और उनके कॉलबैक को लागू किया जाता है।

इसे प्राप्त करने के कई तरीके हैं, लेकिन मैं आपको सेमाफोर के साथ एक दृष्टिकोण दिखाऊंगा:

func testReset() {

    let expectation = expectation(description: "reset() completes within some duration")

    // some mechanism to synchronize concurrent tasks
    // I am using a semaphore
    let s = DispatchSemaphore(value: 0)

    let homeCallback: Callback =  {
        s.signal() // signals the completion of home data init
    }

    let anythingElseCallback: Callback = {
        s.signal() // signals the completions of anything else setup
    }

    // call your reset method as part of the test
    reset(homeDataCallback: homeCallback, anythingElseCallback: anythingElseCallback)

    // we know we need to wait for two things to complete
    // init home data and anything else, so do that
    s.wait()
    s.wait()

    // at this step, reset's internal async methods
    // have completed so we can now
    // fulfill the expectation
    expectation.fulfill()

}

ध्यान दें कि यह सभी परिवर्तन केवल आपको reset कॉल का परीक्षण करने की अनुमति देने के लिए आवश्यक हैं। आपका फ़ंक्शन हस्ताक्षर आपको अपने मौजूदा कोड में reset() वर्तमान के रूप में लिखने की अनुमति देता है क्योंकि इसमें वैकल्पिक तर्क होते हैं जो डिफ़ॉल्ट मानों के लिए शून्य पर सेट होते हैं।

10
Benzi 19 जुलाई 2017, 07:56

reset विधि में कॉलबैक जोड़ें:

func reset(callback: @escaping (()-> Void)) {
    var callbacksCount = 0

    func tryCallback() {
        if callbacksCount == 2 {
            callback()
        }
    }

    initializeAnythingElse() {
        callbacksCount += 1
    }

    initializeHomeData() {
        callbacksCount += 1    
    }
}

और इसका परीक्षण उसी तरह करें जैसे आपने अन्य तरीकों के लिए किया था।

आप कॉल को अनुक्रमिक भी बना सकते हैं, समानांतर निष्पादन अधिक जटिल कोड के अनुकूलन की तरह नहीं लगता है:

func reset(callback: @escaping (()-> Void)) {
    initializeAnythingElse() {
        initializeHomeData() {
            callback()
        }
    }
}
0
Alexey Kozhevnikov 23 जुलाई 2017, 13:59