在传统编写 App 自动化测试用例的过程中,基本都是需要测试工程师,根据功能测试用例转换为自动化测试的用例。市面上自动生成 Web 或 App 自动化测试用例的产品无非也都是通过录制的方式,获取操作人的行为操作,从而记录测试用例。整个过程类似于
但是通常录制出来的用例可用性、可维护性都不强,而且依然需要人手工介入录制的过程。
在 LLM 问世之后,我们便在探索,是否有第二种可能性,由大模型执行功能测试用例,生成自动化测试用例?
在前面的章节 基于 LangChain 手工测试用例转 Web 自动化测试生成工具中,给大家讲解了手工用例转 Web 自动化测试用例的过程,而 App 自动化测试用例生成的原理也基本类似。
应用价值
测试工程师在编写用例的过程中,将操作步骤明确的表达出来。即可通过大模型将功能测试用例可以直接转为 App 自动化测试用例。极大的节省了人力与资源。
实践演练
实现原理
整个实现原理如下图所示:
实现思路
测试用例规范与要求
如果想要将功能用例转换为自动化测试用例,那么对功能测试用例则需要清晰,明确的表达出来每个操作步骤。如果测试用例本身就表达的含糊不清,那么自然大模型是无法识别它需要进行的具体的操作步骤的。
如下所示,为一个测试步骤。在这些测试步骤中,具体打开哪些页面,输入哪些信息,点击哪些按钮都清晰的表达了出来。
1. 打开 app activity ".Settings" , app package com.android.settings2. 点击 Battery3. 获取 Battery 的电量4. 返回上一级页面
通过 AGENT 执行功能测试用例。
大模型本身是不具备任何执行能力或生成能力的,它只会”思考“,但是通过 LangChain 的 Agent,可以将一些”工具”外挂到大模型身上。
那么如果要执行这些功能测试用例,大模型就需要具备执行用例的能力。而我们要做的事情,就是将 tools(工具包),外挂到大模型上面。
相关知识点:Agent、 tools
- 封装好 App 的底层工具
from time import sleepfrom appium import webdriverfrom appium.options.android import UiAutomator2Optionsfrom 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()
@tooldef init(app_activity, app_package): """ 打开app的安装包,并返回app的resource """ return app.init(app_activity, app_package)
@tooldef find(xpath: str): """通过xpath定位元素""" return app.find(xpath)
@tooldef click(xpath: str = None): """以xpath的方式定位网页元素后点击""" app.find(xpath) return app.click()
@tooldef send_keys(xpath, text): """定位到xpath指定的元素,并输入text""" app.find(xpath) return app.send_keys(text)
@tooldef sleep(seconds: int): """等待指定的秒数""" time.sleep(seconds)
@tooldef back(): """ 返回上一级界面 :return: """ app.back()
tools = [init, find, click, send_keys, sleep, back]
记录执行步骤
在 Agent 的配置中,可以要求 agent 将所有的执行步骤记录下来。而执行记录会记录在返回结果中的intermediate_steps
中。
而我们则需要将这些步骤取出来,按照我们的需求记录下来。
# 获取执行结果import jsonfrom langchain import hubfrom langchain.agents import create_structured_chat_agent, AgentExecutorfrom langchain_core.agents import AgentActionfrom 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 toolsapp_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.settings2. 点击 Battery3. 获取 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 自动化测试用例生成工具。