Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -50,103 +50,173 @@ def call_openai_chat(messages, model="gpt-4o-mini", max_tokens=3000):
|
|
| 50 |
return f"OpenAI API Error: {str(e)}"
|
| 51 |
|
| 52 |
def parse_test_cases_to_dataframe(text_response):
|
| 53 |
-
"""
|
| 54 |
try:
|
| 55 |
test_cases = []
|
| 56 |
|
| 57 |
-
#
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
precondition_pattern = r'(?:Precondition|Pre-condition|Prerequisites?)\s*:?\s*([^\n]+)'
|
| 61 |
-
steps_pattern = r'(?:Test Steps?|Steps|Procedure)\s*:?\s*((?:[^\n]*\n?)*?)(?=Expected|Priority|Test Case|$)'
|
| 62 |
-
expected_pattern = r'(?:Expected Result|Expected|Result)\s*:?\s*([^\n]+)'
|
| 63 |
-
priority_pattern = r'(?:Priority|Severity)\s*:?\s*([^\n]+)'
|
| 64 |
-
test_data_pattern = r'(?:Test Data|Data)\s*:?\s*([^\n]+)'
|
| 65 |
|
| 66 |
-
# Split
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
for i, block in enumerate(blocks):
|
| 70 |
-
if len(block.strip()) <
|
| 71 |
continue
|
| 72 |
|
|
|
|
| 73 |
test_case = {}
|
| 74 |
|
| 75 |
-
#
|
| 76 |
-
|
| 77 |
-
test_case['Test_Case_ID'] = id_match.group(1).strip() if id_match else f"TC_{len(test_cases)+1:03d}"
|
| 78 |
|
| 79 |
-
|
| 80 |
-
test_case['
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
|
| 83 |
-
|
|
|
|
| 84 |
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
-
|
| 92 |
-
|
|
|
|
| 93 |
|
| 94 |
-
|
| 95 |
-
test_case['
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
|
|
|
| 97 |
test_case['Created_Date'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 98 |
test_case['Status'] = "New"
|
| 99 |
|
| 100 |
test_cases.append(test_case)
|
| 101 |
|
| 102 |
-
#
|
| 103 |
if not test_cases:
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
'Test_Steps': "",
|
| 116 |
-
'Expected_Results': "",
|
| 117 |
-
'Priority': "Medium",
|
| 118 |
-
'Test_Data': "N/A",
|
| 119 |
-
'Created_Date': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 120 |
-
'Status': "New"
|
| 121 |
-
}
|
| 122 |
-
elif current_case:
|
| 123 |
-
if not current_case.get('Test_Steps'):
|
| 124 |
-
current_case['Test_Steps'] = line
|
| 125 |
-
elif not current_case.get('Expected_Results'):
|
| 126 |
-
current_case['Expected_Results'] = line
|
| 127 |
-
|
| 128 |
-
if current_case:
|
| 129 |
-
test_cases.append(current_case)
|
| 130 |
|
| 131 |
-
return pd.DataFrame(test_cases)
|
| 132 |
-
'Test_Case_ID': ['TC_001'],
|
| 133 |
-
'Title': ['Sample Test Case'],
|
| 134 |
-
'Preconditions': ['N/A'],
|
| 135 |
-
'Test_Steps': ['Parse failed - manual review needed'],
|
| 136 |
-
'Expected_Results': ['Manual review needed'],
|
| 137 |
-
'Priority': ['Medium'],
|
| 138 |
-
'Test_Data': ['N/A'],
|
| 139 |
-
'Created_Date': [datetime.now().strftime("%Y-%m-%d %H:%M:%S")],
|
| 140 |
-
'Status': ['New']
|
| 141 |
-
})
|
| 142 |
|
| 143 |
except Exception as e:
|
|
|
|
| 144 |
return pd.DataFrame({
|
| 145 |
'Test_Case_ID': ['TC_001'],
|
| 146 |
'Title': ['Parsing Error'],
|
| 147 |
'Preconditions': ['N/A'],
|
| 148 |
-
'Test_Steps': [f'Error: {str(e)}'],
|
| 149 |
-
'Expected_Results': ['Manual review
|
| 150 |
'Priority': ['High'],
|
| 151 |
'Test_Data': ['N/A'],
|
| 152 |
'Created_Date': [datetime.now().strftime("%Y-%m-%d %H:%M:%S")],
|
|
@@ -251,75 +321,84 @@ def generate_test_cases_from_text(requirements, test_types, priority_level):
|
|
| 251 |
"""Enhanced test case generation with more specific prompts"""
|
| 252 |
|
| 253 |
enhanced_prompt = f"""
|
| 254 |
-
As an expert QA engineer, create comprehensive and detailed test cases for the following requirements
|
| 255 |
-
|
| 256 |
REQUIREMENTS:
|
| 257 |
{requirements}
|
| 258 |
-
|
| 259 |
INSTRUCTIONS:
|
| 260 |
- Generate {test_types} test scenarios
|
| 261 |
- Focus on {priority_level} priority tests
|
| 262 |
-
-
|
| 263 |
-
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
Preconditions: [What must be true before testing]
|
| 271 |
Test Steps:
|
| 272 |
-
1.
|
| 273 |
-
2.
|
| 274 |
-
3.
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
"""
|
| 281 |
|
| 282 |
messages = [{"role": "user", "content": enhanced_prompt}]
|
| 283 |
response = call_openai_chat(messages, max_tokens=4000)
|
| 284 |
|
| 285 |
if "Error:" in response:
|
| 286 |
-
return response, None
|
| 287 |
|
| 288 |
df = parse_test_cases_to_dataframe(response)
|
| 289 |
csv_path = create_download_csv(df, "generated_test_cases")
|
| 290 |
|
| 291 |
-
return response, csv_path
|
| 292 |
|
| 293 |
def generate_test_cases_from_image(image, test_focus):
|
| 294 |
"""Enhanced image-based test case generation"""
|
| 295 |
|
|
|
|
|
|
|
|
|
|
| 296 |
base64_image = encode_image(image)
|
| 297 |
|
| 298 |
enhanced_prompt = f"""
|
| 299 |
-
As an expert QA engineer, analyze this
|
| 300 |
-
|
| 301 |
FOCUS AREA: {test_focus}
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
- Include accessibility and responsive design considerations
|
| 308 |
-
- Cover both happy path and error scenarios
|
| 309 |
-
|
| 310 |
-
FORMAT EACH TEST CASE AS:
|
| 311 |
-
Test Case ID: TC_XXX
|
| 312 |
-
Test Case Title: [Clear, descriptive title]
|
| 313 |
Preconditions: [Setup requirements]
|
| 314 |
Test Steps:
|
| 315 |
-
1. [
|
| 316 |
-
2. [
|
| 317 |
-
3. [
|
| 318 |
-
Expected Results: [Expected
|
| 319 |
-
Priority: [High/Medium/Low
|
| 320 |
-
Test Data: [Required
|
| 321 |
-
|
| 322 |
-
Generate
|
| 323 |
"""
|
| 324 |
|
| 325 |
messages = [
|
|
@@ -335,12 +414,12 @@ def generate_test_cases_from_image(image, test_focus):
|
|
| 335 |
response = call_openai_chat(messages, model="gpt-4o-mini", max_tokens=4000)
|
| 336 |
|
| 337 |
if "Error:" in response:
|
| 338 |
-
return response, None
|
| 339 |
|
| 340 |
df = parse_test_cases_to_dataframe(response)
|
| 341 |
csv_path = create_download_csv(df, "image_based_test_cases")
|
| 342 |
|
| 343 |
-
return response, csv_path
|
| 344 |
|
| 345 |
def optimize_test_cases(existing_cases, focus_areas, optimization_goal):
|
| 346 |
"""Enhanced test case optimization"""
|
|
@@ -676,15 +755,25 @@ def create_gradio_interface():
|
|
| 676 |
with gr.Column():
|
| 677 |
test_cases_output = gr.Textbox(
|
| 678 |
label="Generated Test Cases",
|
| 679 |
-
lines=
|
| 680 |
-
max_lines=
|
| 681 |
)
|
| 682 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 683 |
|
| 684 |
generate_btn.click(
|
| 685 |
fn=generate_test_cases_from_text,
|
| 686 |
inputs=[requirements_input, test_types, priority_level],
|
| 687 |
-
outputs=[test_cases_output, csv_download]
|
| 688 |
)
|
| 689 |
|
| 690 |
with gr.TabItem("Image Requirements"):
|
|
@@ -704,15 +793,25 @@ def create_gradio_interface():
|
|
| 704 |
with gr.Column():
|
| 705 |
img_test_cases_output = gr.Textbox(
|
| 706 |
label="Generated Test Cases",
|
| 707 |
-
lines=
|
| 708 |
-
max_lines=
|
| 709 |
)
|
| 710 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 711 |
|
| 712 |
generate_img_btn.click(
|
| 713 |
fn=generate_test_cases_from_image,
|
| 714 |
inputs=[image_input, test_focus],
|
| 715 |
-
outputs=[img_test_cases_output, img_csv_download]
|
| 716 |
)
|
| 717 |
|
| 718 |
# Test Case Optimization Tab
|
|
|
|
| 50 |
return f"OpenAI API Error: {str(e)}"
|
| 51 |
|
| 52 |
def parse_test_cases_to_dataframe(text_response):
|
| 53 |
+
"""Improved parsing that handles various response formats"""
|
| 54 |
try:
|
| 55 |
test_cases = []
|
| 56 |
|
| 57 |
+
# First, try to split by common delimiters
|
| 58 |
+
# Look for patterns like "Test Case", "TC", numbers followed by periods, etc.
|
| 59 |
+
potential_blocks = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
|
| 61 |
+
# Split by various patterns that might indicate new test cases
|
| 62 |
+
split_patterns = [
|
| 63 |
+
r'\n(?=Test Case[:\s#]*\d+)',
|
| 64 |
+
r'\n(?=TC[:\s#]*\d+)',
|
| 65 |
+
r'\n(?=\d+\.?\s*Test)',
|
| 66 |
+
r'\n(?=#{1,3}\s*Test)',
|
| 67 |
+
r'\n(?=\*\*Test Case)',
|
| 68 |
+
r'\n(?=## Test Case)',
|
| 69 |
+
]
|
| 70 |
|
| 71 |
+
blocks = [text_response] # Start with the whole text
|
| 72 |
+
|
| 73 |
+
for pattern in split_patterns:
|
| 74 |
+
new_blocks = []
|
| 75 |
+
for block in blocks:
|
| 76 |
+
new_blocks.extend(re.split(pattern, block, flags=re.IGNORECASE | re.MULTILINE))
|
| 77 |
+
blocks = [b for b in new_blocks if len(b.strip()) > 20]
|
| 78 |
+
if len(blocks) > 1: # If we found a good split, use it
|
| 79 |
+
break
|
| 80 |
+
|
| 81 |
+
# If we still have only one block, try a more aggressive split
|
| 82 |
+
if len(blocks) <= 1:
|
| 83 |
+
lines = text_response.split('\n')
|
| 84 |
+
current_block = []
|
| 85 |
+
blocks = []
|
| 86 |
+
|
| 87 |
+
for line in lines:
|
| 88 |
+
line = line.strip()
|
| 89 |
+
if not line:
|
| 90 |
+
continue
|
| 91 |
+
|
| 92 |
+
# Check if this line starts a new test case
|
| 93 |
+
if (re.match(r'(test case|tc)\s*[:#]?\s*\d+', line.lower()) or
|
| 94 |
+
re.match(r'\d+\.?\s*(test|scenario)', line.lower()) or
|
| 95 |
+
re.match(r'#{1,3}\s*test', line.lower()) or
|
| 96 |
+
'**Test Case' in line):
|
| 97 |
+
|
| 98 |
+
if current_block:
|
| 99 |
+
blocks.append('\n'.join(current_block))
|
| 100 |
+
current_block = []
|
| 101 |
+
current_block.append(line)
|
| 102 |
+
else:
|
| 103 |
+
current_block.append(line)
|
| 104 |
+
|
| 105 |
+
if current_block:
|
| 106 |
+
blocks.append('\n'.join(current_block))
|
| 107 |
+
|
| 108 |
+
# Parse each block
|
| 109 |
for i, block in enumerate(blocks):
|
| 110 |
+
if len(block.strip()) < 20:
|
| 111 |
continue
|
| 112 |
|
| 113 |
+
# Extract information using multiple strategies
|
| 114 |
test_case = {}
|
| 115 |
|
| 116 |
+
# Strategy 1: Look for labeled fields
|
| 117 |
+
lines = [line.strip() for line in block.split('\n') if line.strip()]
|
|
|
|
| 118 |
|
| 119 |
+
# Initialize with defaults
|
| 120 |
+
test_case['Test_Case_ID'] = f"TC_{len(test_cases)+1:03d}"
|
| 121 |
+
test_case['Title'] = f"Test Case {len(test_cases)+1}"
|
| 122 |
+
test_case['Preconditions'] = "N/A"
|
| 123 |
+
test_case['Test_Steps'] = ""
|
| 124 |
+
test_case['Expected_Results'] = ""
|
| 125 |
+
test_case['Priority'] = "Medium"
|
| 126 |
+
test_case['Test_Data'] = "N/A"
|
| 127 |
|
| 128 |
+
# Parse line by line for labeled content
|
| 129 |
+
current_field = None
|
| 130 |
+
steps_lines = []
|
| 131 |
|
| 132 |
+
for line in lines:
|
| 133 |
+
line_lower = line.lower()
|
| 134 |
+
|
| 135 |
+
# Check for field labels
|
| 136 |
+
if any(label in line_lower for label in ['test case id', 'tc id', 'id:']):
|
| 137 |
+
test_case['Test_Case_ID'] = re.sub(r'.*?[:\-]\s*', '', line).strip()
|
| 138 |
+
current_field = None
|
| 139 |
+
|
| 140 |
+
elif any(label in line_lower for label in ['title:', 'test case title', 'name:']):
|
| 141 |
+
test_case['Title'] = re.sub(r'.*?[:\-]\s*', '', line).strip()
|
| 142 |
+
current_field = None
|
| 143 |
+
|
| 144 |
+
elif any(label in line_lower for label in ['precondition', 'prerequisite']):
|
| 145 |
+
test_case['Preconditions'] = re.sub(r'.*?[:\-]\s*', '', line).strip()
|
| 146 |
+
current_field = None
|
| 147 |
+
|
| 148 |
+
elif any(label in line_lower for label in ['test step', 'steps:', 'procedure']):
|
| 149 |
+
current_field = 'steps'
|
| 150 |
+
step_content = re.sub(r'.*?[:\-]\s*', '', line).strip()
|
| 151 |
+
if step_content:
|
| 152 |
+
steps_lines.append(step_content)
|
| 153 |
+
|
| 154 |
+
elif any(label in line_lower for label in ['expected result', 'expected:', 'result:']):
|
| 155 |
+
test_case['Expected_Results'] = re.sub(r'.*?[:\-]\s*', '', line).strip()
|
| 156 |
+
current_field = None
|
| 157 |
+
|
| 158 |
+
elif any(label in line_lower for label in ['priority:', 'severity:']):
|
| 159 |
+
test_case['Priority'] = re.sub(r'.*?[:\-]\s*', '', line).strip()
|
| 160 |
+
current_field = None
|
| 161 |
+
|
| 162 |
+
elif any(label in line_lower for label in ['test data:', 'data:']):
|
| 163 |
+
test_case['Test_Data'] = re.sub(r'.*?[:\-]\s*', '', line).strip()
|
| 164 |
+
current_field = None
|
| 165 |
+
|
| 166 |
+
else:
|
| 167 |
+
# If we're in the middle of collecting steps, add this line
|
| 168 |
+
if current_field == 'steps':
|
| 169 |
+
steps_lines.append(line)
|
| 170 |
+
elif not any(test_case.values()): # If nothing has been set yet, this might be the title
|
| 171 |
+
if len(line) > 5 and not line.startswith(('β’', '-', '*', '1.', '2.')):
|
| 172 |
+
test_case['Title'] = line[:100]
|
| 173 |
|
| 174 |
+
# Combine steps
|
| 175 |
+
if steps_lines:
|
| 176 |
+
test_case['Test_Steps'] = '\n'.join(steps_lines)
|
| 177 |
|
| 178 |
+
# Fallback: if we couldn't parse properly, use the first few lines
|
| 179 |
+
if (test_case['Title'] == f"Test Case {len(test_cases)+1}" and
|
| 180 |
+
test_case['Test_Steps'] == "" and
|
| 181 |
+
test_case['Expected_Results'] == ""):
|
| 182 |
+
|
| 183 |
+
if len(lines) > 0:
|
| 184 |
+
test_case['Title'] = lines[0][:100]
|
| 185 |
+
if len(lines) > 1:
|
| 186 |
+
test_case['Test_Steps'] = '\n'.join(lines[1:min(len(lines), 4)])
|
| 187 |
+
if len(lines) > 4:
|
| 188 |
+
test_case['Expected_Results'] = lines[-1][:200]
|
| 189 |
|
| 190 |
+
# Add metadata
|
| 191 |
test_case['Created_Date'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 192 |
test_case['Status'] = "New"
|
| 193 |
|
| 194 |
test_cases.append(test_case)
|
| 195 |
|
| 196 |
+
# Final fallback - create from raw text
|
| 197 |
if not test_cases:
|
| 198 |
+
test_cases.append({
|
| 199 |
+
'Test_Case_ID': 'TC_001',
|
| 200 |
+
'Title': 'Generated Test Case',
|
| 201 |
+
'Preconditions': 'N/A',
|
| 202 |
+
'Test_Steps': text_response[:500] + "..." if len(text_response) > 500 else text_response,
|
| 203 |
+
'Expected_Results': 'Review generated content',
|
| 204 |
+
'Priority': 'Medium',
|
| 205 |
+
'Test_Data': 'N/A',
|
| 206 |
+
'Created_Date': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 207 |
+
'Status': 'Needs Review'
|
| 208 |
+
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
|
| 210 |
+
return pd.DataFrame(test_cases)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
|
| 212 |
except Exception as e:
|
| 213 |
+
# Error fallback
|
| 214 |
return pd.DataFrame({
|
| 215 |
'Test_Case_ID': ['TC_001'],
|
| 216 |
'Title': ['Parsing Error'],
|
| 217 |
'Preconditions': ['N/A'],
|
| 218 |
+
'Test_Steps': [f'Error parsing response: {str(e)}\n\nOriginal text: {text_response[:300]}...'],
|
| 219 |
+
'Expected_Results': ['Manual review required'],
|
| 220 |
'Priority': ['High'],
|
| 221 |
'Test_Data': ['N/A'],
|
| 222 |
'Created_Date': [datetime.now().strftime("%Y-%m-%d %H:%M:%S")],
|
|
|
|
| 321 |
"""Enhanced test case generation with more specific prompts"""
|
| 322 |
|
| 323 |
enhanced_prompt = f"""
|
| 324 |
+
As an expert QA engineer, create comprehensive and detailed test cases for the following requirements.
|
| 325 |
+
|
| 326 |
REQUIREMENTS:
|
| 327 |
{requirements}
|
| 328 |
+
|
| 329 |
INSTRUCTIONS:
|
| 330 |
- Generate {test_types} test scenarios
|
| 331 |
- Focus on {priority_level} priority tests
|
| 332 |
+
- Use EXACTLY this format for each test case
|
| 333 |
+
- Generate 5-8 test cases with clear separation
|
| 334 |
+
|
| 335 |
+
FORMAT EACH TEST CASE EXACTLY AS SHOWN:
|
| 336 |
+
|
| 337 |
+
Test Case ID: TC_001
|
| 338 |
+
Title: Login with valid credentials
|
| 339 |
+
Preconditions: User has a valid account, application is accessible
|
|
|
|
| 340 |
Test Steps:
|
| 341 |
+
1. Navigate to login page
|
| 342 |
+
2. Enter valid username
|
| 343 |
+
3. Enter valid password
|
| 344 |
+
4. Click login button
|
| 345 |
+
Expected Results: User successfully logs in and redirects to dashboard
|
| 346 |
+
Priority: High
|
| 347 |
+
Test Data: username: testuser@example.com, password: Test123!
|
| 348 |
+
|
| 349 |
+
Test Case ID: TC_002
|
| 350 |
+
Title: Login with invalid credentials
|
| 351 |
+
Preconditions: Application is accessible
|
| 352 |
+
Test Steps:
|
| 353 |
+
1. Navigate to login page
|
| 354 |
+
2. Enter invalid username
|
| 355 |
+
3. Enter invalid password
|
| 356 |
+
4. Click login button
|
| 357 |
+
Expected Results: Error message displayed, user remains on login page
|
| 358 |
+
Priority: High
|
| 359 |
+
Test Data: username: invalid@test.com, password: wrongpass
|
| 360 |
+
|
| 361 |
+
Now generate test cases for the given requirements following this EXACT format.
|
| 362 |
"""
|
| 363 |
|
| 364 |
messages = [{"role": "user", "content": enhanced_prompt}]
|
| 365 |
response = call_openai_chat(messages, max_tokens=4000)
|
| 366 |
|
| 367 |
if "Error:" in response:
|
| 368 |
+
return response, None, None
|
| 369 |
|
| 370 |
df = parse_test_cases_to_dataframe(response)
|
| 371 |
csv_path = create_download_csv(df, "generated_test_cases")
|
| 372 |
|
| 373 |
+
return response, df, csv_path
|
| 374 |
|
| 375 |
def generate_test_cases_from_image(image, test_focus):
|
| 376 |
"""Enhanced image-based test case generation"""
|
| 377 |
|
| 378 |
+
if image is None:
|
| 379 |
+
return "Please upload an image first.", None, None
|
| 380 |
+
|
| 381 |
base64_image = encode_image(image)
|
| 382 |
|
| 383 |
enhanced_prompt = f"""
|
| 384 |
+
As an expert QA engineer, analyze this UI/wireframe/mockup image and create test cases.
|
| 385 |
+
|
| 386 |
FOCUS AREA: {test_focus}
|
| 387 |
+
|
| 388 |
+
Use EXACTLY this format for each test case:
|
| 389 |
+
|
| 390 |
+
Test Case ID: TC_001
|
| 391 |
+
Title: [Clear descriptive title]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 392 |
Preconditions: [Setup requirements]
|
| 393 |
Test Steps:
|
| 394 |
+
1. [Step 1]
|
| 395 |
+
2. [Step 2]
|
| 396 |
+
3. [Step 3]
|
| 397 |
+
Expected Results: [Expected outcome]
|
| 398 |
+
Priority: [High/Medium/Low]
|
| 399 |
+
Test Data: [Required data]
|
| 400 |
+
|
| 401 |
+
Generate 5-8 test cases covering all visible UI elements and user flows.
|
| 402 |
"""
|
| 403 |
|
| 404 |
messages = [
|
|
|
|
| 414 |
response = call_openai_chat(messages, model="gpt-4o-mini", max_tokens=4000)
|
| 415 |
|
| 416 |
if "Error:" in response:
|
| 417 |
+
return response, None, None
|
| 418 |
|
| 419 |
df = parse_test_cases_to_dataframe(response)
|
| 420 |
csv_path = create_download_csv(df, "image_based_test_cases")
|
| 421 |
|
| 422 |
+
return response, df, csv_path
|
| 423 |
|
| 424 |
def optimize_test_cases(existing_cases, focus_areas, optimization_goal):
|
| 425 |
"""Enhanced test case optimization"""
|
|
|
|
| 755 |
with gr.Column():
|
| 756 |
test_cases_output = gr.Textbox(
|
| 757 |
label="Generated Test Cases",
|
| 758 |
+
lines=10,
|
| 759 |
+
max_lines=15
|
| 760 |
)
|
| 761 |
+
|
| 762 |
+
# Add a separate row for the dataframe and download
|
| 763 |
+
with gr.Row():
|
| 764 |
+
test_cases_table = gr.Dataframe(
|
| 765 |
+
label="π Test Cases Table",
|
| 766 |
+
interactive=False,
|
| 767 |
+
wrap=True
|
| 768 |
+
)
|
| 769 |
+
|
| 770 |
+
with gr.Row():
|
| 771 |
+
csv_download = gr.File(label="π₯ Download CSV")
|
| 772 |
|
| 773 |
generate_btn.click(
|
| 774 |
fn=generate_test_cases_from_text,
|
| 775 |
inputs=[requirements_input, test_types, priority_level],
|
| 776 |
+
outputs=[test_cases_output, test_cases_table, csv_download]
|
| 777 |
)
|
| 778 |
|
| 779 |
with gr.TabItem("Image Requirements"):
|
|
|
|
| 793 |
with gr.Column():
|
| 794 |
img_test_cases_output = gr.Textbox(
|
| 795 |
label="Generated Test Cases",
|
| 796 |
+
lines=10,
|
| 797 |
+
max_lines=15
|
| 798 |
)
|
| 799 |
+
|
| 800 |
+
# Add separate row for table and download
|
| 801 |
+
with gr.Row():
|
| 802 |
+
img_test_cases_table = gr.Dataframe(
|
| 803 |
+
label="π Test Cases Table",
|
| 804 |
+
interactive=False,
|
| 805 |
+
wrap=True
|
| 806 |
+
)
|
| 807 |
+
|
| 808 |
+
with gr.Row():
|
| 809 |
+
img_csv_download = gr.File(label="π₯ Download CSV")
|
| 810 |
|
| 811 |
generate_img_btn.click(
|
| 812 |
fn=generate_test_cases_from_image,
|
| 813 |
inputs=[image_input, test_focus],
|
| 814 |
+
outputs=[img_test_cases_output, img_test_cases_table, img_csv_download]
|
| 815 |
)
|
| 816 |
|
| 817 |
# Test Case Optimization Tab
|