You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在游标中运行tSQLt断言:多测试合并为单测试的问题

我之前也碰到过这种为同一存储过程的不同参数写一堆重复测试的情况,确实太冗余了。你用游标没跑起来,大概率是实现没贴合tSQLt的运行逻辑,或者游标本身的写法有问题。下面给你两种靠谱的解决思路,尤其是第一种,直接把35个参数的测试合并到一个tSQLt测试里:

方法一:在单个测试存储过程中遍历参数执行断言

这是最直接的方式,把所有参数值放到一个集合里,循环遍历每个参数执行测试逻辑,同时在断言里带上参数值,方便出问题时快速定位。

具体代码示例

首先确保你已经创建了tSQLt测试类(如果还没的话):

EXEC tSQLt.NewTestClass 'Test_YourTargetStoredProc';
GO

然后编写合并后的测试存储过程:

CREATE PROCEDURE Test_YourTargetStoredProc.[Test StoredProc with all parameter variations]
AS
BEGIN
    -- 1. 调用你的假表填充存储过程,准备测试环境
    EXEC dbo.PopulateYourFakeTables;

    -- 2. 定义所有要测试的参数值,这里用临时表存储,替换成你的参数类型和实际值
    CREATE TABLE #TestParams (ParamValue VARCHAR(50) /* 改成你的参数类型 */);
    INSERT INTO #TestParams (ParamValue)
    VALUES ('ParamVal1'), ('ParamVal2'), ('ParamVal3'), /* ... 把35个参数值都列进来 ... */;

    -- 3. 遍历参数执行测试
    DECLARE @CurrentParam VARCHAR(50);
    DECLARE paramCursor CURSOR FOR SELECT ParamValue FROM #TestParams;
    
    OPEN paramCursor;
    FETCH NEXT FROM paramCursor INTO @CurrentParam;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        -- 执行被测试的存储过程,传入当前参数
        EXEC dbo.YourTargetStoredProc @YourParam = @CurrentParam;

        -- 这里写你的断言逻辑,举个例子:检查假表中的结果是否符合预期
        DECLARE @ExpectedResult INT = 10; -- 替换成你的预期值
        DECLARE @ActualResult INT;
        SELECT @ActualResult = COUNT(*) FROM dbo.FakeResultTable WHERE InputParam = @CurrentParam;

        -- 断言时带上参数值,方便定位失败案例
        EXEC tSQLt.AssertEquals 
            @Expected = @ExpectedResult, 
            @Actual = @ActualResult, 
            @Message = '测试失败,参数值:' + @CurrentParam;

        FETCH NEXT FROM paramCursor INTO @CurrentParam;
    END

    -- 清理游标
    CLOSE paramCursor;
    DEALLOCATE paramCursor;
END;
GO

运行测试

执行这条命令就能跑这个合并后的测试:

EXEC tSQLt.Run 'Test_YourTargetStoredProc.[Test StoredProc with all parameter variations]';

为什么你之前的游标方案没执行测试?

大概率是这几个原因:

  • 测试命名不符合规范:tSQLt只会识别属于测试类、名称以Test开头的存储过程为测试,检查下你的测试存储过程命名是不是TestClassName.[Test ...]的格式。
  • 参数集合为空:如果你的游标查询的参数列表是空的,循环根本不会执行,tSQLt会认为测试没做任何操作。
  • 没有触发断言:如果测试过程中没有执行任何tSQLt.Assert*方法,tSQLt可能会标记测试为“未执行”,因为它看不到任何验证逻辑。

备选方法:用动态SQL生成参数化测试(可选)

如果你想保留每个参数案例作为独立的测试条目,但又不想手动写35个存储过程,可以用动态SQL批量生成测试。不过这个方法是生成多个测试,不是合并成一个,适合需要单独查看每个参数测试结果的场景:

DECLARE @ParamValue VARCHAR(50);
DECLARE @TestProcName VARCHAR(100);
DECLARE @SQL NVARCHAR(MAX);

-- 这里可以复用之前的#TestParams临时表,或者重新定义参数集合
CREATE TABLE #TestParams (ParamValue VARCHAR(50));
INSERT INTO #TestParams (ParamValue)
VALUES ('ParamVal1'), ('ParamVal2'), ('ParamVal3'), /* ... 所有参数值 ... */;

DECLARE paramCursor CURSOR FOR SELECT ParamValue FROM #TestParams;
OPEN paramCursor;
FETCH NEXT FROM paramCursor INTO @ParamValue;

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 生成合法的测试存储过程名称,替换特殊字符
    SET @TestProcName = 'Test_YourTargetStoredProc.[Test StoredProc with param: ' + REPLACE(@ParamValue, ' ', '_') + ']';
    SET @SQL = N'
    CREATE PROCEDURE ' + @TestProcName + '
    AS
    BEGIN
        EXEC dbo.PopulateYourFakeTables;
        EXEC dbo.YourTargetStoredProc @YourParam = ''' + @ParamValue + ''';
        -- 这里写你的断言逻辑,和上面一致
        DECLARE @ExpectedResult INT = 10;
        DECLARE @ActualResult INT;
        SELECT @ActualResult = COUNT(*) FROM dbo.FakeResultTable WHERE InputParam = ''' + @ParamValue + ''';
        EXEC tSQLt.AssertEquals @ExpectedResult, @ActualResult;
    END;';

    EXEC sp_executesql @SQL;
    FETCH NEXT FROM paramCursor INTO @ParamValue;
END

CLOSE paramCursor;
DEALLOCATE paramCursor;

这个方法会自动生成35个测试存储过程,每个对应一个参数值,你可以用tSQLt.Run 'Test_YourTargetStoredProc';一次性跑所有测试。

内容的提问来源于stack exchange,提问作者JMariña

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:13:59