Iterative Debugging of AI‑Generated Test Cases and Scripts (Part 4)
The article outlines a lightweight AI‑agent workflow that iteratively refines Python‑based Playwright/pytest test scripts by combining human review with AI‑generated suggestions, shows the exact system and user prompts, and provides a complete runnable example with database setup, request handling, and a failing test case to illustrate the debugging loop.
The author extends the series on using an intelligent agent to generate test cases and scripts by introducing a simple online debugging flow. The workflow consists of a start node and a single AI node named "Optimize Test Script" that repeatedly receives the current script and error information, then returns an improved version.
System and User Prompts
System Prompt: "You are a senior software test development engineer proficient in Python, Playwright and pytest. Your core responsibility is to optimize the test script based on ${sys.query}."
User Prompt: "You are a senior software test development engineer proficient in Python, Playwright and pytest. Your core responsibility is to optimize the test script based on ${sys.query}."
During execution, the user must describe the test script and any error messages clearly; by iterating this exchange, the script is gradually improved.
Full Example Test Script
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__)
# Database configuration (keep encoding consistent with backend)
DB_CONFIG = {
'host': 'localhost',
'user': 'root',
'password': '123456',
'database': 'chatgptebusiness',
'charset': 'utf8'
}
# API endpoints
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):
"""Initialize class‑level resources: DB connection and HTTP session"""
cls.db = pymysql.connect(**DB_CONFIG)
cls.session = requests.Session()
logger.info("Class-level setup completed")
@classmethod
def tearDownClass(cls):
"""Clean up class‑level resources"""
cls.db.close()
cls.session.close()
logger.info("Class-level teardown completed")
def setUp(self):
"""Before each test: clear tables and obtain initial 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):
"""After each test: ensure a clean environment"""
logger.info("Test teardown completed: %s", self._testMethodName)
def _clear_tables(self):
"""Empty relevant DB tables"""
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):
"""Extract CSRF token from the page"""
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):
"""Compute password hash using the backend's algorithm"""
return hashlib.sha256(password.encode('utf-8')).hexdigest()
def _post_vericode(self, contact):
"""Send verification request for phone/email"""
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):
"""Submit new password (backend expects plaintext)"""
self.csrf_token = self._get_csrf_token(RECOVER_URL)
data = {
"csrftoken": self.csrf_token,
"identifyingCode": identifying_code,
"newPassword": new_password, # send plaintext
"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):
"""Parse error message from HTML 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:
return ""
@parameterized.expand([
("有效手机号", "13800138000", True, "成功"),
("有效邮箱", "[email protected]", True, "成功"),
])
def test_verify_contact(self, test_name, contact, is_success, expected_msg):
"""Test verification endpoint (001 series)"""
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):
"""Test password‑reset endpoint (002 series)"""
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)}")
response = self._post_resetcode(code, new_password, confirm_password)
self.assertEqual(response.status_code, 200)
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)The author notes that AI‑generated scripts rarely work perfectly on the first try; therefore the human must run the script, capture the failure details, feed them back to the agent via the prompts, and let the agent propose corrections. This loop continues until the test passes.
Running the provided test reveals a hash mismatch failure: the expected SHA‑256 of the new password is
7f91e8a4b648b0125b15dc5a3b6466f9f4906d92c72bea9bd6be92c853bebda2, but the database stores
04e45016090b3ae8bac292e00f912ca04d2f93b0b0a51f5b22ccf40c7123df1a. The author uses this example to demonstrate how the debugging workflow surfaces such discrepancies, prompting the agent to adjust the hashing logic or the test data preparation.
Two diagrams (included as images) illustrate the overall flow and the position of the AI node within the debugging pipeline.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Woodpecker Software Testing
The Woodpecker Software Testing public account shares software testing knowledge, connects testing enthusiasts, founded by Gu Xiang, website: www.3testing.com. Author of five books, including "Mastering JMeter Through Case Studies".
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
