2011-05-21 9 views
15

आप पहले उत्तरदाता इकाई परीक्षण कैसे लिखते हैं?आईओएस यूनिट टेस्ट: कैसे सेट/अपडेट/पहली बार जांचें?

मैं यह पुष्टि करने के लिए एक परीक्षण लिखने की कोशिश कर रहा हूं कि एक विधि अगली पाठ फ़ील्ड पर ध्यान केंद्रित करे। controllerUIViewController का वंशज है। लेकिन इस खोजपूर्ण परीक्षण विफल रहता है:

- (void)testFirstResponder 
{ 
    [controller view]; 
    [[controller firstTextField] becomeFirstResponder]; 

    STAssertTrue([[controller firstTextField] isFirstResponder], nil); 
} 

पहली पंक्ति का कारण बनता है दृश्य लोड करने के लिए इतना है कि अपनी दुकानों स्थान पर हैं। टेक्स्ट फ़ील्ड गैर-शून्य हैं। लेकिन परीक्षण कभी नहीं गुजरता है।

मुझे लगता है कि becomeFirstResponder पहले उत्तरदाता को तुरंत सेट नहीं करता है, लेकिन बाद में इसे शेड्यूल करता है। तो क्या इसके खिलाफ यूनिट परीक्षण लिखने का एक अच्छा तरीका है?

अप स्वीकार किए जाते हैं जवाब में टिप्पणी से जवाब पुलिंग ... बातें करते हैं थोड़े समय के लिए चलाएँ:

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]]; 

उत्तर

7

मुझे लगता है कि प्रबंध /, पहले प्रत्युत्तर श्रृंखला किसी भी तरह मुख्य पाश में पूरा किया है बदल रहा है जब यूआई अगली घटना से निपटने के लिए तैयारी कर अद्यतन किया जाता है। यदि इस परिकल्पना सही है, तो मैं बस निम्नलिखित करना होगा:

-(void)assertIfNotFirstResponder:(UITextField*)field { 
    STAssertTrue([field isFirstResponder], nil); 
} 

- (void)testFirstResponder 
{ 
    [controller view]; 
    [[controller firstTextField] becomeFirstResponder]; 
    [self performSelector:@selector(@"assertIfNotFirstResponder:") withObject:[controller firstTextField] afterDelay:0.0]; 
} 

नोट: मैं एक 0.0 देरी का इस्तेमाल किया है क्योंकि मैं बस चाहता हूँ कि संदेश घटना कतार पर रख दिया और जितनी जल्दी हो सके भेजा जाता है। मुझे अपने घर के रखरखाव के लिए मुख्य लूप पर वापस जाने का एक तरीका चाहिए। इससे आपके मामले में कोई वास्तविक देरी नहीं होनी चाहिए। यदि आप एक ही तरह के कई परीक्षण निष्पादित कर रहे हैं, यानी पहले प्रतिक्रियाकर्ता के नियंत्रण को बार-बार बदलकर, इस तकनीक को यह गारंटी देनी चाहिए कि उन सभी घटनाओं को performSelector द्वारा उत्पन्न किए गए लोगों के साथ सही ढंग से आदेश दिया गया है।

आप एक अलग धागे से अपने परीक्षण चल रहे हैं, तो आप – performSelectorOnMainThread:withObject:waitUntilDone:

+1

अच्छा विचार, लेकिन यूनिट परीक्षण के लिए, इवेंट कतार पर एक संदेश डालने से काम नहीं होता है क्योंकि परीक्षण समाप्त होता है और दावा से पहले स्थिरता टूट जाती है। Counterexample: 'STAssertTrue' को 'STAssertFalse' में बदलना कोई फर्क नहीं पड़ता। –

+1

ठीक है, यह काम नहीं करेगा ... एक और संकेत के रूप में, मुझे पता चला है कि आप स्थिति का परीक्षण करने से पहले रन लूप के लिए कुछ समय तक दौड़ सकते हैं: '[[NSRunLoop currentRunLoop] runUntilDate: fiveSecondsFromNow];' (से: http://stackoverflow.com/questions/1077737/ocunit-test-for-protocols-callbacks-delegate-in-objective-c)। मुझे पूरी तरह से यकीन नहीं है कि यह समाधान वास्तव में "सुरुचिपूर्ण" है, लेकिन इसे काम करना चाहिए और "छोटे" मामलों के लिए उपयुक्त हो सकता है (जब आपको वास्तव में फ्रैंक के साथ जाने की आवश्यकता नहीं है) ... – sergio

+0

बढ़िया! शून्य का रन टाइम निर्दिष्ट करने से भी चाल चलती है। इस तरह के एक अद्भुत ढांचे के लिए –

6

आप सुनिश्चित करने के लिए पाठ फ़ील्ड दृश्य पदानुक्रम में स्थापित किया गया है की जरूरत है।

यदि दृश्य की विंडो संपत्ति में UIWindow ऑब्जेक्ट है, तो इसे दृश्य पदानुक्रम में स्थापित किया गया है; अगर यह शून्य लौटाता है, तो दृश्य किसी भी पदानुक्रम से अलग होता है।

उम्मीद है कि इस मदद करता है ....

+0

आप सही हैं, UIWindow शून्य था। क्या यूनिट टेस्ट में इसे बदलने का कोई तरीका है? दृश्य नियंत्रक को धक्का देना काम नहीं करता है क्योंकि यह चीजों को शेड्यूल करता है, लेकिन (जैसा कि @sergio की प्रतिक्रिया में उल्लेख किया गया है) जल्द ही यूनिट परीक्षण के लिए पर्याप्त नहीं है। –

+0

अब मेरे पास मेरा जवाब है। पहेली के भाग में भरने के लिए +1। –

2

इस्तेमाल कर सकते हैं यह इकाई परीक्षण के बजाय लगता है, तो यह स्वचालित स्वीकृति परीक्षण के लिए एक काम है। (Frank: Automated Acceptance Tests for iPhone and iPad देखें)

+0

+1! – sergio

+0

मैं सहमत हूं, दुर्भाग्य से जहां तक ​​मुझे पता है कि अब तक एक्सकोड नए यूआई परीक्षण ढांचे के साथ ऐसा करना संभव नहीं है। –

15

Xcode 5.1 और XCTestCase का उपयोग करना, यह ठीक काम करने के लिए लगता है: एक दृश्य/subview के लिए आदेश में

- (void)testFirstResponder 
{  
    // Make sure the controller's view has a window 
    UIWindow *window = [[UIWindow alloc] init]; 
    [window addSubview:controller.view]; 

    // Call whatever method you're testing 
    [controller.textView becomeFirstResponder]; 

    // Assert that the desired subview is the first responder 
    XCTAssertTrue([sut.textView isFirstResponder]); 
} 

पहले प्रत्युत्तर बनने के लिए, यह एक दृश्य पदानुक्रम की हिस्सा होना चाहिए, जिसका अर्थ है कि इसकी रूट व्यू की विंडो प्रॉपर्टी सेट होनी चाहिए।

जॉन और सर्जीओ का उल्लेख है कि आपको [[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]] को अपने वांछित सबव्यूव पर becomeFirstResponder पर कॉल करने के बाद कॉल करने की आवश्यकता हो सकती है, लेकिन मुझे पता चला कि यह हमारे उदाहरण में आवश्यक नहीं था।

हालांकि, आपका माइलेज भिन्न हो सकता है (यहां तक ​​कि आप जिस एक्सकोड का उपयोग कर रहे हैं उसके संस्करण के आधार पर), इसलिए आपको ऐसी कॉल शामिल करने की आवश्यकता हो सकती है या नहीं।

+0

क्या आपको विंडो को कुंजी विंडो के बिना काम करता है? – bejonbee

+0

आईओएस 10.3 के रूप में, यह इसे मुख्य विंडो बनाये बिना काम करता है। – XML

संबंधित मुद्दे