Performance testing reports require a significant number of screenshots to document results. Automating this process saves time and ensures consistency. This tool utilizes the pyautogui library to control mouse and keyboard actions, locating interface buttons through pre-captured reference images. To ensure accurate image recognition, the library's native screenshot function must be used, as third-party tools may capture images in formats that the library cannot process correctly.
import pyautogui as auto_gui
# Capture a specific region of the screen (x, y, width, height)
auto_gui.screenshot('reference_button.png', region=(0, 0, 100, 50))
Window Management and Focus
Before capturing screenshots or interacting with the interface, the tool must switch to the JMeter window. The pygetwindow library is used to manage windows. The following function searches for a window title containing a specific keyword, activates it, and optionally maximizes it.
import pygetwindow as window_manager
def bring_window_to_front(title_keyword, maximize=True):
"""Activates the window matching the title keyword."""
all_titles = window_manager.getAllTitles()
target_title = next((t for t in all_titles if title_keyword.lower() in t.lower()), None)
if target_title:
window_obj = window_manager.getWindowsWithTitle(target_title)[0]
window_obj.activate()
if maximize:
window_obj.maximize()
return True
return False
Capturing Reference Images for Automation
The initialization phase involves capturing reference images of common buttons, such as the 'Clear All' button. This ensures that previous report data does not interfere with new captures. The user defines the screen coordinates through a UI, and the tool saves the image and updates a JSON configuration file.
import json
import os
import time
CONFIG_PATH = 'jmeter_config.json'
def capture_reference_image(self, button_name, coordinates):
if not bring_window_to_front("Apache JMeter"):
raise Exception("JMeter window not found.")
time.sleep(1) # Allow window transition
x, y, w, h = coordinates
image_path = f'refs/{button_name}.png'
auto_gui.screenshot(image_path, region=(x, y, w, h))
if os.path.exists(image_path):
entry = {button_name: image_path}
if os.path.exists(CONFIG_PATH):
with open(CONFIG_PATH, 'r') as f:
data = json.load(f)
else:
data = {'init': {}}
data['init'].update(entry)
with open(CONFIG_PATH, 'w') as f:
json.dump(data, f)
bring_window_to_front("Configuration Tool")
Verification of Image Recognition
After adding listeners, the tool verifies that the captured reference images can be located on the screen. The locateCenterOnScreen function attempts to find the image, and a retry mechanism handles potential latency. The confidence parameter allows for slight visual variations, while grayscale can speed up the search.
def find_and_click_target(image_path, max_retries=2):
attempts = 0
while attempts < max_retries:
try:
# Search for the image on screen
position = auto_gui.locateCenterOnScreen(
image_path,
confidence=0.9,
grayscale=True
)
if position:
auto_gui.moveTo(position, duration=0.3)
auto_gui.click()
return position
except auto_gui.ImageNotFoundException:
attempts += 1
time.sleep(0.5)
except Exception as e:
print(f"Error locating image: {e}")
break
return False
The testing workflow iterates through the configured buttons and listener items. For each item, it attempts to locate and click the associated reference image. If an image is missing or cannot be found after the retry limit, the operation is logged for review.
def run_visual_validation(self):
selected_items = self.get_selected_listeners()
if not selected_items:
self.log("No listeners selected.")
return
if not bring_window_to_front("Apache JMeter"):
self.log("JMeter window not detected.")
return
auto_gui.click(100, 600) # Focus safe area
auto_gui.press('home') # Scroll to top
with open(CONFIG_PATH, 'r') as f:
config = json.load(f)
# Test initialization button
init_image = config.get('init', {}).get('clear_all')
if init_image:
find_and_click_target(init_image)
# Test listener buttons
for listener in selected_items:
listener_config = config.get(listener, {})
for i in range(1, 4):
target = listener_config.get(f'tu{i}')
if target:
success = find_and_click_target(target)
if not success:
self.log(f"Failed to locate image {i} for {listener}")
bring_window_to_front("Report Tool")