In web integration testing, page objects are expected to return other page objects as a result of some actions. For example, a LoginForm.submit()
may return CustomerDashboard
page object on success or a LoginFailed
object on failure.
What I'm having difficulty understanding is what happens when the system is not quite that deterministic. For example Order.submit()
may result in a OrderProcessing
page, or an OrderProcessed
page. What's the best way to handle such a scenario? Should Order.submit()
return a tuple of possible PageObjects that then get handled in the individual test? What is the recommended approach here?
Update with an expanded problem statement
Imagine you have an shopping system that accepts orders. When submitting an order, the system may process the order immediately or the order may be placed in the queue. Eventually, the queued order gets processed. In Rubyish pseudocode the page-object objects responsible for testing this would be:
class ProcessedOrderPage < PageObject
item order_id;
item delivery_date;
end
class QueuedOrderPage < PageObject
item orderInQueue;
end
class OrderPage < PageObject
def submit_order_for_immediate_processing
return ProcessedOrderPage.new
end
def submit_order_for_queued_processing
return ProcessingOrderPage
end
end
So then in our tests we can do things like:
processed_page = orderPage.submit_for_immediate_processing
assert_not_nil processed_page.order_id
or we can test the other scenario:
queued_page = orderPage.submit_for_queued_processing
assert_not_nil queued_page.orderInQueue
The idea here is that we know the expected behaviour exactly, so we can invoke the helpers that return the expected page object. In fact this is described pretty well in this question on SO.
I'm trying to handle a scenario where the behaviour is not so deterministic. Imagine that submit_for_immediate_processing
and submit_for_queued_processing
above are collapsed into a single method, submit_for_processing
and the behaviour is determined by the runtime properties of the system. That is, the order is either processed immediately or is placed in the queue. This behaviour is not ideal from the testing standpoint, but it is what it is. I'd like to understand who is responsible for determining the outcome of this submit_for_processing
method. In this particular case, I'm not really interested in the "queued" state anyway. I want to get to the point where the order is processed, so I can verify various order properties.
The current best practice for using page objects is to keep them as decoupled as possible, and avoid chaining.
It is easier to see what is going on in the test if you are doing:
versus:
As for the indeterminate state issue, you likely need to follow the pattern of waiting for a condition to be met (order processed) to synchronize the test with expectations and then proceed. Something like this: