在傳統編寫 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 自動化測試用例效果如下:
總結
- App 自動化測試用例生成工具需求說明。
- 如何透過 LangChain 實現 App 自動化測試用例生成工具。