在傳統編寫 Web 自動化測試用例的過程中,基本都是需要測試工程師,根據功能測試用例轉換為自動化測試的用例。市面上自動生成 Web 或 App 自動化測試用例的產品無非也都是透過錄制的方式,獲取操作人的行為操作,從而記錄測試用例。整個過程類似於
但是通常錄製出來的用例可用性、可維護性都不強,而且依然需要人手工介入錄製的過程。
在 LLM 問世之後,我們便在探索,是否有第二種可能性,由大模型執行功能測試用例,生成自動化測試用例?
應用價值
測試工程師在編寫用例的過程中,將操作步驟明確的表達出來。即可透過大模型將功能測試用例可以直接轉為 Web 自動化測試用例。極大的節省了人力與資源。
實踐演練
實現原理
整個實現原理如下圖所示:
實現思路
測試用例規範與要求
如果想要將功能用例轉換為自動化測試用例,那麼對功能測試用例則需要清晰,明確的表達出來每個操作步驟。如果測試用例本身就表達的含糊不清,那麼自然大模型是無法識別它需要進行的具體的操作步驟的。
如下所示,為一個登入功能的測試步驟。在這些測試步驟中,具體開啟哪些頁面,輸入哪些資訊,點選哪些按鈕都清晰的表達了出來。
1. 開啟 https://litemall.hogwarts.ceshiren.com/#/login?redirect=%2Fdashboard
2. 輸入使用者名稱 hogwarts
3. 輸入密碼 test12345
4. 點選登入按鈕
5. 進入主頁,獲取此時的url
6. 執行完成,退出瀏覽器
透過 AGENT 執行功能測試用例。
大模型本身是不具備任何執行能力或生成能力的,它只會”思考“,但是透過 LangChain 的 Agent,可以將一些”工具”外掛到大模型身上。
那麼如果要執行這些功能測試用例,大模型就需要具備執行用例的能力。而我們要做的事情,就是將 tools(工具包),外掛到大模型上面。
相關知識點: Agent、 tools
- 封裝好 web 的底層工具
class WebAutoFramework:
def __init__(self):
self.driver = None
self.element = None
def init(self):
if not self.driver:
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(5)
def open(self, url):
self.init()
self.driver.get(url)
return self.source()
def source(self):
return self.driver.execute_script(
"""
var content="";
document.querySelectorAll('button').forEach(x=> content+=x.outerHTML);
document.querySelectorAll('input').forEach(x=> content+=x.outerHTML);
//document.querySelectorAll('table').forEach(x=> content+=x.outerHTML);
return content;
"""
)
def click(self):
"""
點選當前的元素
:return:
"""
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 find(self, locator):
print(f"find css = {locator}")
element = self.driver.find_element(by=By.CSS_SELECTOR, value=locator)
self.element = element
return self.source()
def quit(self):
self.driver.quit()
def get_current_url(self):
print(f"當前的url為{self.driver.current_url}")
return self.driver.current_url
- 建立工具以及其說明,並且將工具繫結到工具包中
web = WebAutoFramework()
@tool
def open(url: str):
"""
使用瀏覽器開啟特定的url,並返回網頁內容
"""
r = web.open(url)
return r
@tool
def find(css: str):
"""定位網頁元素"""
return web.find(css)
@tool
def click(css: str = None):
"""以css的方式定位網頁元素後點選"""
web.find(css)
return web.click()
@tool
def send_keys(css, text):
"""定位到css指定的元素,並輸入text"""
web.find(css)
return web.send_keys(text)
@tool
def sleep(seconds: int):
"""等待指定的秒數"""
time.sleep(seconds)
@tool
def quit():
"""退出瀏覽器"""
web.quit()
@tool
def get_current_url():
"""獲取當前的url"""
return web.get_current_url()
tools = [open, quit, get_current_url, find, click, send_keys]
宣告 Agent,並將tools傳遞過去:
web_agent = create_structured_chat_agent(llm, tools, prompt)
# Create an agent executor by passing in the agent and tools
web_agent_executor = AgentExecutor(
agent=web_agent, tools=tools,
verbose=True,
return_intermediate_steps=True,
handle_parsing_errors=True)
執行 Agent:
r = web_agent_executor.invoke({"input": query})
記錄執行步驟
在 Agent 的配置中,可以要求 agent 將所有的執行步驟記錄下來。而執行記錄會記錄在返回結果中的intermediate_steps
中。
而我們則需要將這些步驟取出來,按照我們的需求記錄下來。
# 獲取執行結果
r = agent.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})
生成自動化測試用例。
擁有執行步驟之後,可以將執行步驟傳遞給大模型,然後讓大模型根據執行步驟直接生成 web 自動化測試用例。
prompt = PromptTemplate.from_template("""
你是一個web自動化測試工程師,主要應用的技術棧為pytest + selenium。
以下為web自動化測試的測試步驟,測試步驟由json結構體描述
{step}
{input}
""")
AGENT 結合 CHAIN
import json
from langchain import hub
from langchain.agents import create_structured_chat_agent, AgentExecutor
from langchain.globals import set_debug
from langchain_core.agents import AgentAction
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
from web.selenium_tools import tools
set_debug(True)
prompt = hub.pull("hwchase17/structured-chat-agent")
llm = ChatOpenAI()
web_agent = create_structured_chat_agent(llm, tools, prompt)
# Create an agent executor by passing in the agent and tools
web_agent_executor = AgentExecutor(
agent=web_agent, tools=tools,
verbose=True,
return_intermediate_steps=True,
handle_parsing_errors=True)
query = """
你是一個自動化測試工程師,接下來需要根據測試步驟,
每一步如果定位都是根據上一步的返回的html操作完成
執行對應的測試用例,測試步驟如下
1. 開啟 https://litemall.hogwarts.ceshiren.com/#/login?redirect=%2Fdashboard
2. 輸入使用者名稱 hogwarts
3. 輸入密碼 test12345
4. 點選登入按鈕
5. 進入主頁,獲取此時的url
6. 執行完成,退出瀏覽器
"""
def web_execute_result(_):
# 獲取執行結果
r = web_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)
prompt_testcase = PromptTemplate.from_template("""
你是一個web自動化測試工程師,主要應用的技術棧為pytest + selenium。
以下為web自動化測試的測試步驟,測試步驟由json結構體描述
{step}
{input}
""")
chain = (
RunnablePassthrough.
assign(step=web_execute_result)
| prompt_testcase
| llm
| StrOutputParser()
)
print(chain.invoke({"input": "請根據以上的資訊,給出對應的web自動化測試的程式碼"}))
執行效果
最後,自動生成的 Web 自動化測試用例效果如下:
總結
- Web 自動化測試用例生成工具需求說明。
- 如何透過 LangChain 實現 Web 自動化測試用例生成工具。