介面自動化測試用例是一個老生常談的問題,在未引入人工智慧之前,也有非常多的生成方案,比如如下所示,透過har生成介面自動化測試用例:
但是以上的生成方式依然是有一些弊端,比如 har 本身雖然能表述一定的介面資訊和業務資訊,但是畢竟無法用來表述全部的應用場景與用例場景。而大部分的應用場景和用例場景,均是透過自然語言進行描述的。而解析自然語言,則是大語言模型擅長做的事情。
實踐演練
需求說明
以下內容為3條介面測試用例:
測試模組 | 測試標題 | 測試步驟 | 預期結果 |
---|---|---|---|
介面功能 | 正常情況下的請求 | 傳送一個正常的GET請求 | 響應狀態碼為 200 ,並返回請求者的IP地址 |
介面功能 | 非法請求方法 | 傳送一個非GET請求,如POST或者PUT | 響應狀態碼為 405 |
介面功能 | 無效的請求路徑 | 傳送一個不存在的路徑 | 響應狀態碼為404 |
以下為一個獲取ip介面的har檔案:
- 介面Har檔案(需要可留言領取)
實現原理
接下來,將透過這兩個資料檔案自動生成對應的測試用例。
透過功能用例生成測試指令碼
在這個過程中,測試用例本身是自然語言,自然語言的解析與處理本身就是大模型非常擅長的工作。而可以透過 LangChain 簡化整個的實現的過程。
編寫的提示詞模版資訊如下所示:
template = """
你是一個自動化測試工程師,精通的技術棧為 Python pytest requests庫
以下是這個介面的具體資訊,
{context}
Question: {input}"""
透過功能測試用例生成的自動化測試指令碼如下所示:
#1. Test case: 正常情況下的請求
import pytest
import requests
def test_normal_request():
url = 'http://example.com/normal_request'
response = requests.get(url)
assert response.status_code == 200
assert response.json()['ip_address'] == 'requester_ip'
#2. Test case: 非法請求方法
import pytest
import requests
def test_invalid_request_method():
url = 'http://example.com/invalid_request_method'
response = requests.post(url)
assert response.status_code == 405
# 3. Test case: 無效的請求路徑
import pytest
import requests
def test_invalid_request_path():
url = 'http://example.com/invalid_request_path'
response = requests.get(url)
assert response.status_code == 404
當然,在此過程中可以很明顯的發現,自動生成的用例是沒有任何的介面資訊的。原因是我們給到的資料裡面就是沒有介面資訊的。
填充介面資料
接下來,將讀取har檔案中的介面資料資訊,和指令碼進行結合。
提示詞模版如下:
template = """
你是一個自動化測試工程師,你非常熟悉requests庫
{context}
Question:
請根據傳入的介面資訊提取request中的 ip 、 url 、method、json。
key值為前面提到的欄位,如果沒有則無需新增。如果有則提取對應的value。
要求返回的格式為json格式
"""
生成結果如下:
{
"ip": "182.92.156.22",
"url": "https://httpbin.ceshiren.com/ip",
"method": "GET"
}
完整程式碼
再將以上的過程結合之後,完整版的程式碼如下所示
from langchain_community.chat_models.openai import ChatOpenAI
from langchain_community.document_loaders.text import TextLoader
from langchain_core.output_parsers import JsonOutputParser, StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough
from utils.langchain_debug import langchain_debug
langchain_debug()
llm = ChatOpenAI()
def get_by_filename(filename):
info = TextLoader(f'./data/{filename}')
return info.load()
def get_case_data(_):
template = """
你是一個自動化測試工程師,你非常熟悉requests庫
{context}
Question: {input}
請根據傳入的介面資訊提取request中的 ip 、 url 、method、json。
key值為前面提到的欄位,如果沒有則無需新增。如果有則提取對應的value。
要求返回的格式為json格式
"""
prompt = PromptTemplate.from_template(template=template, )
data_chain = (
RunnablePassthrough.assign(context=lambda x: get_by_filename("ip.har"), )
| prompt
| llm
| JsonOutputParser()
)
return data_chain
def get_case():
"""
透過大模型生成測試資料。
:return:
"""
template = """
你是一個自動化測試工程師,精通的技術棧為 Python pytest requests庫
以下是這個介面的具體資訊,你的
{context}
請求的引數資訊將輸入一個字典,輸入的內容為
{req}
Question: {input}"""
# 模板提示,輸出 json 格式的回答
prompt = PromptTemplate.from_template(
template=template, )
chain = (
RunnablePassthrough.
assign(context=lambda x: get_by_filename("獲取ip測試用例.md"),
req=get_case_data)
| prompt
| llm
| StrOutputParser()
)
input_template = """
根據每條測試用例的測試步驟,生成對應的測試資料資訊,
每條測試用例要求都有一條對應的單獨的pytest函式
"""
print(chain.invoke({"input": input_template}))
if __name__ == '__main__':
get_case()
總結
- 掌握介面自動化測試用例生成的原理。
- 瞭解如何透過大語言模型生成介面自動化測試指令碼與資料。
- 掌握透過LangChain生成完整版介面自動化測試用例的方法。