mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Refactor: Tests: Move utilities to common module
* Some functions were copied between tests, now import a common module for these. * Merge _test_vars and _test_window into a single function, and use the window index instead of excluding windows. * Rename idle_until to not be a hack, and explain that it can be used for testing operator jobs while keeping the disclaimer that it should not typically be used. Pull Request: https://projects.blender.org/blender/blender/pulls/153159
This commit is contained in:
parent
20ce68c534
commit
27b2b9646f
6 changed files with 268 additions and 367 deletions
129
tests/python/ui_simulate/modules/ui_test_utils.py
Normal file
129
tests/python/ui_simulate/modules/ui_test_utils.py
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
# SPDX-FileCopyrightText: 2019-2026 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
__all__ = (
|
||||
"call_menu",
|
||||
"call_operator",
|
||||
"get_area_center",
|
||||
"get_area_center_from_spacetype",
|
||||
"get_window_area_by_type",
|
||||
"get_window_size_in_pixels",
|
||||
"idle_until",
|
||||
"keep_open",
|
||||
"test_window",
|
||||
)
|
||||
|
||||
|
||||
def test_window(window_index=0):
|
||||
"""
|
||||
Get window with associated event simulator and tests.
|
||||
"""
|
||||
import unittest
|
||||
from .easy_keys import EventGenerate
|
||||
import bpy
|
||||
|
||||
window = bpy.data.window_managers[0].windows[window_index]
|
||||
|
||||
return (
|
||||
EventGenerate(window),
|
||||
unittest.TestCase(),
|
||||
window,
|
||||
)
|
||||
|
||||
|
||||
def call_operator(e, text: str):
|
||||
"""
|
||||
Call operator by name.
|
||||
"""
|
||||
yield e.f3()
|
||||
yield e.text(text)
|
||||
yield e.ret()
|
||||
|
||||
|
||||
def call_menu(e, text: str):
|
||||
"""
|
||||
Call operator through menu.
|
||||
"""
|
||||
yield e.f3()
|
||||
yield e.text_unicode(text.replace(" -> ", " \u25b8 "))
|
||||
yield e.ret()
|
||||
|
||||
|
||||
def get_window_area_by_type(window, space_type):
|
||||
"""
|
||||
Get first area of the specified space type in a window.
|
||||
"""
|
||||
for area in window.screen.areas:
|
||||
if area.type == space_type:
|
||||
return area
|
||||
|
||||
|
||||
def get_area_center(area):
|
||||
"""
|
||||
Get coordinate in the center of an area, e.g. for placing the cursor.
|
||||
"""
|
||||
return (
|
||||
area.x + area.width // 2,
|
||||
area.y + area.height // 2,
|
||||
)
|
||||
|
||||
|
||||
def get_area_center_from_spacetype(window, space_type):
|
||||
"""
|
||||
Get coordinate in the center of the first area with the given spacetype.
|
||||
"""
|
||||
area = get_window_area_by_type(window, space_type)
|
||||
if area is None:
|
||||
raise Exception("Space Type {!r} not found".format(space_type))
|
||||
return get_area_center(area)
|
||||
|
||||
|
||||
def get_window_size_in_pixels(window):
|
||||
"""
|
||||
Get window size that can be used for positioning a cursor.
|
||||
"""
|
||||
import sys
|
||||
size = window.width, window.height
|
||||
# macOS window size is a multiple of the pixel_size.
|
||||
if sys.platform == "darwin":
|
||||
from bpy import context
|
||||
# The value is always rounded to an int, so converting to an int is safe here.
|
||||
pixel_size = int(context.preferences.system.pixel_size)
|
||||
size = size[0] * pixel_size, size[1] * pixel_size
|
||||
return size
|
||||
|
||||
|
||||
def idle_until(until, idle=1 / 60, timeout=1.0):
|
||||
"""
|
||||
Idle while the internal event loop runs until a specified condition is true.
|
||||
|
||||
This should be used sparingly as it may represent some other failure
|
||||
condition inside Blender. Currently, it is used to:
|
||||
- Test completion and cancellation of operators that use jobs.
|
||||
- Multi window undo tests that need separate view layer (see #148903).
|
||||
|
||||
Note: In practice, the timeout value of 1.0 seconds should be more than enough
|
||||
for all cases. In testing with a fixed, constant delay, the tests succeeded
|
||||
with a timeout of 1/6th of a second.
|
||||
:param until: lambda to check the condition of after each sleep
|
||||
:param idle: how long to idle between checks of the `until` lambda.
|
||||
Defaults to 60Hz due to common refresh rates.
|
||||
:param timeout: the max time in seconds that this busy wait will execute.
|
||||
:return:
|
||||
"""
|
||||
import datetime
|
||||
import time
|
||||
start_time = time.time()
|
||||
current_time = time.time()
|
||||
while current_time - start_time < timeout and not until():
|
||||
yield datetime.timedelta(seconds=idle)
|
||||
current_time = time.time()
|
||||
|
||||
|
||||
def keep_open():
|
||||
"""
|
||||
Only for development, handy so we can quickly keep the window open while testing.
|
||||
"""
|
||||
import bpy
|
||||
bpy.app.use_event_simulate = False
|
||||
Loading…
Add table
Add a link
Reference in a new issue