Pywinauto waiting too long to do an action - python

I need help.
I'm doing a UI automation, and it works properly.
However, it waits for all controls get done, but for example, the textbox I want to send keys is activated.
Because of that, my automation is very slow, and I couldn't find any helpful information in module documentation.
Thank you all

I find out the solution. If you have the same problem, you should always search for controls, with child_window function.
If you use the bracket notation, pywiauto will search all controls from root window, and depending the application, it takes a long time.
However, using child window, you can filter by control type, title and automation id

Global timings for every operation can be changed in module pywinauto.timings:
https://pywinauto.readthedocs.io/en/latest/code/pywinauto.timings.html
But please be careful. Aggressive timings can make some actions unstable.

Related

PyWinAuto - How do I check when a button control becomes visible?

I am writing UI Automation tests for a WPF application that has a button which only becomes enabled on the UI when certain conditions are met.
I've read through all the uia_controls wrappers available to use (https://pywinauto.readthedocs.io/en/latest/code/pywinauto.controls.uia_controls.html) and there doesn't seem to be one that will allow me to check whether a button control is enabled before clicking on it.
Please advise if pywinauto is able to check that a button is enabled before interacting with it.
Check the enabled property of the element_info.
https://pywinauto.readthedocs.io/en/latest/code/pywinauto.element_info.html#pywinauto.element_info.ElementInfo.enabled
There are few ways. The first one is calling .wait('visible', timeout=10) on WindowSpecification object. The second one is checking return result of method .is_visible() for the wrapper object. Of course, you should know the difference between WindowSpecification and wrapper (see the Getting Started Guide).
Also see chapter Waiting for Long Operations.
P.S. Using UIAElementInfo directly is not recommended as it is low level of the implementation hidden behind wrapper interface.

Switching Windows with Python

I'll preface this by saying that I'm very inexperienced with python, and I'm hoping that means the solution to my problem will be simple.
My program will be performing simple actions in another window, so ideally I would like my script to make sure that this other window is maximized and active before it proceeds with the rest of the commands. This has proved to be much more difficult than I had expected.
I am fairly certain that I can achieve this with win32gui using find_window and setting it to the foreground. I thought I had found my solution when I came across this previous question:
Python Window Activation
Unfortunately I was unable to use the solution code or manipulate it to solve my problem for a few reasons:
-The way that user had defined find_window only allows you to choose by the classname of the window, which I don't know and haven't been able to find since it is just a game running in Java. I couldn't seem to change that line to work for the specific windowname (Which I do know) as it is not the "default argument".
-I don't want to enumerate the windows to find it as I'm not sure how that would work.
-using find_window_wildcard as it's written in that script has managed to bring the window to the foreground a few times, but only if the window was already open, and it only works intermittently.
-set_foreground() requires one input statement and no matter how I try to set it I am always given an error that I either have the wrong number of elements or an invalid handle on the window.
I know that I'm stupid; but a clear and concise solution to this problem or at least a good explanation of the find_window/getwindow syntax would be a godsend to myself and anyone else who's having this problem.
I would strongly suggest you take a look at the pages for Swapy and for pywinauto. They can help you do some awesome things when it comes to UI Automation.
The way that user had defined find_window only allows you to choose by the classname of the window
The way the user defined it is to pass the two parameters class_name and window_name through, untouched, to win32gui.FindWindow (which in turn just calls the Win32 API function FindWindow). So, just do this:
windowmgr.find_window(None, 'My Window Name')
But even if that weren't true, you don't need to use his find_window function; it should be pretty obvious how to call win32gui.FindWindow yourself:
hwnd = win32gui.FindWindow(None, 'My Window Name')
And if you want a good explanation of the FindWindow/EnumWindows/etc. syntax, did you try looking at the docs for them? Is there something you didn't understand there?
Meanwhile:
… the classname of the window, which I don't know and haven't been able to find since it is just a game running in Java
What difference does it make that it's running in Java? You can enumerate the windows and print out their classnames, whether they're written in C++, Java, .NET, Python, or anything else. Or use one of the tools that comes with Visual Studio/VS Express, or any of the free improved versions you can find all over the net, like MS Spy++, which will let you point at a window and give you the caption and class name.
I don't want to enumerate the windows to find it as I'm not sure how that would work.
Just call windowmgr.find_window_wildcard(wildcard) with a regular expression, and it'll enumerate the windows and compare their titles to that regular expression.
If you want to write your own code to do it, just write a function like this:
def my_callback(hwnd, cookie):
Now, when you do this:
win32gui.EnumWindows(my_callback, some_cookie)
… it will call your my_callback function once per window, with hwnd being the window (which you can pass to win32gui functions like, e.g., GetWindowText), and cookie being the same some_cookie value you passed in. (If you don't need anything passed in, just pass None, and don't do anything with the value in your callback function. But you can see how the other answerer used it to pass the regular expression through.)
Meanwhile:
using find_window_wildcard as it's written in that script has managed to bring the window to the foreground a few times, but only if the window was already open, and it only works intermittently.
First, you can't bring a window to the foreground if it doesn't exist. How do you expect that to work?
As far as working intermittently, my guess is that there are lots of windows that match your wildcard, and the program is going to just pick one of them arbitrarily. It may not be the one you want. (It may even be a hidden window or something, so you won't see anything happen at all.)
At any rate, you don't need to use find_window_wildcard; if you know the exact name, use that. Of course it still may not be unique (whatever the game's name is, there's nothing stopping you from opening an email message or a Notepad window with the same title… which, by the way, is why you want to try class names first), but at least it's more likely to be unique than some underspecified wildcard.
So, what if the class name isn't unique (or, even worse, it's one of the special "number" classes, like #32770 for a general dialog window), and neither is the window name? You may be able to narrow things down a little better by looking at, say, the owning process or module (exe/dll), or the parent window, or whatever. You'll have to look through the win32gui and/or MSDN docs (linked above) for likely things to try, and play around through trial and error (remember the Spy tool, too) until you find some way to specify the window uniquely. Then code that up.

wxPython - Disable a whole menu

I have come across a problem while using wxPython lately: I want to grey out a whole wx.Menu and I can't find a way to do it. I could disable all the wx.MenuItem instances related to the wx.Menu, but I find it less efficient ergonomically speaking than greying out the menu itself.
The wx.Menu class has a method named Enable() which accepts the 'enable' argument, but its solely use is to enable/disable a related wx.MenuItem and not the wx.Menu itself. Actually, I'm not even sure that what I want can be done.
However, I would be glad to listen to your solutions if you have some.
Enable is just for the menu items. EnableTop should counter-intuitively disable the entire menu. See my old tutorial on menus about half-way down for more info. Here's how I did it:
self.menuBar.EnableTop(0, False)
Note that it's zero-based, so zero is the first menu, one is the second, etc.

Take all input in Python (like UAC)

Is there any way I can create a UAC-like environment in Python? I want to basically lock the workstation without actually using the Windows lock screen. The user should not be able to do anything except, say, type a password to unlock the workstation.
You cannot do this without cooperation with operating system. Whatever you do, Ctrl-Alt-Del will allow the user to circumvent your lock.
The API call you're looking for Win32-wise is a combination of CreateDesktop and SetThreadDesktop.
In terms of the internals of Vista+ desktops, MSDN covers this, as does this blog post. This'll give you the requisite background to know what you're doing.
In terms of making it look like the UAC dialog - well, consent.exe actually takes a screenshot of the desktop and copies it to the background of the new desktop; otherwise, the desktop will be empty.
As the other answerer has pointed out - Ctrl+Alt+Delete will still work. There's no way around that - at least, not without replacing the keyboard driver, anyway.
As to how to do this in Python - it looks like pywin32 implements SetThreadDesktop etc. I'm not sure how compatible it is with Win32; if you find it doesn't work as you need, then you might need a python extension to do it. They're not nearly as hard to write as they sound.
You might be able to get the effect you desire using a GUI toolkit that draws a window that covers the entire screen, then do a global grab of the keyboard events. I'm not sure if it will catch something like ctrl-alt-del on windows, however.
For example, with Tkinter you can create a main window, then call the overrideredirect method to turn off all window decorations (the standard window titlebar and window borders, assuming your window manager has such things). You can query the size of the monitor, then set this window to that size. I'm not sure if this will let you overlay the OSX menubar, though. Finally, you can do a grab which will force all input to a specific window.
How effective this is depends on just how "locked out" you want the user to be. On a *nix/X11 system you can pretty much completely lock them out (so make sure you can remotely log in while testing, or you may have to forcibly reboot if your code has a bug). On windows or OSX the effectiveness might be a little less.
I would try with pygame, because it can lock mouse to itself and thus keep all input to itself, but i wouldn't call this secure without much testing, ctr-alt-del probably escape it, can't try on windows right now.
(not very different of Bryan Oakley's answer, except with pygame)

How to make PowerBuilder UI testing application?

I'm not familiar with PowerBuilder but I have a task to create Automatic UI Test Application for PB. We've decided to do it in Python with pywinauto and iaccesible libraries. The problem is that some UI elements like newly added lists record can not be accesed from it (even inspect32 can't get it).
Any ideas how to reach this elements and make them testable?
I'm experimenting with code for a tool for automating PowerBuilder-based GUIs as well. From what I can see, your best bet would be to use the PowerBuilder Native Interface (PBNI), and call PowerScript code from within your NVO.
If you like, feel free to send me an email (see my profile for my email address), I'd be interested in exchanging ideas about how to do this.
I didn't use PowerBuilder for a while but I guess that the problem that you are trying to solve is similar to the one I am trying to address for people making projects with SCADA systems like Wonderware Intouch.
The problem with such an application is that there is no API to get or set the value of a control. So a pywinauto approach can't work.
I've made a small tool to simulate the user events and to get the results from a screencapture. I am usig PIL and pytesser ORM for the analysis of the screen captures. It is not the easiest way but it works OK.
The tool is open-source and free of charge and can be downloaded from my website (Sorry in french). You just need an account but it's free as well. Just ask.
If you can read french, here is one article about testing Intouch-based applications
Sorry for the self promotion, but I was facing a similar problem with no solution so I've written my own. Anyway, that's free and open-source...
I've seen in AutomatedQa support that they a recipe recommending using msaa and setting some properties on the controls. I do not know if it works.
If you are testing DataWindows (the class is pbdwxxx, e.g. pbdw110) you will have to use a combination of clicking at specific coordinates and sending Tab keys to get to the control you want. Of course you can also send up and down arrow keys to move among rows. The easiest thing to do is to start with a normal control like an SLE and tab into the DataWindow. The problem is that the DataWindow is essentially just an image. There is no control for a given field until you move the focus there by clicking or tabbing. I've also found that the DataWindow's iAccessible interface is a bit strange. If you ask the DataWindow for the object with focus, you don't get the right answer. If you enumerate through all of the children you can find the one that has focus. If you can modify the source I also advise that you set AccessibleName for your DataWindow controls, otherwise you probably won't be able to identify the controls except by position (by DataWindow controls I mean the ones inside the DataWindow, not the DataWindow itself). If it's an MDI application, you may also find it useful to locate the MicroHelp window (class fnhelpxxx, e.g. fnhelp110, find from the main application window) to help determine your current context.
Edited to add:
Sikuli looks very promising for testing PowerBuilder. It works by recognizing objects on the screen from a saved fragment of screenshot. That is, you take a screenshot of the part of the screen you want it to find.

Categories