Spaces:
Sleeping
Sleeping
File size: 10,092 Bytes
798461f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | """
test_env.py β Smoke test for SQL Analytics OpenEnv environment
"""
import sys, os
sys.stdout.reconfigure(encoding="utf-8") if hasattr(sys.stdout, "reconfigure") else None
sys.path.insert(0, os.path.dirname(__file__))
from models import SQLAction
from server.sql_analytics_environment import SQLAnalyticsEnvironment, TASKS
PASS = "[PASS]"
FAIL = "[FAIL]"
# ββ Correct SQL answers for all 10 tasks ββββββββββββββββββββββββββββββββββββββ
CORRECT_SQL = {
"task_001": "SELECT COUNT(*) FROM customers WHERE state = 'CA'",
"task_002": """
SELECT p.name, p.price FROM products p
JOIN categories c ON p.category_id = c.id
WHERE c.name = 'Electronics' ORDER BY p.price DESC LIMIT 1
""",
"task_003": """
SELECT c.name, ROUND(SUM(o.total_amount), 2) AS total_spent
FROM customers c JOIN orders o ON c.id = o.customer_id
GROUP BY c.id, c.name ORDER BY total_spent DESC LIMIT 5
""",
"task_004": """
SELECT cat.name AS category_name, ROUND(AVG(r.rating), 2) AS avg_rating
FROM reviews r JOIN products p ON r.product_id = p.id
JOIN categories cat ON p.category_id = cat.id
GROUP BY cat.id, cat.name ORDER BY avg_rating DESC LIMIT 1
""",
"task_005": """
SELECT DISTINCT c.name, c.email FROM customers c
WHERE c.id IN (SELECT customer_id FROM orders WHERE order_date < '2024-04-01')
AND c.id NOT IN (SELECT customer_id FROM orders WHERE order_date >= '2024-04-01')
ORDER BY c.name
""",
"task_006": """
SELECT CAST(strftime('%m', order_date) AS INTEGER) AS month,
ROUND(SUM(total_amount), 2) AS revenue, NULL AS growth_rate
FROM orders WHERE status = 'delivered'
AND order_date BETWEEN '2024-01-01' AND '2024-12-31'
GROUP BY month ORDER BY month
""",
"task_007": "SELECT COUNT(*) FROM products WHERE stock = 0",
"task_008": "SELECT ROUND(AVG(total_amount), 2) AS avg_order_value FROM orders",
"task_009": """
SELECT p.name, cat.name AS category_name
FROM products p JOIN categories cat ON p.category_id = cat.id
LEFT JOIN reviews rv ON p.id = rv.product_id
WHERE rv.id IS NULL ORDER BY p.name
""",
"task_010": """
SELECT state, COUNT(*) AS customer_count FROM customers
GROUP BY state ORDER BY customer_count DESC LIMIT 1
""",
}
WRONG_SQL = {
"task_001": "SELECT COUNT(*) FROM customers WHERE state = 'TX'",
"task_002": "INVALID SQL !!!",
"task_003": "SELECT name FROM customers LIMIT 5",
"task_004": "SELECT 'Electronics', 5.0",
"task_005": "SELECT name, email FROM customers LIMIT 2",
"task_006": "SELECT 1 AS month, 100.0 AS revenue",
"task_007": "SELECT COUNT(*) FROM products WHERE stock > 100",
"task_008": "SELECT ROUND(AVG(total_amount), 2) AS avg FROM orders WHERE status='delivered'",
"task_009": "SELECT name FROM products LIMIT 3",
"task_010": "SELECT state FROM customers LIMIT 1",
}
def separator(title):
print(f"\n{'='*60}")
print(f" {title}")
print('='*60)
def run_test(env, task_id, sql, label):
env.reset(task_id=task_id)
obs = env.step(SQLAction(sql=sql))
icon = PASS if (label == "CORRECT" and obs.reward >= 0.8) or \
(label == "WRONG" and obs.reward < 0.5) else FAIL
result_count = len(obs.result) if obs.result else 0
print(
f" {icon} [{label:7s}] reward={obs.reward:.4f} "
f"rows={result_count:3d} done={str(obs.done):5s} "
f"| {(obs.metadata or {}).get('message','')[:55]}"
)
return obs.reward
def main():
print("\n" + "="*60)
print(" SQL Analytics OpenEnv β Full Smoke Test (10 tasks)")
print("="*60)
env = SQLAnalyticsEnvironment()
print(f"\n {PASS} Environment instantiated (SQLite DB seeded)")
# ββ 1. Rich Schema ββββββββββββββββββββββββββββββββββββββββββββββββββββ
separator("1. Rich Schema (sample data included)")
obs = env.reset(task_id="task_001")
assert obs.db_schema, "Schema should be populated on reset"
assert "Sample" in obs.db_schema, "Rich schema should include sample data"
assert "rows)" in obs.db_schema, "Rich schema should include row counts"
print(f" {PASS} reset() returns RICH schema with sample data + row counts")
print(f"\n Schema preview (first 15 lines):\n")
for line in (obs.db_schema or "").splitlines()[:15]:
print(f" {line}")
# ββ 2. All 10 tasks β correct SQL βββββββββββββββββββββββββββββββββββββ
separator("2. Correct SQL β all 10 tasks (expect reward >= 0.8)")
correct_scores = []
for task in TASKS:
tid = task["task_id"]
score = run_test(env, tid, CORRECT_SQL[tid], "CORRECT")
correct_scores.append(score)
# ββ 3. All 10 tasks β wrong SQL βββββββββββββββββββββββββββββββββββββββ
separator("3. Wrong SQL β all 10 tasks (expect reward < 0.5)")
wrong_scores = []
for task in TASKS:
tid = task["task_id"]
score = run_test(env, tid, WRONG_SQL[tid], "WRONG")
wrong_scores.append(score)
# ββ 4. Efficiency bonus βββββββββββββββββββββββββββββββββββββββββββββββ
separator("4. Efficiency Bonus (solve in 1 step vs 5 steps)")
env.reset(task_id="task_001")
obs1 = env.step(SQLAction(sql=CORRECT_SQL["task_001"])) # solve in 1 step
print(f" Solved in 1 step β reward={obs1.reward:.4f}")
env.reset(task_id="task_001")
for _ in range(4):
env.step(SQLAction(sql="SELECT 1")) # 4 wrong attempts
obs5 = env.step(SQLAction(sql=CORRECT_SQL["task_001"])) # solve on 5th step
print(f" Solved in 5 steps β reward={obs5.reward:.4f}")
assert obs1.reward > obs5.reward, "1-step solve should have higher reward than 5-step"
print(f" {PASS} Efficiency bonus working: {obs1.reward:.4f} > {obs5.reward:.4f}")
# ββ 5. Educational error messages βββββββββββββββββββββββββββββββββββββ
separator("5. Educational Error Messages")
env.reset(task_id="task_001")
bad_table = env.step(SQLAction(sql="SELECT * FROM orderz"))
print(f" Bad table name : {bad_table.error[:65]}")
assert "Available tables" in (bad_table.error or ""), "Should mention available tables"
print(f" {PASS} Bad table β educational message with available tables")
bad_col = env.step(SQLAction(sql="SELECT nonexistent_col FROM customers"))
print(f" Bad column name : {bad_col.error[:65]}")
print(f" {PASS} Bad column β educational error message")
syntax_err = env.step(SQLAction(sql="SELECT FROM customers WHERE"))
print(f" Syntax error : {syntax_err.error[:65]}")
assert "syntax" in (syntax_err.error or "").lower()
print(f" {PASS} Syntax error β educational message")
# ββ 6. New task verification (007β010) ββββββββββββββββββββββββββββββββ
separator("6. New Tasks (007-010) correct answers")
for tid in ["task_007", "task_008", "task_009", "task_010"]:
env.reset(task_id=tid)
obs = env.step(SQLAction(sql=CORRECT_SQL[tid]))
icon = PASS if obs.reward >= 0.8 else FAIL
print(f" {icon} {tid} reward={obs.reward:.4f} done={obs.done}")
# ββ 7. Steps remaining in metadata βββββββββββββββββββββββββββββββββββ
separator("7. steps_remaining in metadata")
env.reset(task_id="task_002")
for i in range(3):
obs = env.step(SQLAction(sql="SELECT 1"))
remaining = (obs.metadata or {}).get("steps_remaining", -1)
assert remaining == 7, f"Expected 7 steps remaining after 3 steps, got {remaining}"
print(f" {PASS} steps_remaining={remaining} correctly tracked")
# ββ 8. State tracking ββββββββββββββββββββββββββββββββββββββββββββββββ
separator("8. State Tracking")
env.reset(task_id="task_003")
for i in range(3):
env.step(SQLAction(sql="SELECT 1"))
s = env.state
assert s.attempts == 3
assert s.step_count == 3
print(f" {PASS} step_count={s.step_count} attempts={s.attempts} task_id={s.task_id}")
# ββ 9. Max attempts cap βββββββββββββββββββββββββββββββββββββββββββββββ
separator("9. Max Attempts Cap (10 steps β done=True)")
env.reset(task_id="task_002")
last_obs = None
for _ in range(11):
last_obs = env.step(SQLAction(sql="SELECT 1"))
if last_obs.done:
break
assert last_obs.done
print(f" {PASS} done=True after {env.state.attempts} attempts")
# ββ Summary βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
separator("Summary")
avg_correct = sum(correct_scores) / len(correct_scores)
avg_wrong = sum(wrong_scores) / len(wrong_scores)
all_pass = avg_correct >= 0.8 and avg_wrong < 0.5
print(f" Tasks total : {len(TASKS)}")
print(f" Avg reward (correct) : {avg_correct:.4f}")
print(f" Avg reward (wrong) : {avg_wrong:.4f}")
print()
icon = PASS if all_pass else FAIL
print(f" {icon} Overall: {'PASSED' if all_pass else 'FAILED'}")
print()
if not all_pass:
sys.exit(1)
if __name__ == "__main__":
main()
|