杰瑞科技汇

Python如何用uiautomation实现UI自动化测试?

Of course! uiautomation is a powerful and popular Python library for automating the Windows Graphical User Interface (GUI). It's essentially a wrapper around the UI Automation API provided by Windows, making it accessible and easy to use for Python developers.

Python如何用uiautomation实现UI自动化测试?-图1
(图片来源网络,侵删)

Here's a comprehensive guide covering everything you need to know to get started with uiautomation.


What is uiautomation?

uiautomation is a Python module that allows you to programmatically interact with Windows applications. You can use it to:

  • Find UI elements: Buttons, text boxes, menus, list items, etc.
  • Get information from UI elements: Text content, properties, and states (e.g., is a button enabled?).
  • Interact with UI elements: Click buttons, type text into fields, select items from lists, and more.
  • Control windows: Move, resize, minimize, maximize, and close application windows.
  • Automate repetitive tasks: Automate data entry, software testing, or any other GUI-based workflow.

A key feature of uiautomation is that it uses UIA (UI Automation), the modern accessibility framework in Windows. This makes it more reliable for newer applications (like those built with WPF, UWP, or WinForms) compared to older libraries that rely on older APIs like Win32 or SendKeys.


Installation

First, you need to install the library. It's available on PyPI.

Python如何用uiautomation实现UI自动化测试?-图2
(图片来源网络,侵删)
pip install uiautomation

Core Concepts

To use uiautomation, you need to understand three main concepts:

  1. Element: Any item on the screen, from the entire desktop window down to a single pixel. Elements have a tree-like structure (parent-child relationships).
  2. Control Type: The type of an element (e.g., Button, Edit, Text, List, MenuItem). This is the most common way to find elements.
  3. Properties: Attributes of an element, such as its Name, AutomationId, or ControlType. You can use these properties to uniquely identify an element.

How to Find UI Elements

This is the most critical part of GUI automation. uiautomation offers several methods to find elements, ranging from simple to more specific.

The Desktop (Desktop)

All UI elements are descendants of the desktop window. You start your search from here.

import uiautomation as auto
# Get the desktop element
desktop = auto.Desktop()
print(f"Desktop Name: {desktop.Name}")

Finding by Control Type (Most Common)

You can search for elements by their type (e.g., Button, Text, Edit) using methods like ButtonControl(), TextControl(), EditControl(), etc.

Python如何用uiautomation实现UI自动化测试?-图3
(图片来源网络,侵删)

These methods search within a given element's children.

Example: Find all buttons on the desktop

import uiautomation as auto
desktop = auto.Desktop()
# Find all Button controls under the desktop
buttons = desktop.ButtonControl()
# The method returns the first match. To get all, you need to use a loop or a more advanced search.
# Let's find a button with a specific name.
ok_button = desktop.ButtonControl(SubName="OK") # SubName is a partial match on the element's Name
if ok_button:
    print(f"Found 'OK' button: {ok_button.Name}")

Finding by Search Properties (More Precise)

For more control, you can use the generic FindAll() or FindFirst() methods, which allow you to specify a dictionary of properties to match.

  • ControlType: The type of control.
  • Name: The name of the control.
  • AutomationId: A stable identifier for the control (very useful!).
  • ClassName: The underlying Windows class name.

Example: Find a specific text box

Let's say we want to find the search bar in the Windows Calculator.

import uiautomation as auto
import time
# Open Calculator (you might need to do this manually or with another script)
# For this example, let's assume it's already open.
desktop = auto.Desktop()
# Find the Calculator window first
# We search for a window with the name "Calculator"
calculator_window = desktop.WindowControl(Name="Calculator")
if not calculator_window.Exists(3): # Check if it exists for 3 seconds
    print("Calculator window not found. Please open it.")
    exit()
# Now, find the text display inside the calculator window
# It's a TextControl with AutomationId "CalculatorResults"
display_text = calculator_window.TextControl(AutomationId="CalculatorResults")
if display_text:
    print(f"Found display: '{display_text.Name}' with text: '{display_text.GetWindowText()}'")
else:
    print("Could not find the calculator display.")

Advanced Search: Tree Walker

For complex UI structures, TreeWalker gives you fine-grained control to traverse the element tree manually. This is useful when other methods fail.

import uiautomation as auto
desktop = auto.Desktop()
walker = auto.TreeWalker(auto.ConditionControlType(auto.ControlType.Window))
# Get the first child of the desktop (which is a window)
first_window = walker.GetNextSibling(desktop)
if first_window:
    print(f"First window found: {first_window.Name}")

Common UI Actions and Information

Once you have a UI element, you can perform various actions and get information from it.

Method/Property Description Example
Click() Simulates a mouse click. ok_button.Click()
SendKeys(keys) Sends keyboard input to an element (e.g., a text box). edit_box.SendKeys("Hello World")
GetWindowText() Gets the text content of an element. print(text_box.GetWindowText())
Name Gets the Name property of the element. print(button.Name)
Enabled Checks if the element is enabled. if button.Enabled: ...
Exists(timeout) Checks if the element still exists on the screen. Can wait for a timeout. if my_button.Exists(5): ... (wait up to 5 seconds)
SetFocus() Sets the keyboard focus to the element. edit_box.SetFocus()
GetBoundingRectangle() Gets the screen coordinates (x, y, width, height) of the element. rect = my_button.GetBoundingRectangle()

Complete Example: Automating Notepad

Let's put it all together in a practical example. We will:

  1. Open Notepad.
  2. Type a sentence.
  3. Save the file with a specific name.
  4. Close Notepad.

Note: To open Notepad, you can use os.system or subprocess, but this is OS-dependent. For a pure uiautomation script, you would need to open it manually before running the script.

import uiautomation as auto
import time
import os
# --- Configuration ---
APP_NAME = "Untitled - Notepad"
SAVE_BUTTON_NAME = "Save"
FILE_NAME_EDIT_ID = "File name:"
SAVE_DIALOG_NAME = "Save As"
def main():
    # 1. Find the Notepad window
    print("Looking for Notepad window...")
    notepad_window = auto.Desktop().WindowControl(Name=APP_NAME)
    if not notepad_window.Exists(3):
        print(f"Error: Could not find '{APP_NAME}' window. Please open Notepad.")
        return
    print(f"Found Notepad window: {notepad_window.Name}")
    # 2. Type text into the editor
    # The main text area in Notepad is an Edit control.
    # We can find it by its ControlType and its position relative to the window.
    edit_control = notepad_window.EditControl()
    if not edit_control.Exists():
        print("Error: Could not find the text area in Notepad.")
        return
    print("Typing text into Notepad...")
    edit_control.SetFocus()
    edit_control.SendKeys("Hello from uiautomation! This is a test.")
    time.sleep(1) # Pause to see the typing
    # 3. Save the file
    print("Saving the file...")
    # Use the hotkey Alt + F to open the File menu
    auto.SendKeys('{ALT}f')
    time.sleep(0.5)
    # Find the 'Save' menu item and click it
    # We search within the menu popup, which is a Menu control
    save_menu_item = auto.MenuControl().MenuItemControl(Name=SAVE_BUTTON_NAME)
    if save_menu_item.Exists():
        save_menu_item.Click()
    else:
        print("Error: Could not find the 'Save' menu item.")
        return
    time.sleep(1) # Wait for the "Save As" dialog to appear
    # 4. Handle the "Save As" dialog
    print("Handling 'Save As' dialog...")
    save_dialog = auto.Desktop().WindowControl(Name=SAVE_DIALOG_NAME)
    if not save_dialog.Exists():
        print("Error: 'Save As' dialog did not appear.")
        return
    # Find the file name edit box and type the name
    file_name_edit = save_dialog.EditControl(AutomationId=FILE_NAME_EDIT_ID)
    if file_name_edit.Exists():
        file_name_edit.SetFocus()
        file_name_edit.SendKeys("my_test_file.txt{ENTER}") # Type name and press Enter
        print("File saved as 'my_test_file.txt'")
    else:
        print("Error: Could not find the file name edit box in the 'Save As' dialog.")
    # 5. Close Notepad
    print("Closing Notepad...")
    notepad_window.Close()
    # Handle the "Do you want to save?" dialog that might appear
    time.sleep(1)
    save_dialog = auto.Desktop().WindowControl(Name="Notepad")
    if save_dialog.Exists():
        save_dialog.ButtonControl(SubName="Don't Save").Click()
if __name__ == "__main__":
    main()

Tips and Best Practices

  1. Use AutomationId whenever possible: It's the most stable way to find elements, as it doesn't change with localization (unlike Name) or minor UI updates.
  2. Be Patient: GUI operations are not instantaneous. Always add small time.sleep() delays or use the Exists(timeout) method to wait for elements to appear or become ready.
  3. Use SubName for Partial Matches: If an element's full name is dynamic (e.g., "Untitled - Notepad"), use SubName="Notepad" to find it.
  4. Inspect UI Elements: The best way to find the right ControlType, Name, or AutomationId is to use a tool. Inspect.exe is a free tool from Microsoft that comes with the Windows SDK. It allows you to point at any UI element and see all its properties.
  5. Start Broad, Then Narrow: First, find the main window. Then, search for elements within that window. This makes your scripts more robust.
  6. Handle Errors: Always check if an element was found using if element.Exists() before trying to interact with it. This prevents your script from crashing.
分享:
扫描分享到社交APP
上一篇
下一篇