fhoeben/hsac-fitnesse-fixtures

Unpredictable popup that requires specific handling

pvbemmelen62 opened this issue · 5 comments

We're testing a complex web application, where clicking and entering data in the user interface, may cause asynchronous data-handling actions going on behind the scenes.
Sometimes when performing a click or enter, a popup is shown by the application, saying something like "the data you are using has been changed by a background process" ; and the application won't have carried out the click or enter. To solve this, the following steps need to be taken:

  1. confirm the popup
  2. do whatever is needed to refresh the data that you are working on.
  3. do the click or enter again (assumption: this time there won't be a popup)

The appearance of the popup is unpredictable; a particular click or enter may show the popup during one testrun, and not show it on the next testrun.
When running a script multiple times, you may find that the popup is more likely at certain points during the execution of a script.

One could prevent the popup from occurring at all, by always refreshing the data (step 2) before doing the click or enter.
But step 2 may be relatively time-consuming; there could be a large table on the screen, and all its data would need to be refreshed and repainted on screen.
You want to do step 2 only when the popup is shown.
What is required for step 2, will depend on where in the script the popup occurs. Step 2 may be as simple as one instruction, or it may require two or more instructions.

Yes, it's a nasty web application. Is there any way to handle this in our Fitnesse scripts ?

@pvbemmelen62 I believe this is possible, but will require a custom subclass of BrowserTest.

I'm a bit too busy at the moment to dive deeply into this at the moment, but it sounds like you need to either override the method to handle the click/enter to check whether the pop up appears and add additional behaviour when it is present.

If just overriding a few methods is not enough you can even add something similar to what I implemented for 'rich faces' (in RichFacesTest) or Angular (in BrowserTest). There I added extra behaviour to the generic behaviour of the fixture.
The 'hooks' beforeInvoke() and invoke() can be overridden to add generic behaviour to all methods invoked via FitNesse. But be careful: they will be added to all calls so make sure to check whether the method being called indeeds needs the extra behaviour (and is not something like setting a timeout or taking a screenshot)

@fhoeben There are two issues that need to be addressed, when implementing automatic handling of the popup:

  1. What you need to do in step 2 may vary depending on where in the script the popup appears; there may not be a refresh command that solves all problems wherever you are in the script; maybe for a specific table in the script, you want to specify specific commands that will achieve the refresh. Would it be possible to have a scenario "refresh record" that is called for step 2 , and that can be defined in the test script ?
  2. Step 3 requires to do the click or enter again. Is that easier to implement in the click and enter methods of BrowserTest, because there you know the specific click/enter command that is being executed? I have no idea if you could do it in 'beforeInvoke()' and 'invoke()'.

If we would add the popup handling behaviour , and are afraid of the performance drop cause by the testing for the popup, then we could add a flag that the script writer can set, to activate the behaviour only for those commands where it is found to be needed. I'm hoping that the testing for that flag causes very little performance drop.

@pvbemmelen62

  1. Calling a scenario does not seem possible from the fixture's Java code. At that point FitNesse already resolved all scenarios and I don't believe you can alter the 'wiki contents' to add steps of any kind to the script let alone dynamically query the definition of a scenario by name and adding its content.
  2. Doesn't need to be an issue from invoke() as there I expect you would be able to just call the method being executed again. I do something similar when waiting for elements to appear or dealing with 'stale elements' I believe.

But the fact that you do not know how to address the issue statically seems like a big issue to fix this in code. How horrible this must be for actual users. Are they provided with a manual: if you get this error in location a then you have to perform steps 'a', 'b', 'c'; if you get it at location b then you have to do 'x', 'y' and 'z'?

If there are just a couple of these remediation steps/scenarios maybe you can code behaviour for each? Ideally with a check in the code to automatically determine which path to choose, otherwise you need to add some sort of setter to configure with steps to do on issues.

It doesn't sound nice at all...

@fhoeben This afternoon I had a meeting with a senior tester and a programmer, and we found that the most viable solution is to try and avoid the alert from appearing at all.

For instance, when you create a client record, by entering name, country, birth date, and other simple data , then before adding other data like documents, we let the script wait 2 seconds, and then fetch the client record we just created by searching for it through a query.
The hope is, that the query will return the client record as it is internally, including any changes made by background processes.
Will this always prevent the alert from popping up? No guarantee, unfortunately. It's just a matter of trying, and see if it works most of the time. Without the wait for 2 seconds, the chance that a background process makes a change after we fetched the record, will increase.
(While writing this, I must admit, I still don't really understand how a "merge" conflict is avoided this way. Maybe I'd have to ask the programmer again.)

We'll document the places/actions in the program where the popup might appear, and how to try and avoid it from appearing.
That way the testers will learn more, and hopefully won't lose time dealing with this problem.

Anyway, in the meeting I learned that dealing with the alert in the code is practically impossible: clicking OK in the alert, will close the alert, but will also overwrite the data shown on screen, with the version of that data as is maintained internally; i.e. with the version including changes made by the background process. For how many fields you'd have to re-enter data, depends on how many fields were successfully stored earlier, and are retained in that internal version.
You could enter a value, and immediately store it; and only then enter the next value, and immediately store it; etc.
That way you would always have only one value to re-enter when encountering the alert. By all those stores would probably come with a significant performance drop.

I'll close the call. Thanks for your support.

See earlier comment.