0

这是一个关于 tSQLt / SQL 测试最佳实践的问题。

假设我有一个存储过程,它返回一个简单的 SELECT 语句的结果,例如

SELECT
    A.Column1
,   B.Column2
FROM
    TableA AS A
INNER JOIN
    TableB AS B
ON
    A.ID = B.ID
    ;

我正在考虑要写什么 tSQLt 测试。最明显的测试是我在两个表中都有记录(具有匹配的 ID)并且该过程返回正确的数据。

那个测试够吗?可能不会,因为有人可以将 INNER JOIN 更改为 LEFT JOIN,测试仍然可以通过,但是存储过程的行为现在已经改变。

因此,我是否应该测试 TableA 或 TableB 何时为空,或者两个表都为空,是否不返回任何记录?虽然我认为这更完整,但对我来说这听起来有点矫枉过正,并且可能导致对具有 5 个或更多表的 SELECT 语句进行大量测试。

我会欣赏社区的想法。

谢谢,

4

1 回答 1

3

确保存在 INNER JOIN 更重要。因为我们不想具体说明存储过程是如何实现的。但是,我们确实希望确保存储过程的预期结果始终按预期返回。

我的测试看起来像这样:

CREATE PROCEDURE [MyTests.SimpleTests].[test Returns_SimpleTable_Successfully]
AS
BEGIN
    --Arrange
    EXEC tSQLt.FakeTable @schemaname = 'dbo', @tablename = 'TableA';
    EXEC tSQLt.FakeTable @schemaname = 'dbo', @tablename = 'TableB';

    INSERT INTO TableA (Id, Column1) VALUES (1, 'Value1'),(2, 'Value2')
    INSERT INTO TableB (Id, Column2) VALUES (1, 'Value3'),(3, 'Value4')

    CREATE TABLE Expected
    (
       Column1 NVARCHAR(255),
       Column2 NVARCHAR(255)
    )

    INSERT Expected (Column1, Column2)
    VALUES (N'Value1', N'Value3');

    --Act
    CREATE TABLE Actual
    (
       Column1 NVARCHAR(255),
       Column2 NVARCHAR(255)
    )

    INSERT Actual (Column1, Column2)
    EXEC up_SimpleTest

    --Assert
    EXEC tSQLt.AssertEqualsTable 'Expected', 'Actual'

END;

被测试的存储过程如下所示:

CREATE PROC up_SimpleTest
AS
BEGIN

    SELECT
        A.Column1,
        B.Column2
    FROM TableA AS A
    RIGHT JOIN TableB AS B
        ON A.Id = B.Id;

END

这意味着如果存储过程更改为 LEFT、RIGHT 或 FULL 连接。测试将失败,因为不会返回预期的数据。但是,它确实允许存储过程更改为此并且仍然有效:

SELECT
    A.Column1,
    B.Column2
FROM TableA A, TableB B
WHERE A.Id = B.Id

这就是我们不应该也不能强制使用 INNER JOIN 的原因,因为关于如何实现查询还有许多其他有效方法。

于 2015-10-16T07:39:24.460 回答