kif-framework / KIF

Keep It Functional - An iOS Functional Testing Framework
Other
6.21k stars 914 forks source link

`waitForView` fails and doesn't return `nil` #1222

Closed HassanElDesouky closed 3 years ago

HassanElDesouky commented 3 years ago

I want to catch timeout failures inside of my logger. I want to do something like that:

guard let identifierView = uiDriver().usingIdentifier("not_available_identifier"),
          let view = identifierView.waitForView() else {
            Log("Failed to find the view with identifier:\(identifier)")
            return
        }
            view.tap()

However, the above will timeout and fail inside KIF.

I can't use tryFindingView because as the docs say "If the element isn't found, then the step will not wait and instead immediately return NO"

dostrander commented 3 years ago

I'm a little confused at the issue.

Is waitForView returning nil or is it failing inside of KIF? Also what do you mean by it failing inside of KIF is it timing out trying to find the view or is it crashing?

HassanElDesouky commented 3 years ago

Is waitForView returning nil or is it failing inside of KIF?

It's not returning nil.

Also what do you mean by it failing inside of KIF is it timing out trying to find the view or is it crashing?

I mean it's timing out and not returning nil.

justinseanmartin commented 3 years ago

I don't think it makes sense to alter the behavior of waitForView to handle this use case, because that would be a breaking change. The documentation in tryFindingView is slightly inaccurate, as it will poll for 1s, instead of the timeout interval (10s unless overridden). It seems reasonable to alter that behavior to allow it to respect the usingTimeout: interval if explicitly specified, but still default to 1s instead of 10s.

The reason for this behavior in tryFindingView is it is expected to not find a match sometimes and waiting 10s to determine that will slow down tests. Tests should generally be deterministic, so needing a test to have logic based on the presence/absence of a view is considered an anti-pattern. I don't know if that's exactly what you're doing with your logger scenario, so this may not apply.

I think the way I'd handle your logger scenario is to create your a subclass of KIFTestCase and override the behavior in failWithException:. Alternatively, you could do something similar by making your own actor type that can customize actor behavior and hook in logging. If there are changes that can be made to expose more information that would help with your logger, let us know your suggestions here.

HassanElDesouky commented 3 years ago

@justinseanmartin I decided to go with subclassing of KIFTestCase and overriding the behavior in failWithException. Thank you for suggesting that.