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

霍格沃兹测试学院發表於2024-08-29

在傳統編寫 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 自動化測試用例效果如下:

總結

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

相關文章