正如智能体生成测试用例和脚本方法(一)描述
注意:有智能体生成的测试用例不可能一次正确,我们需要通过人工的方式+智能体辅助的方式进行调试。在通过智能体生成用例和测试脚本的方法(四)。我会进行详细介绍。
我们可以简单建立一个智能体流程来对生成的测试脚本进行联机调试

在这个流程中,除了开始节点,就一个智能节点:优化测试脚本
系统提示词
你是一位资深的软件测试开发工程师,精通Python、Playwright和pytest框架。你的核心职责是根据${sys.query},优化测试脚本。
用户提示词
你是一位资深的软件测试开发工程师,精通Python、Playwright和pytest框架。你的核心职责是根据${sys.query},优化测试脚本。
在运行的时候描述清楚测试脚本和报错信息,通过不断迭代,就可以不断优化脚本。

比如
测试脚本
import unittest
import requests
import hashlib
import re
import pymysql
from parameterized import parameterized
from bs4 import BeautifulSoup
import logging
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# 数据库配置 (保持与后端一致的编码)
DB_CONFIG = {
'host': 'localhost',
'user': 'root',
'password': '123456',
'database': 'chatgptebusiness',
'charset': 'utf8'
}
# API接口配置
VERICODE_URL = "http://127.0.0.1:8080/ChatGPTEbusiness/jsp/VeriCodePage.jsp"
RECOVER_URL = "http://127.0.0.1:8080/ChatGPTEbusiness/jsp/RecoverPage.jsp"
class RecoverPasswordAPITest(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""初始化类级别资源:创建数据库连接和请求会话"""
cls.db = pymysql.connect(**DB_CONFIG)
cls.session = requests.Session()
logger.info("Class-level setup completed")
@classmethod
def tearDownClass(cls):
"""清理类级别资源:关闭数据库连接和会话"""
cls.db.close()
cls.session.close()
logger.info("Class-level teardown completed")
def setUp(self):
"""每条测试用例执行前:清空数据库表并获取初始CSRF Token"""
self._clear_tables()
self.csrf_token = self._get_csrf_token(VERICODE_URL)
logger.info("Test setup completed: %s", self._testMethodName)
def tearDown(self):
"""每条测试用例执行后:确保环境干净"""
logger.info("Test teardown completed: %s", self._testMethodName)
def _clear_tables(self):
"""清空数据库表,确保测试环境干净"""
try:
with self.db.cursor() as cursor:
cursor.execute("SET FOREIGN_KEY_CHECKS = 0")
cursor.execute("DELETE FROM user")
cursor.execute("DELETE FROM code")
cursor.execute("SET FOREIGN_KEY_CHECKS = 1")
self.db.commit()
logger.info("Database tables cleared")
except Exception as e:
self.fail(f"Database clear failed: {str(e)}")
def _get_csrf_token(self, url):
"""从页面获取CSRF Token"""
try:
response = self.session.get(url)
response.raise_for_status()
match = re.search(r'<input type="hidden" id="csrftoken" name="csrftoken" value="([^"]+)"', response.text)
return match.group(1) if match else None
except Exception as e:
logger.error("CSRF token retrieval failed: %s", str(e))
self.fail(f"Get CSRF token failed: {str(e)}")
def _hash_password(self, password):
"""计算密码哈希(使用后端相同的处理方式)"""
return hashlib.sha256(password.encode('utf-8')).hexdigest()
def _post_vericode(self, contact):
"""封装发送手机号/邮箱验证请求"""
data = {
"csrftoken": self.csrf_token,
"contact": contact
}
response = self.session.post(VERICODE_URL, data=data, cookies={"csrftoken": self.csrf_token})
response.raise_for_status()
return response
def _post_resetcode(self, identifying_code, new_password, confirm_password):
"""
1. 发送明文密码(后端会自行处理哈希)
2. 修正:后端要求明文,不进行任何哈希处理
"""
self.csrf_token = self._get_csrf_token(RECOVER_URL)
data = {
"csrftoken": self.csrf_token,
"identifyingCode": identifying_code,
"newPassword": new_password, # 直接发送明文
"confirmPassword": confirm_password
}
response = self.session.post(RECOVER_URL, data=data, cookies={"csrftoken": self.csrf_token})
response.raise_for_status()
return response
def _get_error_message(self, response):
"""从响应中提取错误提示信息"""
try:
soup = BeautifulSoup(response.text, 'html.parser')
error_div = soup.find('div', id='recoverError')
return error_div.get_text(strip=True) if error_div else ""
except Exception as e:
return ""
@parameterized.expand([
("有效手机号", "13800138000", True, "成功"),
("有效邮箱", "test@example.com", True, "成功"),
])
def test_verify_contact(self, test_name, contact, is_success, expected_msg):
"""测试手机号/邮箱验证接口(001系列)"""
if is_success:
try:
with self.db.cursor() as cursor:
# 插入测试用户(使用两次哈希存储,与后端一致)
old_password = "oldpass123"
first_hash = self._hash_password(old_password)
cursor.execute(
"INSERT INTO user (phone, password) VALUES (%s, %s)",
(contact,first_hash)
)
self.db.commit()
logger.info("Test user created: %s", contact)
except Exception as e:
self.fail(f"Failed to create test user: {str(e)}")
response = self._post_vericode(contact)
self.assertEqual(response.status_code, 200)
if is_success:
self.assertIn("找回密码", response.text)
else:
error_msg = self._get_error_message(response)
self.assertEqual(error_msg, expected_msg)
@parameterized.expand([
("正确验证码和密码", "13800138000", "123456", "Abc123", "Abc123", "成功"),
])
def test_reset_password(self, test_name, contact, code, new_password, confirm_password, expected_msg):
"""测试密码重置接口(002系列)"""
try:
with self.db.cursor() as cursor:
# 插入测试用户(使用两次哈希存储,与后端一致)
old_password = "oldpass123"
first_hash = self._hash_password(old_password)
cursor.execute(
"INSERT INTO user (phone, password) VALUES (%s, %s)",
(contact, first_hash)
)
user_id = cursor.lastrowid
self.db.commit()
# 插入验证码
cursor.execute(
"INSERT INTO code (uid, code) VALUES (%s, %s)",
(user_id, code)
)
self.db.commit()
logger.info("Test data created: user_id=%s, contact=%s", user_id, contact)
except Exception as e:
self.fail(f"Failed to create test data: {str(e)}")
# 1. 发送明文密码(后端会进行两次哈希处理)
response = self._post_resetcode(code, new_password, confirm_password)
self.assertEqual(response.status_code, 200)
# 2. 验证数据库更新(使用两次哈希验证)
if "成功" in expected_msg:
try:
with self.db.cursor() as cursor:
cursor.execute("SELECT password FROM user WHERE id = %s", (user_id,))
result = cursor.fetchone()
self.assertIsNotNone(result, "User record not updated")
# 重要:计算两次哈希(与后端一致)
first_hash = self._hash_password(new_password)
expected_hash = first_hash
logger.info("Calculated hash: %s (for password: '%s')", expected_hash, new_password)
logger.info("Database hash: %s", result[0])
self.assertEqual(
expected_hash,
result[0],
f"Password hash mismatch: expected '{expected_hash}', got '{result[0]}'"
)
except Exception as e:
self.fail(f"Database verification failed: {str(e)}")
else:
error_msg = self._get_error_message(response)
self.assertEqual(error_msg, expected_msg)
if __name__ == "__main__":
unittest.main(verbosity=2, failfast=True)
遇到问题
2026-04-09 13:30:41,189 - INFO - Class-level setup completed
test_reset_password_0__ (__main__.RecoverPasswordAPITest.test_reset_password_0__)
测试密码重置接口(002系列) [with test_name='正确验证码和密码', contact='13800138000', code='123456', new_password='Abc123', confirm_password='Abc123', expected_msg='成功'] ... 2026-04-09 13:30:41,269 - INFO - Database tables cleared
2026-04-09 13:30:41,516 - INFO - Test setup completed: test_reset_password_0__
2026-04-09 13:30:41,524 - INFO - Test data created: user_id=11, contact=13800138000
2026-04-09 13:30:41,549 - INFO - Calculated hash: 7f91e8a4b648b0125b15dc5a3b6466f9f4906d92c72bea9bd6be92c853bebda2 (for password: 'Abc123')
2026-04-09 13:30:41,553 - INFO - Database hash: 04e45016090b3ae8bac292e00f912ca04d2f93b0b0a51f5b22ccf40c7123df1a
FAIL
2026-04-09 13:30:41,561 - INFO - Test teardown completed: test_reset_password_0__
2026-04-09 13:30:41,564 - INFO - Class-level teardown completed
======================================================================
FAIL: test_reset_password_0__ (__main__.RecoverPasswordAPITest.test_reset_password_0__)
测试密码重置接口(002系列) [with test_name='正确验证码和密码', contact='13800138000', code='123456', new_password='Abc123', confirm_password='Abc123', expected_msg='成功']
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\xiang\Desktop\AI赋能软件测试实战\reset_API.py", line 191, in test_reset_password
self.assertEqual(
AssertionError: '7f91e8a4b648b0125b15dc5a3b6466f9f4906d92c72bea9bd6be92c853bebda2' != '04e45016090b3ae8bac292e00f912ca04d2f93b0b0a51f5b22ccf40c7123df1a'
- 7f91e8a4b648b0125b15dc5a3b6466f9f4906d92c72bea9bd6be92c853bebda2
+ 04e45016090b3ae8bac292e00f912ca04d2f93b0b0a51f5b22ccf40c7123df1a
: Password hash mismatch: expected '7f91e8a4b648b0125b15dc5a3b6466f9f4906d92c72bea9bd6be92c853bebda2', got '04e45016090b3ae8bac292e00f912ca04d2f93b0b0a51f5b22ccf40c7123df1a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\xiang\AppData\Local\Programs\Python\Python312\Lib\site-packages\parameterized\parameterized.py", line 620, in standalone_func
return func(*(a + p.args), **p.kwargs, **kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\xiang\Desktop\AI赋能软件测试实战\reset_API.py", line 197, in test_reset_password
self.fail(f"Database verification failed: {str(e)}")
AssertionError: Database verification failed: '7f91e8a4b648b0125b15dc5a3b6466f9f4906d92c72bea9bd6be92c853bebda2' != '04e45016090b3ae8bac292e00f912ca04d2f93b0b0a51f5b22ccf40c7123df1a'
- 7f91e8a4b648b0125b15dc5a3b6466f9f4906d92c72bea9bd6be92c853bebda2
+ 04e45016090b3ae8bac292e00f912ca04d2f93b0b0a51f5b22ccf40c7123df1a
: Password hash mismatch: expected '7f91e8a4b648b0125b15dc5a3b6466f9f4906d92c72bea9bd6be92c853bebda2', got '04e45016090b3ae8bac292e00f912ca04d2f93b0b0a51f5b22ccf40c7123df1a'
----------------------------------------------------------------------
Ran 1 test in 0.390s
FAILED (failures=1)