基於LangChain手工測試用例轉App自動化測試生成工具

霍格沃兹测试开发学社發表於2024-09-19

在傳統編寫 App 自動化測試用例的過程中,基本都是需要測試工程師,根據功能測試用例轉換為自動化測試的用例。市面上自動生成 Web 或 App 自動化測試用例的產品無非也都是透過錄制的方式,獲取操作人的行為操作,從而記錄測試用例。整個過程類似於

但是通常錄製出來的用例可用性、可維護性都不強,而且依然需要人手工介入錄製的過程。

在 LLM 問世之後,我們便在探索,是否有第二種可能性,由大模型執行功能測試用例,生成自動化測試用例?

在前面的章節 基於 LangChain 手工測試用例轉 Web 自動化測試生成工具中,給大家講解了手工用例轉 Web 自動化測試用例的過程,而 App 自動化測試用例生成的原理也基本類似。

應用價值

測試工程師在編寫用例的過程中,將操作步驟明確的表達出來。即可透過大模型將功能測試用例可以直接轉為 App 自動化測試用例。極大的節省了人力與資源。

實踐演練

實現原理

整個實現原理如下圖所示:

實現思路

測試用例規範與要求

如果想要將功能用例轉換為自動化測試用例,那麼對功能測試用例則需要清晰,明確的表達出來每個操作步驟。如果測試用例本身就表達的含糊不清,那麼自然大模型是無法識別它需要進行的具體的操作步驟的。

如下所示,為一個測試步驟。在這些測試步驟中,具體開啟哪些頁面,輸入哪些資訊,點選哪些按鈕都清晰的表達了出來。

開啟  app activity ".Settings" , app package com.android.settings
2. 點選 Battery
3. 獲取 Battery 的電量
4. 返回上一級頁面
透過 AGENT 執行功能測試用例。

大模型本身是不具備任何執行能力或生成能力的,它只會”思考“,但是透過 LangChain 的 Agent,可以將一些”工具”外掛到大模型身上。

那麼如果要執行這些功能測試用例,大模型就需要具備執行用例的能力。而我們要做的事情,就是將 tools(工具包),外掛到大模型上面。

相關知識點:Agent、 tools

  • 封裝好 App 的底層工具

from time import sleep
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy

class AppAutoFramework:
    def __init__(self):
        self.driver = None
        self.element = None

    def init(self, app_activity, app_package):
        if not self.driver:
            # 設定 capability
            caps = {
                # 設定 app 安裝的平臺(Android、iOS)
                "platformName": "android",
                # 設定 appium 驅動
                "appium:automationName": "uiautomator2",
                # 設定裝置名稱
                "appium:deviceName": "emulator-5554",
                "appium:noReset": True,
                # 設定以下兩個引數來控制啟動app和關閉掉app
                "appium:forceAppLaunch" : True,
                "appium:shouldTerminateApp" : True,
                # 設定 app 的包名
            "appium:appPackage": app_package,
                # 設定 app 啟動頁
            "appium:appActivity": app_activity
            }
            # 初始化 driver
            self.driver = webdriver.Remote(
                "http://localhost:4723",
                options=UiAutomator2Options().load_capabilities(caps)
            )
            self.driver.implicitly_wait(5)
        return self.source()

    def source(self):
        return self.driver.page_source

    def find(self, locator):
        print(f"find xpath = {locator}")
        element = self.driver.find_element(by=AppiumBy.XPATH, value=locator)
        self.element = element
        return self.source()

    def click(self):
        self.element.click()
        sleep(1)
        return self.source()

    def send_keys(self, text):
        self.element.clear()
        self.element.send_keys(text)
        return self.source()

    def back(self):
        self.driver.back()
        return self.source()

  • 建立工具以及其說明,並且將工具繫結到工具包中

import time

from langchain_core.tools import tool

app = AppAutoFramework()


@tool
def init(app_activity, app_package):
    """
    開啟app的安裝包,並返回app的resource
    """
    return app.init(app_activity, app_package)


@tool
def find(xpath: str):
    """透過xpath定位元素"""
    return app.find(xpath)


@tool
def click(xpath: str = None):
    """以xpath的方式定位網頁元素後點選"""
    app.find(xpath)
    return app.click()


@tool
def send_keys(xpath, text):
    """定位到xpath指定的元素,並輸入text"""
    app.find(xpath)
    return app.send_keys(text)


@tool
def sleep(seconds: int):
    """等待指定的秒數"""
    time.sleep(seconds)


@tool
def back():
    """
    返回上一級介面
    :return:
    """
    app.back()


tools = [init, find, click, send_keys, sleep, back]
記錄執行步驟

在 Agent 的配置中,可以要求 agent 將所有的執行步驟記錄下來。而執行記錄會記錄在返回結果中的intermediate_steps中。

而我們則需要將這些步驟取出來,按照我們的需求記錄下來。


# 獲取執行結果
import json
from langchain import hub
from langchain.agents import create_structured_chat_agent, AgentExecutor
from langchain_core.agents import AgentAction
from langchain_openai import ChatOpenAI

from app.appium_tools import tools

prompt = hub.pull("hwchase17/structured-chat-agent")
llm = ChatOpenAI()
app_agent = create_structured_chat_agent(llm, tools, prompt)
# Create an agent executor by passing in the agent and tools
app_agent_executor = AgentExecutor(
    agent=app_agent, tools=tools,
    verbose=True,
    return_intermediate_steps=True,
    handle_parsing_errors=True)

query = """
你是一個自動化測試工程師,接下來需要根據測試步驟,
每一步如果定位都是根據上一步的返回的html操作完成
執行對應的測試用例,測試步驟如下
1. 開啟  app activity ".Settings" , app package com.android.settings
2. 點選 Battery
3. 獲取 Battery 的電量
4. 返回上一級頁面
"""

def execute_result(_):
    # 獲取執行結果
    r = app_agent_executor.invoke({"input": query})
    # 獲取執行記錄
    steps = r["intermediate_steps"]
    steps_info = []
    # 遍歷執行步驟,獲取每一步的執行步驟以及輸入的資訊。
    for step in steps:
        action = step[0]
        if isinstance(action, AgentAction):
            steps_info.append({'tool': action.tool, 'input': action.tool_input})
    return json.dumps(steps_info)


if __name__ == '__main__':
    print(execute_result(""))
生成自動化測試用例。

擁有執行步驟之後,可以將執行步驟傳遞給大模型,然後讓大模型根據執行步驟直接生成 web 自動化測試用例。


prompt_testcase = PromptTemplate.from_template("""
你是一個app自動化測試工程師,主要應用的技術棧為pytest + appium。
以下為app自動化測試的測試步驟,測試步驟由json結構體描述

{step}

{input}

""")

chain = (
        RunnablePassthrough.
        assign(step=execute_result)
        | prompt_testcase
        | llm
        | StrOutputParser()
)

print(chain.invoke({"input": "請根據以上的資訊,給出對應的app自動化測試的程式碼"}))

執行效果

最後,自動生成的 App 自動化測試用例效果如下:

總結

  1. App 自動化測試用例生成工具需求說明。
  2. 如何透過 LangChain 實現 App 自動化測試用例生成工具。

相關文章