当我们需要测试一个应用程序的 UI 时,我们需要手工点击每个 UI 元素,并提供相应的输入,观察应用程序的反应并验证应用程序是否正确。
然而,人工测试非常耗费精力和时间,因此我们需要自动化 UI 测试,以便减轻测试工程师的负担。在这篇文章中,我们将学习如何使用 Python 实现一个基本的 UI 测试工具。
前置条件
在开始这个教程之前,我们需要确保以下软件已经安装在我们的计算机上:
- Python 2.7 或 Python 3.x
- PyAutoGUI:一个可以控制鼠标和键盘的 Python 库
- Pillow:一个可以操作图像文件的 Python 库
我们可以使用以下命令安装 PyAutoGUI 和 Pillow:
pip install pyautogui
pip install pillow
步骤 1:安装 PyAutoGUI 和 Pillow
如前所述,我们需要安装 PyAutoGUI 和 Pillow 来实现我们的 UI 测试工具。请在终端或命令提示符窗口中输入以下命令来安装这些库:
pip install pyautogui
pip install pillow
步骤 2:创建测试用例
在我们开始使用 UI 测试工具之前,我们需要先创建一组测试用例。测试用例应该包括测试的 UI 元素,例如输入框,按钮和标签,以及我们希望测试的预期行为。我们可以使用以下示例测试用例:
test_cases = [
{
"name": "Test login with valid credentials",
"steps": [
{
"action": "move_to",
"element": "username_input",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "type_text",
"value": "testuser"
},
{
"action": "move_to",
"element": "password_input",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "type_text",
"value": "testpassword"
},
{
"action": "move_to",
"element": "submit_button",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "wait_for_element_to_appear",
"element": "welcome_label",
"timeout": 10
},
{
"action": "verify_text",
"element": "welcome_label",
"expected_text": "Welcome, testuser!"
},
]
},
{
"name": "Test login with invalid credentials",
"steps": [
{
"action": "move_to",
"element": "username_input",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "type_text",
"value": "testuser"
},
{
"action": "move_to",
"element": "password_input",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "type_text",
"value": "incorrectpassword"
},
{
"action": "move_to",
"element": "submit_button",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "wait_for_element_to_appear",
"element": "error_message",
"timeout": 10
},
{
"action": "verify_text",
"element": "error_message",
"expected_text": "Incorrect password."
}
]
}
]
在这个示例中,我们创建了两个测试用例:一个使用有效凭据登录,另一个使用无效凭据登录。在每个测试用例中,我们添加了一组步骤,用于指定 UI 元素和执行操作,例如点击输入框,键入文本和点击按钮。我们还为每个测试用例添加了名称,以便更好地识别和管理测试用例。
步骤 3:创建 UI 测试工具类
现在我们已经准备好开始创建我们的 UI 测试工具了。我们将使用 Python 类来组织和封装我们的代码,并提高可读性和可重用性。以下是 UI 测试工具类的示例代码:
import time
import pyautogui
from PIL import ImageGrab
class UiTestTool:
def __init__(self, resolution=None):
if resolution is None:
resolution = pyautogui.size()
self.resolution = resolution
def run_test(self, test_case):
print("Running test: {}".format(test_case["name"]))
for step in test_case["steps"]:
action = step["action"]
if action == "move_to":
element = step["element"]
x_offset = step["x_offset"]
y_offset = step["y_offset"]
position = self.get_element_position(element)
pyautogui.moveTo(
position[0] + x_offset,
position[1] + y_offset
)
time.sleep(1)
elif action == "click":
pyautogui.click()
time.sleep(1)
elif action == "type_text":
value = step["value"]
pyautogui.typewrite(value)
time.sleep(1)
elif action == "wait_for_element_to_appear":
element = step["element"]
timeout = step["timeout"]
start_time = time.time()
while time.time() - start_time < timeout:
if self.does_element_exist(element):
return True
time.sleep(1)
return False
elif action == "verify_text":
element = step["element"]
expected_text = step["expected_text"]
actual_text = self.get_text_for_element(element)
if actual_text != expected_text:
return False
return True
def run_all_tests(self, test_cases):
for test_case in test_cases:
result = self.run_test(test_case)
print("Test case: {}. Result: {}".format(
test_case["name"],
"Passed" if result else "Failed"
))
def get_element_position(self, element):
image = ImageGrab.grab()
image.save("test.png")
with open("test.txt", "w") as f:
f.write(pytesseract.image_to_string(image))
# TODO: Implement element detection using OpenCV
return (0, 0)
def does_element_exist(self, element):
# TODO: Implement element detection using OpenCV
return True
def get_text_for_element(self, element):
# TODO: Implement text detection using OpenCV
return ""
在这里,我们创建了一个名为 UiTestTool
的类,用于执行 UI 测试用例。我们构造函数接受一个可选参数 resolution
,用于指定屏幕的分辨率。如果没有传入分辨率,则默认使用电脑屏幕的分辨率。在 run_test
方法中,我们遍历测试用例中的每个步骤,并根据步骤指定的操作来执行操作。目前,我们支持以下操作:
move_to
:将鼠标移动到指定的 UI 元素上。click
:单击当前鼠标位置。type_text
:使用键盘输入指定的文本。wait_for_element_to_appear
:等待 UI 元素出现,如果超时则返回 False。verify_text
:检查 UI 元素中的文本是否与预期相同。
在需要调用输入文本时,我们使用 PyAutoGUI 的 typewrite
函数模拟人手输入的文本,以便我们可以键入用户名和密码。我们使用 sleep
函数添加一秒钟的延迟,以便 UI 可以加载并响应我们的操作。
我们还实现了三个辅助方法:get_element_position
,does_element_exist
和 get_text_for_element
。目前,这些方法仍然是空的,因此它们需要实现。
步骤 4:实现辅助方法
我们现在需要实现三个辅助方法,以使我们的 UI 测试工具能够识别 UI 元素和执行复杂的操作。
get_element_position
该方法用于找到 UI 元素在屏幕上的位置。我们可以使用 PyAutoGUI 的 screenshot
函数捕捉整个屏幕的屏幕截图,并使用 Pillow 的 ImageGrab
模块保存图像。我们可以使用 OpenCV 的模板匹配技术来找到 UI 元素在屏幕截图中的位置。
def get_element_position(self, element):
image = pyautogui.screenshot()
image.save("screenshot.png")
template = cv2.imread(element, 0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(image,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(res >= threshold)
if len(loc[0]) == 0 or len(loc[1]) == 0:
return (0, 0)
x = int(loc[1][0] + w/2)
y = int(loc[0][0] + h/2)
return (x, y)
在上面的代码中,我们首先使用 PyAutoGUI 的 screenshot
函数捕捉屏幕截图,并使用 Pillow 的 ImageGrab
模块保存屏幕截图。然后,我们使用 OpenCV 的 imread
函数加载 UI 元素的图像文件,并使用 matchTemplate
函数在屏幕截图中找到元素的位置。我们使用 where
函数查找元素匹配的像素坐标,并计算目标元素的位置。
does_element_exist
该方法用于检查 UI 元素是否存在。我们可以使用 get_element_position
方法找到元素的位置,并检查是否返回了有效的坐标。
def does_element_exist(self, element):
position = self.get_element_position(element)
return position[0] + position[1] > 0
get_text_for_element
该方法用于检索 UI 元素中的文本。我们需要首先使用 PyAutoGUI 的 screenshot
函数捕捉整个屏幕截图,并使用 Pillow 的 ImageGrab
模块保存屏幕截图。我们可以使用 OpenCV 的模板匹配技术来定位元素的位置,并使用 Pytesseract 模块识别屏幕截图中的文本。
def get_text_for_element(self, element):
position = self.get_element_position(element)
if position[0] + position[1] == 0:
return ""
x = position[0]
y = position[1]
w = 100
h = 100
image = ImageGrab.grab(bbox=(x, y, x+w, y+h))
image.save("element.png")
text = pytesseract.image_to_string(image)
return text.strip()
在上面的代码中,我们首先使用 get_element_position
方法找到 UI 元素在屏幕上的位置。如果 UI 元素不存在,则返回空字符串。否则,我们使用 ImageGrab
模块捕捉相应区域的屏幕截图,并将其保存为 image.png 文件。然后,我们使用 Pytesseract 模块对图像进行 OCR,并将识别出的文本返回。
步骤 5:运行测试用例
我们已经创建了测试用例,添加了测试代码,并实现了辅助方法,现在我们可以运行我们的测试用例了。我们可以使用以下代码运行测试:
test_tool = UiTestTool()
test_tool.run_all_tests(test_cases)
示例说明
这里提供两个示例说明:
示例 1
假设我们正在测试一个基于 Web 的应用程序,我们需要测试登录功能。我们将创建以下两个测试用例:
test_cases = [
{
"name": "Test login with valid credentials",
"steps": [
{
"action": "move_to",
"element": "username_input.png",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "type_text",
"value": "testuser"
},
{
"action": "move_to",
"element": "password_input.png",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "type_text",
"value": "testpassword"
},
{
"action": "move_to",
"element": "submit_button.png",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "wait_for_element_to_appear",
"element": "welcome_label.png",
"timeout": 10
},
{
"action": "verify_text",
"element": "welcome_label.png",
"expected_text": "Welcome, testuser!"
}
]
},
{
"name": "Test login with invalid credentials",
"steps": [
{
"action": "move_to",
"element": "username_input.png",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "type_text",
"value": "testuser"
},
{
"action": "move_to",
"element": "password_input.png",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "type_text",
"value": "incorrectpassword"
},
{
"action": "move_to",
"element": "submit_button.png",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "wait_for_element_to_appear",
"element": "error_message.png",
"timeout": 10
},
{
"action": "verify_text",
"element": "error_message.png",
"expected_text": "Incorrect password."
}
]
}
]
test_tool = UiTestTool()
test_tool.run_all_tests(test_cases)
在这个示例中,我们测试的 Web 应用程序包括一个登录表单,其中包含用户名和密码输入框以及登录按钮。我们使用图像文件(例如 username_input.png
和 password_input.png
)来识别 UI 元素。
在第一个测试用例中,我们使用有效凭据登录,期望应用程序返回欢迎消息并显示用户名。在第二个测试用例中,我们使用无效凭据登录,期望应用程序返回错误消息。
示例 2
假设我们正在测试一个桌面应用程序,我们需要测试创建新文件功能。我们将创建以下测试用例:
test_cases = [
{
"name": "Test creating a new file",
"steps": [
{
"action": "move_to",
"element": "file_menu.png",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "move_to",
"element": "new_file_menu_item.png",
"x_offset": 10,
"y_offset": 10
},
{
"action": "click"
},
{
"action": "wait_for_element_to_appear",
"element": "untitled_file_name.png",
"timeout": 10
}
]
}
]
test_tool = UiTestTool()
test_tool.run_all_tests(test_cases)
在这个示例中,我们测试的桌面应用程序包含一个 “文件” 菜单,其中包含一个 “新建” 菜单项。我们使用图像文件(例如
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python实现测试工具(二)——简单的ui测试工具 - Python技术站