跳转至

SQL测试用例

测试目标: 验证SQL语句的正确性和性能 测试类型: 语法测试、功能测试、性能测试 涉及组件: SELECT、INSERT、UPDATE、DELETE、JOIN、子查询


📋 测试概述

测试目标

  1. 语法测试: 验证SQL语法正确性
  2. 功能测试: 验证SQL功能正确性
  3. 性能测试: 评估SQL执行效率
  4. 边界测试: 测试边界条件

测试环境

  • 数据库: MySQL 8.0+, PostgreSQL 13+
  • 测试框架: pytest
  • 数据生成: Faker

🧪 测试用例列表

1. SELECT语句测试

测试用例1.1: 基础SELECT

测试目标: 验证基础SELECT语句

测试代码:

Python
import pytest
import mysql.connector
from mysql.connector import Error

def test_basic_select():
    """测试基础SELECT"""
    # 创建连接
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 执行SELECT
        cursor.execute("SELECT * FROM users LIMIT 10")
        results = cursor.fetchall()

        # 验证结果
        assert isinstance(results, list)
        assert len(results) <= 10

        if results:
            assert 'id' in results[0]
            assert 'name' in results[0]

        print("✓ 基础SELECT测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 查询成功返回结果


测试用例1.2: WHERE子句

测试目标: 验证WHERE子句

测试代码:

Python
def test_where_clause():
    """测试WHERE子句"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 测试等于
        cursor.execute("SELECT * FROM users WHERE id = 1")
        results = cursor.fetchall()
        assert len(results) == 1

        # 测试大于
        cursor.execute("SELECT * FROM users WHERE age > 18")
        results = cursor.fetchall()
        assert all(r['age'] > 18 for r in results)

        # 测试IN
        cursor.execute("SELECT * FROM users WHERE status IN ('active', 'pending')")
        results = cursor.fetchall()
        assert all(r['status'] in ['active', 'pending'] for r in results)

        # 测试LIKE
        cursor.execute("SELECT * FROM users WHERE name LIKE 'A%'")
        results = cursor.fetchall()
        assert all(r['name'].startswith('A') for r in results)

        print("✓ WHERE子句测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 所有WHERE条件正确过滤数据


测试用例1.3: ORDER BY和LIMIT

测试目标: 验证ORDER BY和LIMIT

测试代码:

Python
def test_order_by_limit():
    """测试ORDER BY和LIMIT"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 测试ORDER BY ASC
        cursor.execute("SELECT * FROM users ORDER BY age ASC LIMIT 5")
        results = cursor.fetchall()
        ages = [r['age'] for r in results]
        assert ages == sorted(ages)

        # 测试ORDER BY DESC
        cursor.execute("SELECT * FROM users ORDER BY created_at DESC LIMIT 5")
        results = cursor.fetchall()
        assert len(results) == 5

        # 测试多列排序
        cursor.execute("SELECT * FROM users ORDER BY status, age DESC LIMIT 10")
        results = cursor.fetchall()
        assert len(results) == 10

        print("✓ ORDER BY和LIMIT测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 结果按指定顺序排序


测试用例1.4: 聚合函数

测试目标: 验证聚合函数

测试代码:

Python
def test_aggregate_functions():
    """测试聚合函数"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 测试COUNT
        cursor.execute("SELECT COUNT(*) as count FROM users")
        result = cursor.fetchone()
        assert 'count' in result
        assert result['count'] >= 0

        # 测试SUM
        cursor.execute("SELECT SUM(age) as total_age FROM users")
        result = cursor.fetchone()
        assert 'total_age' in result

        # 测试AVG
        cursor.execute("SELECT AVG(age) as avg_age FROM users")
        result = cursor.fetchone()
        assert 'avg_age' in result
        assert result['avg_age'] > 0

        # 测试MAX和MIN
        cursor.execute("SELECT MAX(age) as max_age, MIN(age) as min_age FROM users")
        result = cursor.fetchone()
        assert 'max_age' in result
        assert 'min_age' in result
        assert result['max_age'] >= result['min_age']

        # 测试GROUP BY
        cursor.execute("SELECT status, COUNT(*) as count FROM users GROUP BY status")
        results = cursor.fetchall()
        assert len(results) > 0
        assert all('status' in r and 'count' in r for r in results)

        print("✓ 聚合函数测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 聚合函数正确计算


2. JOIN操作测试

测试用例2.1: INNER JOIN

测试目标: 验证INNER JOIN

测试代码:

Python
def test_inner_join():
    """测试INNER JOIN"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 执行INNER JOIN
        query = """
        SELECT u.id, u.name, o.id as order_id, o.amount
        FROM users u
        INNER JOIN orders o ON u.id = o.user_id
        LIMIT 10
        """
        cursor.execute(query)
        results = cursor.fetchall()

        # 验证结果
        assert isinstance(results, list)  # isinstance检查对象类型
        assert len(results) <= 10

        for result in results:
            assert 'id' in result
            assert 'name' in result
            assert 'order_id' in result
            assert 'amount' in result

        print("✓ INNER JOIN测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 只返回匹配的行


测试用例2.2: LEFT JOIN

测试目标: 验证LEFT JOIN

测试代码:

Python
def test_left_join():
    """测试LEFT JOIN"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 执行LEFT JOIN
        query = """
        SELECT u.id, u.name, o.id as order_id
        FROM users u
        LEFT JOIN orders o ON u.id = o.user_id
        LIMIT 10
        """
        cursor.execute(query)
        results = cursor.fetchall()

        # 验证结果
        assert len(results) > 0

        # LEFT JOIN应该返回所有左表行
        # 即使右表没有匹配
        for result in results:
            assert 'id' in result
            assert 'name' in result
            # order_id可能为NULL
            assert 'order_id' in result

        print("✓ LEFT JOIN测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 返回所有左表行


测试用例2.3: 多表JOIN

测试目标: 验证多表JOIN

测试代码:

Python
def test_multiple_join():
    """测试多表JOIN"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 执行多表JOIN
        query = """
        SELECT u.id, u.name, o.id as order_id, p.name as product_name
        FROM users u
        INNER JOIN orders o ON u.id = o.user_id
        INNER JOIN order_items oi ON o.id = oi.order_id
        INNER JOIN products p ON oi.product_id = p.id
        LIMIT 10
        """
        cursor.execute(query)
        results = cursor.fetchall()

        # 验证结果
        assert len(results) <= 10

        for result in results:
            assert 'id' in result
            assert 'name' in result
            assert 'order_id' in result
            assert 'product_name' in result

        print("✓ 多表JOIN测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 正确连接多个表


3. INSERT语句测试

测试用例3.1: 基础INSERT

测试目标: 验证基础INSERT语句

测试代码:

Python
def test_basic_insert():
    """测试基础INSERT"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 插入数据
        query = """
        INSERT INTO users (name, email, age, status)
        VALUES ('Test User', 'test@example.com', 25, 'active')
        """
        cursor.execute(query)
        conn.commit()

        # 验证插入
        assert cursor.rowcount == 1

        # 查询验证
        cursor.execute("SELECT * FROM users WHERE name = 'Test User'")
        result = cursor.fetchone()
        assert result is not None
        assert result['name'] == 'Test User'
        assert result['email'] == 'test@example.com'

        # 清理测试数据
        cursor.execute("DELETE FROM users WHERE name = 'Test User'")
        conn.commit()

        print("✓ 基础INSERT测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 数据成功插入


测试用例3.2: 批量INSERT

测试目标: 验证批量INSERT

测试代码:

Python
def test_batch_insert():
    """测试批量INSERT"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 批量插入数据
        query = """
        INSERT INTO users (name, email, age, status)
        VALUES (%s, %s, %s, %s)
        """

        data = [
            ('User 1', 'user1@example.com', 20, 'active'),
            ('User 2', 'user2@example.com', 25, 'active'),
            ('User 3', 'user3@example.com', 30, 'active'),
        ]

        cursor.executemany(query, data)
        conn.commit()

        # 验证插入
        assert cursor.rowcount == 3

        # 查询验证
        cursor.execute("SELECT COUNT(*) as count FROM users WHERE name LIKE 'User %'")
        result = cursor.fetchone()
        assert result['count'] >= 3

        # 清理测试数据
        cursor.execute("DELETE FROM users WHERE name LIKE 'User %'")
        conn.commit()

        print("✓ 批量INSERT测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 批量数据成功插入


4. UPDATE语句测试

测试用例4.1: 基础UPDATE

测试目标: 验证基础UPDATE语句

测试代码:

Python
def test_basic_update():
    """测试基础UPDATE"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 先插入测试数据
        cursor.execute("""
            INSERT INTO users (name, email, age, status)
            VALUES ('Update Test', 'update@example.com', 25, 'active')
        """)
        conn.commit()

        # 更新数据
        query = "UPDATE users SET age = 26 WHERE name = 'Update Test'"
        cursor.execute(query)
        conn.commit()

        # 验证更新
        assert cursor.rowcount == 1

        # 查询验证
        cursor.execute("SELECT age FROM users WHERE name = 'Update Test'")
        result = cursor.fetchone()
        assert result['age'] == 26

        # 清理测试数据
        cursor.execute("DELETE FROM users WHERE name = 'Update Test'")
        conn.commit()

        print("✓ 基础UPDATE测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 数据成功更新


测试用例4.2: 条件UPDATE

测试目标: 验证条件UPDATE

测试代码:

Python
def test_conditional_update():
    """测试条件UPDATE"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 插入测试数据
        cursor.executemany("""
            INSERT INTO users (name, email, age, status)
            VALUES (%s, %s, %s, %s)
        """, [
            ('Test 1', 'test1@example.com', 20, 'active'),
            ('Test 2', 'test2@example.com', 25, 'active'),
            ('Test 3', 'test3@example.com', 30, 'active'),
        ])
        conn.commit()

        # 条件更新
        query = "UPDATE users SET status = 'inactive' WHERE age > 25"
        cursor.execute(query)
        conn.commit()

        # 验证更新
        assert cursor.rowcount >= 1

        # 查询验证
        cursor.execute("SELECT COUNT(*) as count FROM users WHERE status = 'inactive' AND name LIKE 'Test %'")
        result = cursor.fetchone()
        assert result['count'] >= 1

        # 清理测试数据
        cursor.execute("DELETE FROM users WHERE name LIKE 'Test %'")
        conn.commit()

        print("✓ 条件UPDATE测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 符合条件的数据被更新


5. DELETE语句测试

测试用例5.1: 基础DELETE

测试目标: 验证基础DELETE语句

测试代码:

Python
def test_basic_delete():
    """测试基础DELETE"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 插入测试数据
        cursor.execute("""
            INSERT INTO users (name, email, age, status)
            VALUES ('Delete Test', 'delete@example.com', 25, 'active')
        """)
        conn.commit()

        # 删除数据
        query = "DELETE FROM users WHERE name = 'Delete Test'"
        cursor.execute(query)
        conn.commit()

        # 验证删除
        assert cursor.rowcount == 1

        # 查询验证
        cursor.execute("SELECT COUNT(*) as count FROM users WHERE name = 'Delete Test'")
        result = cursor.fetchone()
        assert result['count'] == 0

        print("✓ 基础DELETE测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 数据成功删除


测试用例5.2: 条件DELETE

测试目标: 验证条件DELETE

测试代码:

Python
def test_conditional_delete():
    """测试条件DELETE"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 插入测试数据
        cursor.executemany("""
            INSERT INTO users (name, email, age, status)
            VALUES (%s, %s, %s, %s)
        """, [
            ('Test 1', 'test1@example.com', 20, 'active'),
            ('Test 2', 'test2@example.com', 25, 'active'),
            ('Test 3', 'test3@example.com', 30, 'active'),
        ])
        conn.commit()

        # 条件删除
        query = "DELETE FROM users WHERE age > 25 AND name LIKE 'Test %'"
        cursor.execute(query)
        conn.commit()

        # 验证删除
        assert cursor.rowcount >= 1

        # 查询验证
        cursor.execute("SELECT COUNT(*) as count FROM users WHERE age > 25 AND name LIKE 'Test %'")
        result = cursor.fetchone()
        assert result['count'] == 0

        # 清理剩余测试数据
        cursor.execute("DELETE FROM users WHERE name LIKE 'Test %'")
        conn.commit()

        print("✓ 条件DELETE测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 符合条件的数据被删除


6. 子查询测试

测试用例6.1: 标量子查询

测试目标: 验证标量子查询

测试代码:

Python
def test_scalar_subquery():
    """测试标量子查询"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 使用子查询
        query = """
        SELECT * FROM users
        WHERE age > (SELECT AVG(age) FROM users)
        LIMIT 10
        """
        cursor.execute(query)
        results = cursor.fetchall()

        # 验证结果
        assert len(results) <= 10

        # 获取平均年龄
        cursor.execute("SELECT AVG(age) as avg_age FROM users")
        avg_age = cursor.fetchone()['avg_age']

        # 验证所有结果年龄都大于平均值
        for result in results:
            assert result['age'] > avg_age

        print("✓ 标量子查询测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 子查询正确执行


测试用例6.2: EXISTS子查询

测试目标: 验证EXISTS子查询

测试代码:

Python
def test_exists_subquery():
    """测试EXISTS子查询"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:
        # 使用EXISTS子查询
        query = """
        SELECT u.id, u.name
        FROM users u
        WHERE EXISTS (
            SELECT 1 FROM orders o
            WHERE o.user_id = u.id
        )
        LIMIT 10
        """
        cursor.execute(query)
        results = cursor.fetchall()

        # 验证结果
        assert len(results) <= 10  # assert断言:条件为False时抛出AssertionError

        for result in results:
            assert 'id' in result
            assert 'name' in result

        print("✓ EXISTS子查询测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: EXISTS子查询正确执行


7. 性能测试

测试用例7.1: 查询性能测试

测试目标: 测试查询执行时间

测试代码:

Python
import time

def test_query_performance():
    """测试查询性能"""
    conn = mysql.connector.connect(
        host='localhost',
        user='test_user',
        password='test_password',
        database='test_db'
    )

    cursor = conn.cursor(dictionary=True)

    try:  # try/except捕获异常
        # 测试简单查询
        query = "SELECT * FROM users LIMIT 1000"

        start_time = time.time()
        cursor.execute(query)
        results = cursor.fetchall()
        end_time = time.time()

        execution_time = end_time - start_time

        print(f"简单查询执行时间: {execution_time:.4f}s")
        print(f"返回行数: {len(results)}")

        # 验证性能
        assert execution_time < 1.0, "查询执行时间过长"

        # 测试复杂查询
        complex_query = """
        SELECT u.id, u.name, COUNT(o.id) as order_count
        FROM users u
        LEFT JOIN orders o ON u.id = o.user_id
        GROUP BY u.id, u.name
        HAVING COUNT(o.id) > 5
        LIMIT 100
        """

        start_time = time.time()
        cursor.execute(complex_query)
        results = cursor.fetchall()
        end_time = time.time()

        execution_time = end_time - start_time

        print(f"复杂查询执行时间: {execution_time:.4f}s")
        print(f"返回行数: {len(results)}")

        # 验证性能
        assert execution_time < 5.0, "复杂查询执行时间过长"

        print("✓ 查询性能测试通过")

    finally:
        cursor.close()
        conn.close()

预期结果: 查询在合理时间内完成


📊 测试执行

运行所有测试

Bash
# 运行所有测试
pytest tests/test_sql.py -v

# 运行特定测试
pytest tests/test_sql.py::test_basic_select -v

# 生成覆盖率报告
pytest tests/test_sql.py --cov=sql --cov-report=html

✅ 验证方法

1. 自动化验证

  • 运行所有测试用例
  • 检查断言是否通过
  • 记录测试结果

2. 性能基准

  • 建立性能基准
  • 监控查询性能变化
  • 优化慢查询

3. 数据验证

  • 验证查询结果正确性
  • 检查数据完整性
  • 验证约束条件

📝 测试报告

测试报告应包含:

  1. 测试概览
  2. 测试用例数量
  3. 通过/失败统计
  4. 执行时间

  5. 详细结果

  6. 每个测试用例的结果
  7. 查询执行时间
  8. 性能指标

  9. 问题分析

  10. 失败原因分析
  11. 性能瓶颈分析
  12. 优化建议

测试完成标准: 所有测试用例通过 推荐测试频率: 每次SQL更新 测试维护周期: 每周