ScreenPyHQ / screenpy

Screenplay pattern base for Python automated UI test suites.
MIT License
27 stars 3 forks source link

Investigate whether we can have `Always` and `Never` Actions. #59

Open perrygoy opened 1 year ago

perrygoy commented 1 year ago

These two actions would take in a performable to be repeatedly performed, maybe on a configurable interval, for the duration of the test. Some example use-cases:

the_actor.should(Never(See.the(Element(ERROR_POPUP), IsVisible()))
the_actor.attempts_to(Always(Click.on_the(BIG_COOKIE)))

Some things we need to consider:

bandophahita commented 1 year ago

I started to write a note about how "Technically speaking it should read 'Always click on the target, WHEN IT APPEARS'" but that got me asking the question, does a distinction exist?

Is it possible to "Always click on target" without the clarification of 'when exists'? or does that qualifier accompany the idea of "Always" in all circumstances?

perrygoy commented 1 year ago

When i wrote this spike, my thought was that Always would just always try, regardless of whether it was successful or not, while Never would expect its Action to always fail. I can see the alternate reading of Always, in that it should always be successful, though.

I think that reading makes more sense, actually. Always should always work, and Never should never work. If someone wants something like what you're describing (always click on the thing, if it's there), they would need to write a Task to supply to Always that checks for it to be there first, then clicks (or uses TriesTo...? 😁).

I've been thinking about this problem on-and-off, and i think we might need to pair it with some kind of Question to ask at the end of the test. I think if we have Always and Never each spawn a thread, we would be able to note the thread's reference using the Director. At the end of the test, we'd have to ask the Question: did all the Alwayses and all the Nevers meet their expectations? I'm not sure how to word that Question, and i'm not sure this is the only way to do it.

To summarize that in some pseudocode:

the_actor.attempts_to(
    Always(Click.on_the(BIG_COOKIE),
    Never(See.the(Element(GRANDMA_APOCALYPSE_BANNER), IsVisible()),
    Pause.for(300).seconds_because("we want to click for 300 seconds.")  # Always and Never will still perform, here
)

...

the_actor.should(
    See.the(RepetitiveActions(), WereSuccessful())  # ???
)

In that last bit, we'd ask the Director for all of the threads and join them, then check for any exceptions raised. If there were some, we could give a list of all of them in the failure state... we'd have to have some nice exception messages to link the correct Always and Nevers.

Anyway, what do you think about all of this?