এক্সকোড ইউআই পরীক্ষার পরীক্ষার ক্ষেত্রে বিলম্ব / অপেক্ষা করুন


182

আমি এক্সকোড 7 বিটা 2 তে উপলব্ধ নতুন ইউআই টেস্টিং ব্যবহার করে একটি পরীক্ষার কেস লেখার চেষ্টা করছি The অ্যাপটির লগইন স্ক্রিন রয়েছে যেখানে এটি সার্ভারে লগইন করার জন্য একটি কল দেয়। এটি একটি অ্যাসিক্রোনাস অপারেশন হওয়ায় এটির সাথে যুক্ত একটি বিলম্ব রয়েছে।

আরও ধাপে এগিয়ে যাওয়ার আগে XCTestCase এ বিলম্ব বা অপেক্ষা করার ব্যবস্থা করার কোনও উপায় আছে কি?

কোনও যথাযথ ডকুমেন্টেশন উপলব্ধ নেই এবং আমি ক্লাসগুলির শিরোনাম ফাইলগুলি দিয়ে গিয়েছিলাম। এই সম্পর্কিত কিছু খুঁজে পেতে সক্ষম ছিল না।

কোন ধারণা / পরামর্শ?


13
আমার মনে হয় NSThread.sleepForTimeInterval(1)কাজ করা উচিত
কামেট্রিক্সম

গ্রেট! দেখে মনে হচ্ছে এটি কাজ করে। তবে এটি করার প্রস্তাবিত উপায় কিনা তা আমি নিশ্চিত নই। আমি মনে করি অ্যাপলের আরও ভাল উপায় দেওয়া উচিত। একটি রাডার দায়ের করতে থাকতে পারে
Tejas এইচ এস

আমি প্রকৃতপক্ষে সত্যিই মনে করি এটি ঠিক আছে, নির্দিষ্ট সময়ের জন্য বর্তমান থ্রেডটি বিরতি দেওয়া সত্যিই সবচেয়ে সাধারণ উপায়। আপনি আরো নিয়ন্ত্রণ করতে চান তাহলে আপনি GCD (মধ্যে পেতে পারেন dispatch_after, dispatch_queueকাপড়)
Kametrixom

@ কামেট্রিক্সম রান লুপটি টিক করবেন না - অ্যাপল বিটা ৪ এ দেশীয় অ্যাসিনক্রোনাস পরীক্ষার প্রবর্তন করেছিল বিশদর জন্য আমার উত্তরটি দেখুন ।
জো মাসিলোটি 26'15

2
সুইফট 4.0 -> থ্রেড.স্লিপ (ফর্মটাইম ইন্টারভাল: 2)
uplearnedu.com

উত্তর:


168

অ্যাসিঙ্ক্রোনাস ইউআই টেস্টিংটি এক্সকোড 7 বিটা 4 এ চালু হয়েছিল। "হ্যালো, বিশ্ব!" পাঠ্য সহ একটি লেবেলের জন্য অপেক্ষা করতে! প্রদর্শিত আপনি নিম্নলিখিত করতে পারেন:

let app = XCUIApplication()
app.launch()

let label = app.staticTexts["Hello, world!"]
let exists = NSPredicate(format: "exists == 1")

expectationForPredicate(exists, evaluatedWithObject: label, handler: nil)
waitForExpectationsWithTimeout(5, handler: nil)

ইউআই পরীক্ষার বিষয়ে আরও বিশদ আমার ব্লগে পাওয়া যাবে।


19
দুর্ভাগ্যক্রমে সময়সীমাটি ঘটেছিল তা স্বীকার করার এবং এগিয়ে যাওয়ার উপায় নেই - waitForExpectationsWithTimeoutস্বয়ংক্রিয়ভাবে আপনার পরীক্ষায় ব্যর্থ হবে যা দুর্ভাগ্যজনক।
জেদীদজা

@ জেডিডজা আসলে, এক্সকোড .0.০.১ নিয়ে আমার ক্ষেত্রে এটি ঘটে না।
বাস্তিয়ান

@ বাস্টিয়ান হুম আকর্ষণীয়; আমি এটি আবার পরীক্ষা করতে হবে।
জেদিদজা

1
এটা আমার জন্য কাজ করে না। এখানে আমার নমুনাটি দেওয়া যাক: xButton = app.toolbars.buttons ["X"] আসুন = এনএসপিডিকেট (বিন্যাস: "উপস্থিত == 1") প্রত্যাশাফোর্ডপ্রেডিকেট (উপস্থিত, মূল্যায়নউইট অবজেক্ট: এক্সবুটন, হ্যান্ডলার: শূন্য) ওয়েলফর এক্সপ্যাকশনস উইথটাইমআউট (10, হ্যান্ডলার: নিল)
ইমোলেমাসি

দেখে app.launch()মনে হচ্ছে কেবল অ্যাপটি পুনরায় চালু করা হবে। এটা কি দরকারি?
ক্রিস প্রিন্স

225

অতিরিক্তভাবে, আপনি কেবল ঘুমাতে পারেন:

sleep(10)

যেহেতু ইউআইটিএসটি অন্য প্রক্রিয়াতে চলে, এটি কাজ করে। আমি জানি না এটি কতটা পরামর্শযুক্ত, তবে এটি কার্যকর।


2
কিছু সময় আমাদের বিলম্ব করার উপায় প্রয়োজন এবং এটি একটি ব্যর্থতা বাড়াতে চাই না! ধন্যবাদ
তাই লে

13
আমি এর আগে সবচেয়ে ভাল উত্তরটি দেখেছি :) আমি + 100 ভোট যোগ করতে পারতাম :)
বার্তোমিয়েজ সেমাসেকজ

8
আমি এনএসটিড্রেড.স্লিপফোর্ডটাইমআইন্টারভালওয়ান (০.২) পছন্দ করি কারণ আপনি সাব-সেকেন্ড বিলম্বগুলি নির্দিষ্ট করতে পারেন। (ঘুম () পূর্ণসংখ্যার প্যারামিটার নেয়; কেবলমাত্র এক সেকেন্ডের বহুগুণ সম্ভব)।
গ্রাহাম পার্কস

5
@ গ্রাহাম্পার্কস, হ্যাঁ, যদিও এখানে রয়েছে:usleep
এমএক্সসিএল

3
এটি কোনও দুর্বল পরামর্শ নয় (ইউআইটিস্টিং কীভাবে কাজ করে আপনি তা পান না) তবে এটি একটি দুর্বল পরামর্শ হলেও কখনও কখনও এমন একটি প্রত্যাশা তৈরির কোনও উপায় নেই যা কাজ করে (সিস্টেম কাউকে সতর্ক করে?) তাই আপনার এটাই এটি is
এমএক্সসিএল

77

এক্সকোড 9 এক্সসিটিওয়াইটারের সাথে নতুন কৌশলগুলি প্রবর্তন করেছে

পরীক্ষার কেস স্পষ্টভাবে অপেক্ষা করে

wait(for: [documentExpectation], timeout: 10)

ওয়েটার উদাহরণ পরীক্ষা করার জন্য প্রতিনিধি

XCTWaiter(delegate: self).wait(for: [documentExpectation], timeout: 10)

ওয়েটার ক্লাসের ফলাফল ফলাফল

let result = XCTWaiter.wait(for: [documentExpectation], timeout: 10)
switch(result) {
case .completed:
    //all expectations were fulfilled before timeout!
case .timedOut:
    //timed out before all of its expectations were fulfilled
case .incorrectOrder:
    //expectations were not fulfilled in the required order
case .invertedFulfillment:
    //an inverted expectation was fulfilled
case .interrupted:
    //waiter was interrupted before completed or timedOut
}

নমুনা ব্যবহার

এক্সকোড 9 এর আগে

উদ্দেশ্য গ

- (void)waitForElementToAppear:(XCUIElement *)element withTimeout:(NSTimeInterval)timeout
{
    NSUInteger line = __LINE__;
    NSString *file = [NSString stringWithUTF8String:__FILE__];
    NSPredicate *existsPredicate = [NSPredicate predicateWithFormat:@"exists == true"];

    [self expectationForPredicate:existsPredicate evaluatedWithObject:element handler:nil];

    [self waitForExpectationsWithTimeout:timeout handler:^(NSError * _Nullable error) {
        if (error != nil) {
            NSString *message = [NSString stringWithFormat:@"Failed to find %@ after %f seconds",element,timeout];
            [self recordFailureWithDescription:message inFile:file atLine:line expected:YES];
        }
    }];
}

, USAGE

XCUIElement *element = app.staticTexts["Name of your element"];
[self waitForElementToAppear:element withTimeout:5];

দ্রুতগতি

func waitForElementToAppear(element: XCUIElement, timeout: NSTimeInterval = 5,  file: String = #file, line: UInt = #line) {
        let existsPredicate = NSPredicate(format: "exists == true")

        expectationForPredicate(existsPredicate,
                evaluatedWithObject: element, handler: nil)

        waitForExpectationsWithTimeout(timeout) { (error) -> Void in
            if (error != nil) {
                let message = "Failed to find \(element) after \(timeout) seconds."
                self.recordFailureWithDescription(message, inFile: file, atLine: line, expected: true)
            }
        }
    }

, USAGE

let element = app.staticTexts["Name of your element"]
self.waitForElementToAppear(element)

অথবা

let element = app.staticTexts["Name of your element"]
self.waitForElementToAppear(element, timeout: 10)

উৎস


1
উপরের এক্সকোড ৯ উদাহরণ সম্পর্কিত আরও কিছু চিত্র খুঁজছেন
rd_

আপনি চেক করতে পারেন shashikantjagtap.net/asynchronous-ios-testing-swift-xcwaiter
টেড

1
পরীক্ষিত। একটি যাদুমন্ত্র মত কাজ করে! ধন্যবাদ!
দাউদ কনসেউইচজ

77

আইওএস 11 / এক্সকোড 9

<#yourElement#>.waitForExistence(timeout: 5)

এটি এই সাইটে সমস্ত কাস্টম বাস্তবায়নের জন্য একটি দুর্দান্ত প্রতিস্থাপন!

আমার উত্তরটি এখানে একবার দেখতে ভুলবেন না: https://stackoverflow.com/a/48937714/971329 । সেখানে আমি অনুরোধগুলির জন্য অপেক্ষা করার একটি বিকল্প বর্ণনা করেছি যা আপনার পরীক্ষাগুলি চালানোর সময়কে হ্রাস করবে!


ধন্যবাদ @ দাইদাই আমি পাঠ্য পরিবর্তন করেছি :)
ব্ল্যাকজ্যাক্স

1
হ্যাঁ XCTestCaseএটি ব্যবহার করার সময় আমি যে পদ্ধতির জন্য যাচ্ছি এটি এখনও এখনও এটি মনোযোগের মতো কাজ করে। আমি বুঝতে পারি না কেন sleep(3)এখানে কেন এমন পদ্ধতির এত বেশি ভোট দেওয়া হয় যেহেতু এটি পরীক্ষার সময়টি কৃত্রিমভাবে প্রসারিত করে এবং যখন আপনার পরীক্ষার স্যুট বড় হয় তখন সত্যিই কোনও বিকল্প হয় না।
ব্ল্যাকজ্যাক্স

আসলে এটির জন্য এক্সকোড 9 প্রয়োজন, তবে ডিভাইস / সিমুলেটরগুলিতে আইওএস 10 চালানো হিসাবেও কাজ করে ;-)
d4Rk

হ্যাঁ আমি এটি উপরের শিরোনামে লিখেছি। তবে এখন বেশিরভাগ লোকের কমপক্ষে এক্সকোড 9 ;-) আপগ্রেড করা উচিত ছিল
ব্ল্যাকজ্যাক্স

32

এক্সকোড 8.3 হিসাবে, আমরা http://masilotti.com/xctest-waiting/ ব্যবহার করতে পারিXCTWaiter

func waitForElementToAppear(_ element: XCUIElement) -> Bool {
    let predicate = NSPredicate(format: "exists == true")
    let expectation = expectation(for: predicate, evaluatedWith: element, 
                                  handler: nil)

    let result = XCTWaiter().wait(for: [expectation], timeout: 5)
    return result == .completed
}

আরেকটি কৌশলটি একটি waitফাংশন লেখার জন্য, এটি আমাকে দেখানোর জন্য কৃতিত্ব জন সানডেলের কাছে যায়

extension XCTestCase {

  func wait(for duration: TimeInterval) {
    let waitExpectation = expectation(description: "Waiting")

    let when = DispatchTime.now() + duration
    DispatchQueue.main.asyncAfter(deadline: when) {
      waitExpectation.fulfill()
    }

    // We use a buffer here to avoid flakiness with Timer on CI
    waitForExpectations(timeout: duration + 0.5)
  }
}

এবং এটি পছন্দ করুন

func testOpenLink() {
  let delegate = UIApplication.shared.delegate as! AppDelegate
  let route = RouteMock()
  UIApplication.shared.open(linkUrl, options: [:], completionHandler: nil)

  wait(for: 1)

  XCTAssertNotNil(route.location)
}

11

@ টেডের উত্তরের ভিত্তিতে , আমি এই এক্সটেনশনটি ব্যবহার করেছি:

extension XCTestCase {

    // Based on https://stackoverflow.com/a/33855219
    func waitFor<T>(object: T, timeout: TimeInterval = 5, file: String = #file, line: UInt = #line, expectationPredicate: @escaping (T) -> Bool) {
        let predicate = NSPredicate { obj, _ in
            expectationPredicate(obj as! T)
        }
        expectation(for: predicate, evaluatedWith: object, handler: nil)

        waitForExpectations(timeout: timeout) { error in
            if (error != nil) {
                let message = "Failed to fulful expectation block for \(object) after \(timeout) seconds."
                self.recordFailure(withDescription: message, inFile: file, atLine: line, expected: true)
            }
        }
    }

}

আপনি এটি ব্যবহার করতে পারেন

let element = app.staticTexts["Name of your element"]
waitFor(object: element) { $0.exists }

এটি কোনও উপাদান অদৃশ্য হওয়ার অপেক্ষার জন্য বা অন্য কোনও সম্পত্তি পরিবর্তনের জন্য উপযুক্ত অনুমতি দেয় (উপযুক্ত ব্লকটি ব্যবহার করে)

waitFor(object: element) { !$0.exists } // Wait for it to disappear

+1 খুব তাত্পর্যপূর্ণ এবং এটি ব্লক প্রিকেটটি ব্যবহার করে যা আমি অনেক বেশি ভাল বলে মনে করি কারণ স্ট্যান্ডার্ড প্রিকেট এক্সপ্রেশনগুলি কখনও কখনও আমার পক্ষে কাজ করে না, উদাহরণস্বরূপ XCUIE উপাদান ইত্যাদিতে কিছু সংখ্যার জন্য অপেক্ষা করার সময়
Lawicko

10

সম্পাদনা:

এটি আসলে আমার কাছে ঘটেছিল যে এক্সকোড 7 বি 4-তে, এখন ইউআই টেস্টিং রয়েছে expectationForPredicate:evaluatedWithObject:handler:

মূল:

আরেকটি উপায় হ'ল একটি নির্দিষ্ট সময়ের জন্য রান লুপটি স্পিন করা। সত্যিই কেবলমাত্র দরকারী যদি আপনি জানেন যে আপনার কতটা (আনুমানিক) সময় অপেক্ষা করতে হবে

OBJ-সি: [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow: <<time to wait in seconds>>]]

সুইফট: NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate(timeIntervalSinceNow: <<time to wait in seconds>>))

আপনার পরীক্ষা চালিয়ে যাওয়ার জন্য যদি কিছু শর্ত পরীক্ষা করতে হয় তবে এটি খুব কার্যকর নয়। শর্তসাপেক্ষ চেক চালাতে, একটি whileলুপ ব্যবহার করুন ।


এটি আমার জন্য পরিষ্কার এবং খুব দরকারী বিশেষত অ্যাপ্লিকেশন লঞ্চের জন্য অপেক্ষা করা, প্রিলোডড ডেটার জন্য অনুরোধ করুন এবং লগইন / লগআউট স্টাফগুলি করুন। ধন্যবাদ.
felixwcf

4

নিম্নলিখিত কোডটি কেবলমাত্র উদ্দেশ্য সি নিয়ে কাজ করে

- (void)wait:(NSUInteger)interval {

    XCTestExpectation *expectation = [self expectationWithDescription:@"wait"];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [expectation fulfill];
    });
    [self waitForExpectationsWithTimeout:interval handler:nil];
}

কেবল নীচে দেওয়া হিসাবে এই ফাংশন কল করুন।

[self wait: 10];

ত্রুটি -> "NSInternInconsistencyException", "API লঙ্ঘন - কোনও প্রত্যাশা সেট না হয়ে অপেক্ষা করার জন্য কল করা হয়েছে"।
ফ্লোইউআই সিম্পলআইটিস্টিং ডটকম

@ আইওএসক্যালেন্ডারপ্যাচথেকোড.কম, আপনি কি এর জন্য বিকল্প সমাধান খুঁজে পেয়েছেন?
সর্বাধিক

@ ম্যাক্স আপনি এই পৃষ্ঠায় অন্য যে কোন একটি ব্যবহার করতে পারেন?
ফ্লোইউআই সিম্পলইউটিস্টিং ডটকম

@ আইওএসসিলেটরপ্যাচথেকোড.কম, না, আমাকে কোনও উপাদান ছাড়াই কিছুটা বিলম্ব দরকার check সুতরাং আমি এই বিকল্প প্রয়োজন।
সর্বোচ্চ

@ ম্যাক্স আমি এই পৃষ্ঠায় নির্বাচিত উত্তর ব্যবহার করেছি। এটা আমার জন্য কাজ করেছে। আপনি তাদের বিশেষত কোনটি সন্ধান করছেন তা জানতে চাইতে পারেন।
ফ্লোইউআই সিম্পলআইটিস্টিং ডটকম

4

আমার ক্ষেত্রে sleepপার্শ্ব প্রতিক্রিয়া তৈরি হয়েছে তাই আমি ব্যবহার করেছিwait

let _ = XCTWaiter.wait(for: [XCTestExpectation(description: "Hello World!")], timeout: 2.0)

0

এক্সসিইউআইলেমেন্টের এপিআই অনুসারে .existsকোনও প্রশ্নের উপস্থিতি আছে কিনা তা যাচাই করতে ব্যবহার করা যেতে পারে তবে নিম্নলিখিত সিনট্যাক্সটি কিছু ক্ষেত্রে কার্যকর হতে পারে!

let app = XCUIApplication()
app.launch()

let label = app.staticTexts["Hello, world!"]
while !label.exists {
    sleep(1)
}

আপনি যদি নিশ্চিত হন যে আপনার প্রত্যাশা শেষ পর্যন্ত পূরণ হবে তবে আপনি এটি চালানোর চেষ্টা করতে পারেন। এটি লক্ষ করা উচিত যে waitForExpectationsWithTimeout(_,handler:_)@ জো ম্যাসিলোটির পোস্টটি ব্যবহার করা উচিত এমন ক্ষেত্রে অপেক্ষাটি যদি দীর্ঘ হয় তবে ক্রাশ হওয়া পছন্দনীয় ।


0

ঘুম থ্রেড ব্লক করবে

"থ্রেডটি ব্লক করা অবস্থায় কোনও রান লুপ প্রক্রিয়াজাতকরণ ঘটে না।"

আপনি ওয়েটফরএক্সিজেন্ড ব্যবহার করতে পারেন

let app = XCUIApplication()
app.launch()

if let label = app.staticTexts["Hello, world!"] {
label.waitForExistence(timeout: 5)
}

0

এটি থ্রেডটিকে ঘুমিয়ে না রেখে বা সময়সীমাতে ত্রুটি না ছড়িয়ে দেরি করবে:

let delayExpectation = XCTestExpectation()
delayExpectation.isInverted = true
wait(for: [delayExpectation], timeout: 5)

প্রত্যাশাটি উল্টে যাওয়ার কারণে এটি নিঃশব্দে সময়সাপেক্ষ হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.