आप सही रास्ते पर हैं। Objc.io आलेख द्वारा सुझाए गए समाधान शायद ऐसा करने का सही तरीका है लेकिन कुछ रिफैक्टरिंग की आवश्यकता है। यदि आप एक कोड परिवर्तन बिंग पर जाने से पहले परीक्षण को पहले चरण के रूप में बनाना चाहते हैं, तो यहां आप यह कैसे कर सकते हैं।
आम तौर पर आप अपने सभी एसिंक परीक्षण करने के लिए XCTestExpectations का उपयोग कर सकते हैं। एक मानक पैटर्न इस तरह जाना हो सकता है:
XCTestExpectation *doThingPromise = [self expetationWithDescription:@"Bazingo"];
[SomeService doThingOnSucceed:^{
[doThingPromise fulfill];
} onFail:^ {
}];
[self waitForExpectationsWithTimeout:1.0 handler:^(NSError *error) {
expect(error).to.beNil();
}]
यह ठीक काम करता है अगर [SomeService doThingOnSucceed: onFail:] एक async अनुरोध को वापस ले आग और उसके बाद सीधे हल करता है। लेकिन क्या होगा अगर इस तरह की और विदेशी चीजों किया:
+ (void)doThingOnSucceed:onFail: {
[Thing do it];
[self.context performBlock:^{
// Uh oh Farfalle-Os
success();
}];
}
प्रदर्शन ब्लॉक की स्थापना के लिये होता है, लेकिन आप क्योंकि आप वास्तव में भीतरी खंड पर इंतजार कर नहीं कर रहे हैं उसके पूरा होने के लिए, बस बाहरी इंतजार कर नहीं किया जाएगा एक। कुंजी यह है कि XCTestWaits वास्तव में परीक्षण खत्म करने देता है और फिर केवल यह जांचता है कि वादा कुछ समय अवधि के भीतर पूरा हो गया था, लेकिन उस समय में यह अन्य परीक्षणों को शुरू करना शुरू कर देगा। वह सफलता() किसी भी संख्या में स्थानों को प्रदर्शित कर सकती है और किसी भी अजीब व्यवहार का उत्पादन करती है।
अलगाव व्यवहार (बनाम कोई अलगाव नहीं) इस तथ्य से आता है कि यदि आप केवल यह परीक्षण चलाते हैं तो सब कुछ भाग्य के कारण ठीक हो सकता है लेकिन यदि आप कई परीक्षण चलाते हैं जो कोरडाटा ब्लॉक को अगले परीक्षण तक लटका दिया जा सकता है एसिंक है, जो उसके निष्पादन को "अनब्लॉक" कर देगा और कुछ यादृच्छिक भविष्य के परीक्षण के लिए कुछ यादृच्छिक भविष्य के समय में इसे निष्पादित करना शुरू कर देगा।
छोटी अवधि के स्पष्ट हैक चारों ओर चीजें खत्म होने तक आपके परीक्षण को रोकना है।
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[SomeService doThingOnComplete:^{
dispatch_semaphore_signal(semaphore);
}];
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}
यह स्पष्ट रूप से पूरा करने से एक परीक्षण से बचाता है जब तक सब कुछ खत्म, जिसका अर्थ है कोई अन्य परीक्षण जब तक इस परीक्षण खत्म चला सकते हैं: यहाँ एक उदाहरण है।
यदि आपके परीक्षण/कोड में इनमें से बहुत से मामले हैं, तो मैं एक प्रेषण समूह बनाने के objc.io समाधान की अनुशंसा करता हूं जिसे आप प्रत्येक परीक्षण के बाद प्रतीक्षा कर सकते हैं।
(स्विफ्ट में) इस लागू करने के लिए कोशिश कर रहा है और मैं खोजने रहा है कि यह काम करता है, लेकिन यह सेमाफोर संकेतों के रूप में के रूप में जल्द जारी रखने के लिए नहीं है। यह Runloop.run पर लटकी हुई है जब तक समय समाप्त होता है। इस उम्मीद है? मेरे कोड: 'जबकि semaphore.wait (टाइमआउट: है अब()) == .timedOut { RunLoop.current.run (जब तक: तिथि (timeIntervalSinceNow: 10)) }' – guptron