jarmo / RAutomation

RAutomation
MIT License
100 stars 33 forks source link

An Issue of Timing #29

Closed enkessler closed 12 years ago

enkessler commented 12 years ago

Here's a little experiment:

  1. Open up an application window.
  2. Locate that window (by :title for the sake of argument) and store it in a handy variable.
  3. Check if it #exist?.
  4. Close the window.
  5. Reopen/relaunch the application window.
  6. Check if it #exists? again using the same variable.

According to RAutomation the window will not exist the second time. You won't be able to click buttons or grab values or anything else for that matter either because the instance of Window that the variable points to was fixed to a specific instance of a matching application window.

Here is the offending piece of code by the way:

    # Retrieves handle of the window.
    # @note Searches only for visible windows.
    # @see RAutomation::Window#hwnd
    def hwnd
      @hwnd ||= Functions.window_hwnd(@locators)
    end

Since most of the internal operations of a Window are handled via its @hwnd, as soon as you use it the first time you are tied to one exact application window.

Is this desired? Shouldn't a given RAutomation::Window object be able to interact with any application window as long as its locators match?

jarmo commented 12 years ago

It was intentional that the hwnd would be persistent so if you'd "attach" to some existing window then you can be sure that it is always the same window. It also makes sense in the programming code too semantically:

win = RAutomation::Window.new(:title => /title/)
win.exists? # true
win.close
win.exists? # false

# open up the window again
system("window")
win.exists? # true

It would be strange to look at the code where window got closed and similar window got opened and #exists? would return "true" suddenly. At least to me. I'd expect to see "RAutomation::Window.new" statement again after reopening the program...

I have thought that maybe creating an alias Window.attach to Window.new would make the code more readable.

So, in other words - i think that it makes sense performance-wise and in usage-wise. I think that it would be bad if you had multiple windows opened with the same title and then at some point your commands would be sent to different window OR it would be very hard to track that one of these windows got closed due to some reason, but they should have not. So i think that it's better to tie the instance with some specific window instead of having it loosely-tied to whichever suiting window.

Any additional thoughts?

enkessler commented 12 years ago

I can understand the desire to use the locators only once in order to permanently connect an RAutomation window to an OS window. I can also understand (mainly because it is how I try to use them most of the time) the desire to collectively use the locators as a window's sole identifier.

I like the idea of being able to use windows in either way. Maybe default RAutomation windows to us whatever OS window matches the locators at the time and also have Window.attach that would limit the Window to only one specific window. From the looks of it, controls in a window already get located anew every time they are interacted with and consistency would be nice.

As far as locators matching more than one window I will say that if you use ambiguous information then you are going to get ambiguous results and it shouldn't be a surprise. We have enough ways of specifying the desired object exactly to avoid the problem.

jarmo commented 12 years ago

I wouldn't like to make the API in any way more complex - e.g. .attach and .new should work the same. I still don't see what's the usecase by locating window always again? Why would you want to do that? I you want to match many windows, then you have a .windows method, which works almost like you want, because you will get all the windows matching the loosely put criteria.

You can't always restrict the locator to have very specific. For example, JS alert-prompt-confirm windows just have some title like "Message from a webpage", which is nothing too good to locate with.

I still see that it will cause more problems than adding any good value. Maybe having some method like ".relocate" would be good also for your usecase? I see it better solution than doing that implicitly since then anyone who reads the test will also see that window had to be relocated for some reason. Otherwise this fact might not come out.

Relocating controls all the time is not a problem since they're still in the same window and it's okay to do that since the area of effect is smaller. At least that's how i think.

So, what do you think about that relocate method, which would essentially do "@hwnd = nil" and nothing else?

enkessler commented 12 years ago

I think that such a method would not gain me anything since I would only be replacing all of the places that I currently have to call .new again and I would call .relocate instead. I would get to avoid the need to repass all of the arguments to .new but that's it.

I like the flexibility to have either 'floating' or 'attached' windows but, in order to maintain convenience, switching between the two modes should only need to be done once. Having an :mode argument in .new could allow Window objects to dynamically define their own #hwnd as appropriate when they are created. The mode can default to 'attached' if that's how most users expect it and there could be a method to switch between the two modes after creation if that would be useful.

jarmo commented 12 years ago

Seems too complicated API-wise to have yet another option and method for toggling that option. Please bring me some real life example where you've running against this issue in everyday life. I can't see myself thinking about any such case without it being awkward or little weird. Maybe the problem is instead at different end - e.g. in the application under test? Or is it really convenient and normal that the window is closed and reopened often? Why does it happen? I just don't see that it's normal that your test has side effects and "hidden agendas".

Having #relocate would be DRY when compared to executing .new with the exact same locators. This explicit method would show to the tester and developer that "it is normal behavior that window got reopened during this case." Why are you so much against it? Do you have to call it after every second line in your tests? Any other reason why you would want to put this implicit reattach into RAutomation?

I have tried to mimic Watir's API as much as possible and it too doesn't relocate IE window if it has been located once.

enkessler commented 12 years ago

Long story short: yes, the application under test is weird and has many strange side effects.

Consider the issue withdrawn.

jarmo commented 12 years ago

What about having still a #relocate method?

enkessler commented 12 years ago

It is useful enough to be worth providing. It is not the power level that I am looking for personally (I'd still rather have the ability to specify the behavior only once and move on) but most people aren't as picky as I am.