沃梦达 / IT编程 / 前端开发 / 正文

python实现测试工具(二)——简单的ui测试工具

当我们需要测试一个应用程序的 UI 时,我们需要手工点击每个 UI 元素,并提供相应的输入,观察应用程序的反应并验证应用程序是否正确。

当我们需要测试一个应用程序的 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_positiondoes_element_existget_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.pngpassword_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测试工具