Tutorial: Creación y ejecución de una prueba unitaria de SQL Server

En este tutorial, se crea una prueba unitaria de SQL Server que comprueba el comportamiento de varios procedimientos almacenados. Las pruebas unitarias de SQL Server se crean para ayudar a identificar los defectos del código que podrían producir un comportamiento incorrecto de la aplicación. Las pruebas unitarias de SQL Server y las pruebas de aplicación se pueden ejecutar como parte de un conjunto de pruebas automatizado.

En este tutorial, realizará las tareas siguientes:

Después de que una de las pruebas unitarias detecte un error en un procedimiento almacenado, corrija ese error y vuelva a ejecutar la prueba.

Requisitos previos

Para completar este tutorial, debe poder conectarse a un servidor de bases de datos (o a una base de datos LocalDB) en el que tenga permisos para crear e implementar una base de datos. Para más información, consulte Permisos necesarios para las características de base de datos de Visual Studio.

Creación de un script que contenga un esquema de base de datos

  1. En el menú Archivo , seleccione Nuevo y, a continuación, seleccione Archivo.

    Aparece el cuadro de diálogo Nuevo archivo .

  2. En la lista Categorías , seleccione General si aún no está resaltado.

  3. En la lista Plantillas, seleccione Archivo SQL y, a continuación, seleccione Abrir.

    Se abre el editor de Transact-SQL.

  4. Copie el código Transact-SQL y péguelo en el editor de Transact-SQL.

    PRINT N'Creating Sales...';
    GO
    
    CREATE SCHEMA [Sales]
        AUTHORIZATION [dbo];
    GO
    
    PRINT N'Creating Sales.Customer...';
    GO
    
    CREATE TABLE [Sales].[Customer]
    (
        [CustomerID] INT IDENTITY (1, 1) NOT NULL,
        [CustomerName] NVARCHAR (40) NOT NULL,
        [YTDOrders] INT NOT NULL,
        [YTDSales] INT NOT NULL
    );
    GO
    
    PRINT N'Creating Sales.Orders...';
    GO
    
    CREATE TABLE [Sales].[Orders]
    (
        [CustomerID] INT NOT NULL,
        [OrderID] INT IDENTITY (1, 1) NOT NULL,
        [OrderDate] DATETIME NOT NULL,
        [FilledDate] DATETIME NULL,
        [Status] CHAR (1) NOT NULL,
        [Amount] INT NOT NULL
    );
    GO
    
    PRINT N'Creating Sales.Def_Customer_YTDOrders...';
    GO
    
    ALTER TABLE [Sales].[Customer]
        ADD CONSTRAINT [Def_Customer_YTDOrders] DEFAULT 0 FOR [YTDOrders];
    GO
    
    PRINT N'Creating Sales.Def_Customer_YTDSales...';
    GO
    
    ALTER TABLE [Sales].[Customer]
        ADD CONSTRAINT [Def_Customer_YTDSales] DEFAULT 0 FOR [YTDSales];
    GO
    
    PRINT N'Creating Sales.Def_Orders_OrderDate...';
    GO
    
    ALTER TABLE [Sales].[Orders]
        ADD CONSTRAINT [Def_Orders_OrderDate] DEFAULT GetDate() FOR [OrderDate];
    GO
    
    PRINT N'Creating Sales.Def_Orders_Status...';
    GO
    
    ALTER TABLE [Sales].[Orders]
        ADD CONSTRAINT [Def_Orders_Status] DEFAULT 'O' FOR [Status];
    GO
    
    PRINT N'Creating Sales.PK_Customer_CustID...';
    GO
    
    ALTER TABLE [Sales].[Customer]
        ADD CONSTRAINT [PK_Customer_CustID] PRIMARY KEY CLUSTERED ([CustomerID] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF);
    GO
    
    PRINT N'Creating Sales.PK_Orders_OrderID...';
    GO
    
    ALTER TABLE [Sales].[Orders]
        ADD CONSTRAINT [PK_Orders_OrderID] PRIMARY KEY CLUSTERED ([OrderID] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF);
    GO
    
    PRINT N'Creating Sales.FK_Orders_Customer_CustID...';
    GO
    
    ALTER TABLE [Sales].[Orders]
        ADD CONSTRAINT [FK_Orders_Customer_CustID] FOREIGN KEY ([CustomerID]) REFERENCES [Sales].[Customer] ([CustomerID]) ON DELETE NO ACTION ON UPDATE NO ACTION;
    GO
    
    PRINT N'Creating Sales.CK_Orders_FilledDate...';
    GO
    
    ALTER TABLE [Sales].[Orders]
        ADD CONSTRAINT [CK_Orders_FilledDate] CHECK ((FilledDate >= OrderDate)
                                                     AND (FilledDate < '01/01/2030'));
    GO
    
    PRINT N'Creating Sales.CK_Orders_OrderDate...';
    GO
    
    ALTER TABLE [Sales].[Orders]
        ADD CONSTRAINT [CK_Orders_OrderDate] CHECK ((OrderDate > '01/01/2005')
                                                    AND (OrderDate < '01/01/2030'));
    GO
    
    PRINT N'Creating Sales.uspCancelOrder...';
    GO
    
    CREATE PROCEDURE [Sales].[uspCancelOrder]
    @OrderID INT
    AS
    BEGIN
        DECLARE @Delta AS INT, @CustomerID AS INT;
        BEGIN TRANSACTION;
        SELECT @Delta = [Amount],
               @CustomerID = [CustomerID]
        FROM [Sales].[Orders]
        WHERE [OrderID] = @OrderID;
        UPDATE [Sales].[Orders]
            SET [Status] = 'X'
        WHERE [OrderID] = @OrderID;
        UPDATE [Sales].[Customer]
            SET YTDOrders = YTDOrders - @Delta
        WHERE [CustomerID] = @CustomerID;
        COMMIT TRANSACTION;
    END
    GO
    
    PRINT N'Creating Sales.uspFillOrder...';
    GO
    
    CREATE PROCEDURE [Sales].[uspFillOrder]
    @OrderID INT, @FilledDate DATETIME
    AS
    BEGIN
        DECLARE @Delta AS INT, @CustomerID AS INT;
        BEGIN TRANSACTION;
        SELECT @Delta = [Amount],
               @CustomerID = [CustomerID]
        FROM [Sales].[Orders]
        WHERE [OrderID] = @OrderID;
        UPDATE [Sales].[Orders]
            SET [Status]     = 'F',
                [FilledDate] = @FilledDate
        WHERE [OrderID] = @OrderID;
        UPDATE [Sales].[Customer]
            SET YTDSales = YTDSales - @Delta
        WHERE [CustomerID] = @CustomerID;
        COMMIT TRANSACTION;
    END
    GO
    
    PRINT N'Creating Sales.uspNewCustomer...';
    GO
    
    CREATE PROCEDURE [Sales].[uspNewCustomer]
    @CustomerName NVARCHAR (40)
    AS
    BEGIN
        INSERT INTO [Sales].[Customer] (CustomerName)
        VALUES (@CustomerName);
        RETURN SCOPE_IDENTITY();
    END
    GO
    
    PRINT N'Creating Sales.uspPlaceNewOrder...';
    GO
    
    CREATE PROCEDURE [Sales].[uspPlaceNewOrder]
    @CustomerID INT, @Amount INT, @OrderDate DATETIME, @Status CHAR (1)='O'
    AS
    BEGIN
        DECLARE @RC AS INT;
        BEGIN TRANSACTION;
        INSERT INTO [Sales].[Orders] (CustomerID, OrderDate, FilledDate, Status, Amount)
        VALUES (@CustomerID, @OrderDate, NULL, @Status, @Amount);
        SELECT @RC = SCOPE_IDENTITY();
        UPDATE [Sales].[Customer]
            SET YTDOrders = YTDOrders + @Amount
        WHERE [CustomerID] = @CustomerID;
        COMMIT TRANSACTION;
        RETURN @RC;
    END
    GO
    
    CREATE PROCEDURE [Sales].[uspShowOrderDetails]
    @CustomerID INT=0
    AS
    BEGIN
        SELECT [C].[CustomerName],
               CONVERT (DATE, [O].[OrderDate]),
               CONVERT (DATE, [O].[FilledDate]),
               [O].[Status],
               [O].[Amount]
        FROM [Sales].[Customer] AS C
             INNER JOIN [Sales].[Orders] AS O
                 ON [O].[CustomerID] = [C].[CustomerID]
        WHERE [C].[CustomerID] = @CustomerID;
    END
    GO
    
  5. Guarde el archivo. Anote la ubicación porque debe usar este script en el procedimiento siguiente.

  6. En el menú Archivo , seleccione Cerrar solución.

    A continuación creará un proyecto de base de datos e importará el esquema desde el script que ha creado.

Crear un proyecto de base de datos e importar un esquema

Creación de un proyecto de base de datos

  1. En el menú Archivo , seleccione Nuevo y seleccione Proyecto.

    Aparecerá el cuadro de diálogo Nuevo proyecto .

  2. En Plantillas instaladas, seleccione el nodo SQL Server y, a continuación, Proyecto de base de datos de SQL Server.

  3. En Nombre, escriba SimpleUnitTestDB.

  4. Active la casilla Crear directorio para la solución si aún no está seleccionada.

  5. Desactive la casilla Agregar al control de código fuente si aún no está desactivada y seleccione Aceptar.

    Se crea el proyecto de base de datos, que aparece en el Explorador de soluciones. A continuación, importará el esquema de la base de datos de un script.

Importación de un esquema de base de datos desde un script

  1. En el menú Proyecto , seleccione Importar y, a continuación, Script (*.sql).

  2. Seleccione Siguiente después de leer la página principal.

  3. Seleccione Examinar y vaya al directorio donde guardó el .sql archivo.

  4. Haga doble clic en el .sql archivo y seleccione Finalizar.

    Se importa el script y los objetos definidos en el script se agregan al proyecto de base de datos.

  5. Revise el resumen y, a continuación, seleccione Finalizar para completar la operación.

    Nota

    El procedimiento Sales.uspFillOrder contiene un error de codificación intencionada que detecta y corrige más adelante en este procedimiento.

Examen del proyecto resultante

  1. En el Explorador de soluciones, examine los archivos de script que se importaron al proyecto.

  2. En el Explorador de objetos de , examine la base de datos del nodo Proyectos.

Implementación en LocalDB

De forma predeterminada, al presionar F5, se implementa (o publica) la base de datos en una base de datos localDB. Puede cambiar la ubicación de la base de datos si va a la pestaña Depurar de la página de propiedades del proyecto y cambia la cadena de conexión.

Crear pruebas unitarias de SQL Server

Creación de una prueba unitaria de SQL Server para los procedimientos almacenados

  1. En el Explorador de objetos de SQL Server, expanda el nodo proyectos para SimpleUnitTestDB y, a continuación, expanda Programación y, a continuación, el nodo Procedimientos almacenados .

  2. Haga clic con el botón derecho en uno de los procedimientos almacenados y seleccione Crear pruebas unitarias para mostrar el cuadro de diálogo Crear pruebas unitarias .

  3. Active las casillas de los cinco procedimientos almacenados: Sales.uspCancelOrder, Sales.uspFillOrder, Sales.uspNewCustomer, Sales.uspPlaceNewOrdery Sales.uspShowOrderDetails.

  4. En la lista desplegable Proyecto , seleccione Crear un nuevo proyecto de prueba de C#.

  5. Acepte los nombres predeterminados para el nombre del proyecto y el nombre de clase y seleccione Aceptar.

  6. En el cuadro de diálogo de configuración de pruebas, en Ejecutar pruebas unitarias usando la siguiente conexión de datos, especifique una conexión a la base de datos que implementó anteriormente en este tutorial. Por ejemplo, si usó la ubicación de implementación predeterminada, que es LocalDB, seleccionaría Nueva conexión especifique (LocalDB)\Projects. Después, elija el nombre de la base de datos. A continuación, seleccione Aceptar para cerrar el cuadro de diálogo Propiedades de conexión .

    Nota

    Si debe probar las vistas o los procedimientos almacenados que tienen permisos restringidos, especificaría normalmente esa conexión en este paso. Después debe especificar la conexión secundaria, con permisos más amplios, para validar la prueba. Si tiene una conexión secundaria, debe agregar ese usuario al proyecto de base de datos y crear un inicio de sesión para ese usuario en el script de implementación previa.

  7. En el cuadro de diálogo de configuración de pruebas, en la sección Implementación , active la casilla Implementar automáticamente el proyecto de base de datos antes de ejecutar pruebas unitarias .

  8. En Proyecto de base de datos, seleccione SimpleUnitTestDB.sqlproj.

  9. En Configuración de implementación, seleccione Depurar.

    Podría generar también datos de prueba como parte de las pruebas unitarias de SQL Server. En este tutorial, omitirá ese paso porque las pruebas crean sus propios datos.

  10. Selecciona Aceptar.

    Se compilará el proyecto de prueba y aparecerá el Diseñador de pruebas unitarias de SQL Server. A continuación, debes actualizar la lógica de las pruebas en el script Transact-SQL de las pruebas unitarias.

Definición de la lógica de prueba

Esta base de datos básica tiene dos tablas, Customer y Order. Actualiza la base de datos mediante los procedimientos almacenados siguientes:

Procedimiento almacenado Description
uspNewCustomer Este procedimiento almacenado agrega un registro a la tabla Customer, que establece las columnas YTDOrders y YTDSales del cliente en cero.
uspPlaceNewOrder Este procedimiento almacenado agrega un registro a la Orders tabla del cliente especificado y actualiza el YTDOrders valor en el registro correspondiente de la Customer tabla.
uspFillOrder Este procedimiento almacenado actualiza un registro de la Orders tabla cambiando el estado de "O" a "F" e incrementa la YTDSales cantidad en el registro correspondiente de la Customer tabla.
uspCancelOrder Este procedimiento almacenado actualiza un registro de la Orders tabla cambiando el estado de "O" a "X" y disminuye la YTDOrders cantidad en el registro correspondiente de la Customer tabla.
uspShowOrderDetails Este procedimiento almacenado combina la Orders tabla con la tabla Custom y muestra los registros de un cliente específico.

Nota

En este ejemplo se muestra cómo crear una prueba unitaria básica de SQL Server. En una base de datos del mundo real, podría sumar los importes totales de todos los pedidos con un estado 'O' o 'F' para un determinado cliente. Los procedimientos de este tutorial no contienen tampoco ningún control de errores. Por ejemplo, no impiden que llame uspFillOrder para un pedido que ya haya sido completado.

Las pruebas suponen que la base de datos se inicia en un estado limpio. Cree pruebas que comprueben las condiciones siguientes:

  • uspNewCustomer: compruebe que la Customer tabla contiene una fila después de ejecutar el procedimiento almacenado.

  • uspPlaceNewOrder: Para el cliente que tiene un CustomerID de 1, haga un pedido por $100. Compruebe que la YTDOrders cantidad de ese cliente es 100 y que la YTDSales cantidad es cero.

  • uspFillOrder: Para el cliente que tiene un CustomerID de 1, haga un pedido de 50 $. Rellene este pedido. Compruebe que los importes de YTDOrders y YTDSales son ambos 50.

  • uspShowOrderDetails: para el cliente que tiene un CustomerID de 1, realice pedidos por $100, $50 y $5. Compruebe que uspShowOrderDetails devuelve el número correcto de columnas y que el conjunto de resultados tiene la suma de comprobación esperada.

Nota

Para un conjunto completo de pruebas unitarias de SQL Server, se comprobaría normalmente que las demás columnas se establecieron correctamente. Para mantener este tutorial en un tamaño manejable, no describe cómo comprobar el comportamiento de uspCancelOrder.

Escribir la prueba unitaria de SQL Server para uspNewCustomer

  1. En la barra de navegación del Diseñador de pruebas unitarias de SQL Server, seleccione Sales_uspNewCustomerTest y asegúrese de que Test está resaltado en la lista adyacente.

    Después de realizar el paso anterior, puede crear el script de prueba para la acción de prueba en la prueba unitaria.

  2. Actualice las instrucciones Transact-SQL en el editor de Transact-SQL para que coincidan con las instrucciones siguientes:

    -- ssNoVersion unit test for Sales.uspNewCustomer
    DECLARE @RC AS INT, @CustomerName AS NVARCHAR (40);
    
    SELECT @RC = 0,
           @CustomerName = 'Fictitious Customer';
    
    EXECUTE
        @RC = [Sales].[uspNewCustomer]
        @CustomerName;
    
    SELECT *
    FROM [Sales].[Customer];
    
  3. En el panel Condiciones de prueba, seleccione la condición De prueba noclusiva y, a continuación, seleccione el icono Eliminar condición de prueba (la X roja).

  4. En el panel Condiciones de prueba , seleccione Recuento de filas en la lista y, a continuación, seleccione el icono Agregar condición de prueba (verde +).

  5. Abra la ventana Propiedades (seleccione la condición de prueba y presione F4) y establezca la propiedad Recuento de filas en 1.

  6. En el menú Archivo, seleccione Guardar todo.

    A continuación, defina la lógica de prueba unitaria para uspPlaceNewOrder.

Escribir la prueba unitaria de SQL Server para uspPlaceNewOrder

  1. En la barra de navegación del Diseñador de pruebas unitarias de SQL Server, seleccione Sales_uspPlaceNewOrderTest y asegúrese de que Test esté resaltado en la lista adyacente.

    Después de realizar este paso, puede crear el script de prueba para la acción de prueba en la prueba unitaria.

  2. Actualice las instrucciones Transact-SQL en el editor de Transact-SQL para que coincidan con las instrucciones siguientes:

    -- ssNoVersion unit test for Sales.uspPlaceNewOrder
    DECLARE @RC AS INT, @CustomerID AS INT, @Amount AS INT, @OrderDate AS DATETIME, @Status AS CHAR (1);
    
    DECLARE @CustomerName AS NVARCHAR (40);
    
    -- NOTE: Assumes that you inserted a Customer record with CustomerName='Fictitious Customer' in the pre-test script.
    SELECT @RC = 0,
           @CustomerID = 0,
           @CustomerName = N'Fictitious Customer',
           @Amount = 100,
           @OrderDate = getdate(),
           @Status = 'O';
    
    SELECT @CustomerID = [CustomerID]
    FROM [Sales].[Customer]
    WHERE [CustomerName] = @CustomerName;
    
    -- place an order for that customer
    EXECUTE
        @RC = [Sales].[uspPlaceNewOrder]
        @CustomerID,
        @Amount,
        @OrderDate,
        @Status;
    
    -- verify that the YTDOrders value is correct.
    SELECT @RC = [YTDOrders]
    FROM [Sales].[Customer]
    WHERE [CustomerID] = @CustomerID;
    
    SELECT @RC AS RC;
    
  3. En el panel Condiciones de prueba, seleccione la condición de prueba noclusiva y seleccione Eliminar condición de prueba.

  4. En el panel Condiciones de prueba , seleccione Valor escalar en la lista y, a continuación, seleccione Agregar condición de prueba.

  5. En la ventana Propiedades , establezca la propiedad Valor esperado en 100.

  6. En la barra de navegación del Diseñador de pruebas unitarias de SQL Server, seleccione Sales_uspPlaceNewOrderTest y asegúrese de que la prueba previa esté resaltada en la lista adyacente.

    Después de realizar este paso, puede especificar las instrucciones que ponen los datos en el estado necesario para ejecutar la prueba. En este ejemplo, primero debe crear el registro Customer antes de poder realizar un pedido.

  7. Seleccione Haga clic aquí para crear para crear un script de prueba previa.

  8. Actualice las instrucciones Transact-SQL en el editor de Transact-SQL para que coincidan con las instrucciones siguientes:

    /*
                                  Add Transact-SQL statements here that you want to run before
                                  the test script is run.
                                  */
    
    -- Add a customer for this test with the name 'Fictitious Customer'
    DECLARE @NewCustomerID AS INT, @CustomerID AS INT, @RC AS INT, @CustomerName AS NVARCHAR (40);
    
    SELECT @RC = 0,
           @NewCustomerID = 0,
           @CustomerID = 0,
           @CustomerName = N'Fictitious Customer';
    
    IF NOT EXISTS (SELECT *
                   FROM [Sales].[Customer]
                   WHERE CustomerName = @CustomerName)
        BEGIN
                    EXECUTE
                @NewCustomerID = [Sales].[uspNewCustomer]
                @CustomerName;
        END
    -- NOTE: Assumes that you inserted a Customer record with CustomerName='Fictitious Customer' in the pre-test script.
    
    SELECT @CustomerID = [CustomerID]
    FROM [Sales].[Customer]
    WHERE [CustomerName] = @CustomerName;
    -- delete any old records in the Orders table and clear out the YTD Sales/Orders fields
    
    DELETE [Sales].[Orders]
    WHERE [CustomerID] = @CustomerID;
    
    UPDATE [Sales].[Customer]
        SET YTDOrders = 0,
            YTDSales  = 0
    WHERE [CustomerID] = @CustomerID;
    
  9. En el menú Archivo, seleccione Guardar todo.

    A continuación, cree la prueba unitaria para uspFillOrder.

Escribir la prueba unitaria de SQL Server para uspFillOrder

  1. En la barra de navegación del Diseñador de pruebas unitarias de SQL Server, seleccione Sales_uspFillOrderTest y asegúrese de que Test está resaltado en la lista adyacente.

    Después de realizar este paso, puede crear el script de prueba para la acción de prueba en la prueba unitaria.

  2. Actualice las instrucciones Transact-SQL en el editor de Transact-SQL para que coincidan con las instrucciones siguientes:

    -- ssNoVersion unit test for Sales.uspFillOrder
    DECLARE @RC AS INT, @CustomerID AS INT, @Amount AS INT, @FilledDate AS DATETIME, @Status AS CHAR (1);
    
    DECLARE @CustomerName AS NVARCHAR (40), @OrderID AS INT;
    
    SELECT @RC = 0,
           @CustomerID = 0,
           @OrderID = 0,
           @CustomerName = N'Fictitious Customer',
           @Amount = 100,
           @FilledDate = getdate(),
           @Status = 'O';
    -- NOTE: Assumes that you inserted a Customer record with CustomerName='Fictitious Customer' in the pre-test script.
    
    SELECT @CustomerID = [CustomerID]
    FROM [Sales].[Customer]
    WHERE [CustomerName] = @CustomerName;
    -- Get the most recently added order.
    
    SELECT @OrderID = MAX([OrderID])
    FROM [Sales].[Orders]
    WHERE [CustomerID] = @CustomerID;
    -- fill an order for that customer
    
    EXECUTE
        @RC = [Sales].[uspFillOrder]
        @OrderID,
        @FilledDate;
    -- verify that the YTDOrders value is correct.
    
    SELECT @RC = [YTDSales]
    FROM [Sales].[Customer]
    WHERE [CustomerID] = @CustomerID;
    
    SELECT @RC AS RC;
    
  3. En el panel Condiciones de prueba, seleccione la condición de prueba noclusiva y seleccione Eliminar condición de prueba.

  4. En el panel Condiciones de prueba , seleccione Valor escalar en la lista y, a continuación, seleccione Agregar condición de prueba.

  5. En la ventana Propiedades , establezca la propiedad Valor esperado en 100.

  6. En la barra de navegación del Diseñador de pruebas unitarias de SQL Server, seleccione Sales_uspFillOrderTest y asegúrese de que la prueba previa esté resaltada en la lista adyacente. Después de realizar este paso, puede especificar las instrucciones que ponen los datos en el estado necesario para ejecutar la prueba. En este ejemplo, debe crear el registro Customer para poder hacer un pedido.

  7. Seleccione Haga clic aquí para crear para crear un script de prueba previa.

  8. Actualice las instrucciones Transact-SQL en el editor de Transact-SQL para que coincidan con las instrucciones siguientes:

    /*
                                  Add Transact-SQL statements here that you want to run before
                                  the test script is run.
                                  */
    BEGIN TRANSACTION
    -- Add a customer for this test with the name 'CustomerB'
    ;
    
    DECLARE @NewCustomerID AS INT, @RC AS INT, @CustomerName AS NVARCHAR (40);
    
    SELECT @RC = 0,
           @NewCustomerID = 0,
           @CustomerName = N'Fictitious Customer';
    
    IF NOT EXISTS (SELECT *
                   FROM [Sales].[Customer]
                   WHERE CustomerName = @CustomerName)
        BEGIN
                    EXECUTE
                @NewCustomerID = [Sales].[uspNewCustomer]
                @CustomerName;
        END
    
    DECLARE @CustomerID AS INT, @Amount AS INT, @OrderDate AS DATETIME, @Status AS CHAR (1);
    
    SELECT @RC = 0,
           @CustomerID = 0,
           @CustomerName = N'Fictitious Customer',
           @Amount = 100,
           @OrderDate = getdate(),
           @Status = 'O';
    -- NOTE: Assumes that you inserted a Customer record with CustomerName='Fictitious Customer' in the pre-test script.
    
    SELECT @CustomerID = [CustomerID]
    FROM [Sales].[Customer]
    WHERE [CustomerName] = @CustomerName;
    -- delete any old records in the Orders table and clear out the YTD Sales/Orders fields
    
    DELETE [Sales].[Orders]
    WHERE [CustomerID] = @CustomerID;
    
    UPDATE [Sales].[Customer]
        SET YTDOrders = 0,
            YTDSales  = 0
    WHERE [CustomerID] = @CustomerID;
    
    EXECUTE
        @RC = [Sales].[uspPlaceNewOrder]
        @CustomerID,
        @Amount,
        @OrderDate,
        @Status;
    
    COMMIT TRANSACTION;
    
    -- place an order for that customer
    
  9. En el menú Archivo, seleccione Guardar todo.

Escribir la prueba unitaria de SQL Server para uspShowOrderDetails

  1. En la barra de navegación del Diseñador de pruebas unitarias de SQL Server, seleccione Sales_uspShowOrderDetailsTest y asegúrese de que Test está resaltado en la lista adyacente.

    Después de realizar este paso, puede crear el script de prueba para la acción de prueba en la prueba unitaria.

  2. Actualice las instrucciones Transact-SQL en el editor de Transact-SQL para que coincidan con las instrucciones siguientes:

    -- ssNoVersion unit test for Sales.uspFillOrder
    DECLARE @RC AS INT, @CustomerID AS INT, @Amount AS INT, @FilledDate AS DATETIME, @Status AS CHAR (1);
    
    DECLARE @CustomerName AS NVARCHAR (40), @OrderID AS INT;
    
    SELECT @RC = 0,
           @CustomerID = 0,
           @OrderID = 0,
           @CustomerName = N'Fictitious Customer',
           @Amount = 100,
           @FilledDate = getdate(),
           @Status = 'O';
    -- NOTE: Assumes that you inserted a Customer record with CustomerName='Fictitious Customer' in the pre-test script.
    
    SELECT @CustomerID = [CustomerID]
    FROM [Sales].[Customer]
    WHERE [CustomerName] = @CustomerName;
    -- fill an order for that customer
    
    EXECUTE
        @RC = [Sales].[uspShowOrderDetails]
        @CustomerID;
    
    SELECT @RC AS RC;
    
  3. En el panel Condiciones de prueba, seleccione la condición de prueba noclusiva y seleccione Eliminar condición de prueba.

  4. En el panel Condiciones de prueba , seleccione Esquema esperado en la lista y, a continuación, seleccione Agregar condición de prueba.

  5. En la ventana Propiedades , en la propiedad Configuración , seleccione el botón Examinar ('...').

  6. En el cuadro de diálogo Configuración de expectedSchemaCondition1 , especifique una conexión a la base de datos. Por ejemplo, si usó la ubicación de implementación predeterminada, que es LocalDB, seleccionaría Nueva conexión especifique (LocalDB)\Projects. Después, elija el nombre de la base de datos.

  7. Seleccione Recuperar. (Si es necesario, seleccione Recuperar hasta que vea los datos).

    Se ejecuta el cuerpo de Transact-SQL de la prueba unitaria y el esquema resultante aparece en el cuadro de diálogo. Dado que no se ejecutó el código de prueba previa, no se devuelve ningún dato. Como solo está comprobando el esquema y no los datos, esto es correcto.

  8. Selecciona Aceptar.

    El esquema esperado se almacena con la condición de prueba.

  9. En la barra de navegación del Diseñador de pruebas unitarias de SQL Server, seleccione Sales_uspShowOrderDetailsTest y asegúrese de que la prueba previa esté resaltada en la lista adyacente. Después de realizar este paso, puede especificar las instrucciones que ponen los datos en el estado necesario para ejecutar la prueba. En este ejemplo, primero debe crear el registro Customer antes de poder realizar un pedido.

  10. Seleccione Haga clic aquí para crear para crear un script de prueba previa.

  11. Actualice las instrucciones Transact-SQL en el editor de Transact-SQL para que coincidan con las instrucciones siguientes:

    /*
                                  Add Transact-SQL statements here to run before the test script is run.
                                  */
    BEGIN TRANSACTION
    -- Add a customer for this test with the name 'FictitiousCustomer'
    ;
    
    DECLARE @NewCustomerID AS INT, @RC AS INT, @CustomerName AS NVARCHAR (40);
    
    SELECT @RC = 0,
           @NewCustomerID = 0,
           @CustomerName = N'Fictitious Customer';
    
    IF NOT EXISTS (SELECT *
                   FROM [Sales].[Customer]
                   WHERE CustomerName = @CustomerName)
        BEGIN
                    EXECUTE
                @NewCustomerID = [Sales].[uspNewCustomer]
                @CustomerName;
        END
    
    DECLARE @CustomerID AS INT, @Amount AS INT, @OrderDate AS DATETIME, @Status AS CHAR (1);
    
    SELECT @RC = 0,
           @CustomerID = 0,
           @CustomerName = N'Fictitious Customer',
           @OrderDate = getdate(),
           @Status = 'O';
    -- NOTE: Assumes that you inserted a Customer record with CustomerName='Fictitious Customer' in the pre-test script.
    
    SELECT @CustomerID = [CustomerID]
    FROM [Sales].[Customer]
    WHERE [CustomerName] = @CustomerName;
    -- delete any old records in the Orders table and clear out the YTD Sales/Orders fields
    
    DELETE [Sales].[Orders]
    WHERE [CustomerID] = @CustomerID;
    
    UPDATE [Sales].[Customer]
        SET YTDOrders = 0,
            YTDSales  = 0
    WHERE [CustomerID] = @CustomerID;
    
    EXECUTE
        @RC = [Sales].[uspPlaceNewOrder]
        @CustomerID, 100,
        @OrderDate,
        @Status;
    
    EXECUTE
        @RC = [Sales].[uspPlaceNewOrder]
        @CustomerID, 50,
        @OrderDate,
        @Status;
    
    EXECUTE
        @RC = [Sales].[uspPlaceNewOrder]
        @CustomerID, 5,
        @OrderDate,
        @Status;
    
    COMMIT TRANSACTION;
    
    -- place 3 orders for that customer
    
  12. En la barra de navegación del Diseñador de pruebas unitarias de SQL Server, seleccione Sales_uspShowOrderDetailsTest y seleccione Probar en la lista adyacente.

    Debe hacerlo porque desea aplicar la condición de suma de comprobación a la prueba, no a la acción anterior a la prueba.

  13. En el panel Condiciones de prueba , seleccione Suma de comprobación de datos en la lista y, a continuación, seleccione Agregar condición de prueba.

  14. En la ventana Propiedades , en la propiedad Configuración , seleccione el botón Examinar ('...').

  15. En el cuadro de diálogo Configuración de checksumCondition1 , especifique una conexión a la base de datos.

  16. Reemplace el código Transact-SQL del cuadro de diálogo (bajo el botón Editar conexión) por el código siguiente:

    BEGIN TRANSACTION
    -- Add a customer for this test with the name 'CustomerB'
    ;
    
    DECLARE @NewCustomerID AS INT, @RC AS INT, @CustomerName AS NVARCHAR (40);
    
    SELECT @RC = 0,
           @NewCustomerID = 0,
           @CustomerName = N'Fictitious Customer';
    
    IF NOT EXISTS (SELECT *
                   FROM [Sales].[Customer]
                   WHERE CustomerName = @CustomerName)
        BEGIN
                    EXECUTE
                @NewCustomerID = [Sales].[uspNewCustomer]
                @CustomerName;
        END
    
    DECLARE @CustomerID AS INT, @Amount AS INT, @OrderDate AS DATETIME, @Status AS CHAR (1);
    
    SELECT @RC = 0,
           @CustomerID = 0,
           @CustomerName = N'Fictitious Customer',
           @OrderDate = getdate(),
           @Status = 'O';
    -- NOTE: Assumes that you inserted a Customer record with CustomerName='Fictitious Customer' in the pre-test script.
    
    SELECT @CustomerID = [CustomerID]
    FROM [Sales].[Customer]
    WHERE [CustomerName] = @CustomerName;
    -- delete any old records in the Orders table and clear out the YTD Sales/Orders fields
    
    DELETE [Sales].[Orders]
    WHERE [CustomerID] = @CustomerID;
    
    UPDATE [Sales].[Customer]
        SET YTDOrders = 0,
            YTDSales  = 0
    WHERE [CustomerID] = @CustomerID;
    
    EXECUTE
        @RC = [Sales].[uspPlaceNewOrder]
        @CustomerID, 100,
        @OrderDate,
        @Status;
    
    EXECUTE
        @RC = [Sales].[uspPlaceNewOrder]
        @CustomerID, 50,
        @OrderDate,
        @Status;
    
    EXECUTE
        @RC = [Sales].[uspPlaceNewOrder]
        @CustomerID, 5,
        @OrderDate,
        @Status;
    
    COMMIT TRANSACTION;
    
    DECLARE @FilledDate AS DATETIME;
    
    DECLARE @OrderID AS INT;
    
    SELECT @RC = 0,
           @CustomerID = 0,
           @OrderID = 0,
           @CustomerName = N'Fictitious Customer',
           @Amount = 100,
           @FilledDate = getdate(),
           @Status = 'O';
    
    SELECT @CustomerID = [CustomerID]
    FROM [Sales].[Customer]
    WHERE [CustomerName] = @CustomerName;
    
    EXECUTE
        @RC = [Sales].[uspShowOrderDetails]
        @CustomerID;
    
    SELECT @RC AS RC;
    
    -- place 3 orders for that customer  -- ssNoVersion unit test for Sales.uspFillOrder  -- NOTE: Assumes that you inserted a Customer record with CustomerName='Fictitious Customer' in the pre-test script.  -- fill an order for that customer
    

    Este código combina el código Transact-SQL anterior a la prueba con el Transact-SQL de la propia prueba. Debe hacer que ambos devuelvan los mismos resultados que devuelve la prueba al ejecutarla.

  17. Seleccione Recuperar. (Si es necesario, seleccione Recuperar hasta que vea los datos).

    Se ejecuta el código Transact-SQL especificado y se calcula una suma de comprobación para los datos devueltos.

  18. Selecciona Aceptar.

    La suma de comprobación calculada se almacena con la condición de prueba. La suma de comprobación esperada aparece en la columna Valor de la condición de prueba Suma de comprobación de datos.

  19. En el menú Archivo, seleccione Guardar todo.

    En este momento, está listo para ejecutar las pruebas.

Ejecución de pruebas unitarias de SQL Server

Ejecución de las pruebas unitarias de SQL Server

  1. En el menú Probar , seleccione Windows y, a continuación, seleccione Vista de prueba en Visual Studio 2010 o Explorador de pruebas en Visual Studio 2012.

  2. En la ventana Vista de prueba (Visual Studio 2010), seleccione Actualizar en la barra de herramientas para actualizar la lista de pruebas. Para ver la lista de pruebas en el Explorador de pruebas (Visual Studio 2012), compile la solución.

    En la ventana Vista de pruebas o Explorador de pruebas se muestran las pruebas que creó anteriormente en este tutorial y a las que agregó las instrucciones y las condiciones de prueba de Transact-SQL. La prueba denominada TestMethod1 está vacía y no se usa en este tutorial.

  3. Haga clic con el botón derecho en Sales_uspNewCustomerTest y seleccione Ejecutar selección.

    Visual Studio utiliza el contexto privilegiado que especificó para conectarse a la base de datos y aplicar el plan de generación de datos. Visual Studio se activa en el contexto de ejecución antes de ejecutar el script Transact-SQL en la prueba. Finalmente, Visual Studio evalúa los resultados del script Transact-SQL con los especificados en la condición de prueba, y aparece un resultado de correcto o error en la ventana Resultados de las pruebas.

  4. Vea el resultado en la ventana Resultados de pruebas .

    La prueba ha pasado, lo que significa que la SELECT instrucción devuelve una fila cuando se ejecuta.

  5. Repita el paso 3 para las Sales_uspPlaceNewOrderTest, Sales_uspFillOrderTest y Sales_uspShowOrderDetailsTest pruebas. Los resultados deberían ser los siguientes:

    Prueba Resultado previsto
    Sales_uspPlaceNewOrderTest Pass (pasado)
    Sales_uspShowOrderDetailsTest Pass (pasado)
    Sales_uspFillOrderTest Se produce el siguiente error: ScalarValueCondition Condition (scalarValueCondition2) Failed: ResultSet 1 Row 1 Column 1: values do not match, actual '-100' expected '100'. este error se produce porque la definición del procedimiento almacenado contiene un error menor.

    A continuación, corrija el error y vuelva a ejecutar la prueba.

Corrección del error en Sales.uspFillOrder

  1. En el nodo Proyectos del Explorador de objetos de SQL Server correspondiente a la base de datos, haga doble clic en el procedimiento almacenado uspFillOrder para abrir su definición en el editor de Transact-SQL.

  2. En la definición, busque la siguiente instrucción Transact-SQL:

    UPDATE [Sales].[Customer]
        SET YTDSales = YTDSales - @Delta
    WHERE [CustomerID] = @CustomerID;
    
  3. Cambie la cláusula SET de la instrucción para que coincida con la siguiente instrucción:

    UPDATE [Sales].[Customer]
        SET YTDSales = YTDSales + @Delta
    WHERE [CustomerID] = @CustomerID;
    
  4. En el menú Archivo , seleccione Guardar uspFillOrder.sql.

  5. En la Vista de prueba, haga clic con el botón derecho en Sales_uspFillOrderTest y seleccione Ejecutar selección.

    Se supera la prueba.

Agregar una prueba unitaria negativa

Puede crear una prueba negativa para comprobar que una prueba genera un error cuando debe dar error. Por ejemplo, si intenta cancelar un pedido que ya estaba rellenado, la prueba debe generar un error. En esta parte del tutorial, se crea una prueba unitaria negativa para el procedimiento almacenado Sales.uspCancelOrder.

Para crear y comprobar una prueba negativa, debe realizar las siguientes tareas:

  • Actualizar el procedimiento almacenado para probar las condiciones de error

  • Definir una nueva prueba unitaria

  • Modificar el código de la prueba unitaria para indicar que se espera un error

  • Ejecutar la prueba unitaria

Actualización del procedimiento almacenado

  1. En el nodo Proyectos del Explorador de objetos de SQL Server para la SimpleUnitTestDB base de datos, expanda el nodo Programación, expanda el nodo Procedimientos almacenados y haga doble clic en uspCancelOrder.

  2. En el editor de Transact-SQL, actualice la definición del procedimiento para que coincida con el código siguiente:

    CREATE PROCEDURE [Sales].[uspCancelOrder]
    @OrderID INT
    AS
    BEGIN
        DECLARE @Delta AS INT, @CustomerID AS INT, @PriorStatus AS CHAR (1);
        BEGIN TRANSACTION;
        BEGIN TRY
            IF (NOT EXISTS (SELECT [CustomerID]
                            FROM [Sales].[Orders]
                            WHERE [OrderID] = @OrderID))
                BEGIN
    -- Specify WITH LOG option so that the error is
    -- written to the application log.
                    RAISERROR ('That order does not exist.',
    -- Message text   16,
    -- severity   1
    -- state
    )
                        WITH LOG;
                END
            SELECT @Delta = [Amount],
                   @CustomerID = [CustomerID],
                   @PriorStatus = [Status]
            FROM [Sales].[Orders]
            WHERE [OrderID] = @OrderID;
            IF @PriorStatus <> 'O'
                BEGIN
    -- Specify WITH LOG option so that the error is
    -- written to the application log.
                    RAISERROR ('You can only cancel open orders.',
    -- Message text   16,
    -- Severity   1
    -- State
    )
                        WITH LOG;
                END
            ELSE
                BEGIN
    -- If we make it to here, then we can cancel the order. Update the status to 'X' first...
                    UPDATE [Sales].[Orders]
                        SET [Status] = 'X'
                    WHERE [OrderID] = @OrderID
    -- and then remove the amount from the YTDOrders for the customer
    ;
                    UPDATE [Sales].[Customer]
                        SET YTDOrders = YTDOrders - @Delta
                    WHERE [CustomerID] = @CustomerID;
                    COMMIT TRANSACTION;
                    RETURN 1;
    -- indicate success
                END
        END TRY
        BEGIN CATCH
            DECLARE @ErrorMessage AS NVARCHAR (4000);
            DECLARE @ErrorSeverity AS INT;
            DECLARE @ErrorState AS INT;
            SELECT @ErrorMessage = ERROR_MESSAGE(),
                   @ErrorSeverity = ERROR_SEVERITY(),
                   @ErrorState = ERROR_STATE();
            ROLLBACK;
            RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
            RETURN 0;
        END CATCH
    END
    
    -- Use RAISERROR inside the CATCH block to return  -- error information about the original error that  -- caused execution to jump to the CATCH block.  -- Message text  -- Severity  -- State  -- indicate failure
    
  3. En el menú Archivo , seleccione Guardar uspCancelOrder.sql.

  4. Presione F5 para implementar SimpleUnitTestDB.

    Implementas las actualizaciones en el uspCancelOrder procedimiento almacenado. No cambió ningún otro objeto, tan solo ha actualizado el procedimiento almacenado.

    A continuación definirá la prueba unitaria asociada para este procedimiento.

Escribir la prueba unitaria de SQL Server para uspCancelOrder

  1. En la barra de navegación del Diseñador de pruebas unitarias de SQL Server, seleccione Sales_uspCancelOrderTest y asegúrese de que Test está resaltado en la lista adyacente.

    Después de realizar este paso, puede crear el script de prueba para la acción de prueba en la prueba unitaria.

  2. Actualice las instrucciones Transact-SQL en el editor de Transact-SQL para que coincidan con las instrucciones siguientes:

    -- ssNoVersion unit test for Sales.uspFillOrder
    DECLARE @RC AS INT, @CustomerID AS INT, @Amount AS INT, @FilledDate AS DATETIME, @Status AS CHAR (1);
    
    DECLARE @CustomerName AS NVARCHAR (40), @OrderID AS INT;
    
    SELECT @RC = 0,
           @CustomerID = 0,
           @OrderID = 0,
           @CustomerName = N'Fictitious Customer',
           @Amount = 100,
           @FilledDate = getdate(),
           @Status = 'O';
    -- NOTE: Assumes that you inserted a Customer record with CustomerName='Fictitious Customer' in the pre-test script.
    
    SELECT @CustomerID = [CustomerID]
    FROM [Sales].[Customer]
    WHERE [CustomerName] = @CustomerName;
    -- Get the most recently added order.
    
    SELECT @OrderID = MAX([OrderID])
    FROM [Sales].[Orders]
    WHERE [CustomerID] = @CustomerID;
    -- try to cancel an order for that customer that has already been filled
    
    EXECUTE
        @RC = [Sales].[uspCancelOrder]
        @OrderID;
    
    SELECT @RC AS RC;
    
  3. En el panel Condiciones de prueba, seleccione la condición de prueba Inconclusa y seleccione el icono Eliminar Condición de Prueba.

  4. En el panel Condiciones de prueba , seleccione Valor escalar en la lista y, a continuación, seleccione el icono Agregar condición de prueba .

  5. En la ventana Propiedades , establezca la propiedad Valor esperado en 0.

  6. En la barra de navegación del Diseñador de pruebas unitarias de SQL Server, seleccione Sales_uspCancelOrderTest y asegúrese de que la prueba previa esté resaltada en la lista adyacente. Después de realizar este paso, puede especificar las instrucciones que ponen los datos en el estado necesario para ejecutar la prueba. En este ejemplo, primero debe crear el registro Customer antes de poder realizar un pedido.

  7. Seleccione Haga clic aquí para crear para crear un script de prueba previa.

  8. Actualice las instrucciones Transact-SQL en el editor de Transact-SQL para que coincidan con las instrucciones siguientes:

    /*
                                  Add Transact-SQL statements here to run before the test script is run.
                                  */
    BEGIN TRANSACTION
    -- Add a customer for this test with the name 'CustomerB'
    ;
    
    DECLARE @NewCustomerID AS INT, @RC AS INT, @CustomerName AS NVARCHAR (40);
    
    SELECT @RC = 0,
           @NewCustomerID = 0,
           @CustomerName = N'Fictitious Customer';
    
    IF NOT EXISTS (SELECT *
                   FROM [Sales].[Customer]
                   WHERE CustomerName = @CustomerName)
        BEGIN
                    EXECUTE
                @NewCustomerID = [Sales].[uspNewCustomer]
                @CustomerName;
        END
    
    DECLARE @CustomerID AS INT, @Amount AS INT, @OrderDate AS DATETIME, @FilledDate AS DATETIME, @Status AS CHAR (1), @OrderID AS INT;
    
    SELECT @RC = 0,
           @CustomerID = 0,
           @OrderID = 0,
           @CustomerName = N'Fictitious Customer',
           @Amount = 100,
           @OrderDate = getdate(),
           @FilledDate = getdate(),
           @Status = 'O';
    -- NOTE: Assumes that you inserted a Customer record with CustomerName='Fictitious Customer' in the pre-test script.
    
    SELECT @CustomerID = [CustomerID]
    FROM [Sales].[Customer]
    WHERE [CustomerName] = @CustomerName;
    -- delete any old records in the Orders table and clear out the YTD Sales/Orders fields
    
    DELETE [Sales].[Orders]
    WHERE [CustomerID] = @CustomerID;
    
    UPDATE [Sales].[Customer]
        SET YTDOrders = 0,
            YTDSales  = 0
    WHERE [CustomerID] = @CustomerID;
    
    EXECUTE
        @OrderID = [Sales].[uspPlaceNewOrder]
        @CustomerID,
        @Amount,
        @OrderDate,
        @Status;
    
    EXECUTE
        @RC = [Sales].[uspFillOrder]
        @OrderID,
        @FilledDate;
    
    COMMIT TRANSACTION;
    
    -- place an order for that customer  -- fill the order for that customer
    
  9. En el menú Archivo, seleccione Guardar todo.

    En este momento, está listo para ejecutar las pruebas.

Ejecución de las pruebas unitarias de SQL Server

  1. En Vista de Prueba, haga clic con el botón derecho en Sales_uspCancelOrderTest, y seleccione Ejecutar selección.

  2. Vea el resultado en la ventana Resultados de pruebas .

    La prueba genera un error y se muestra el siguiente mensaje de error:

    Test method TestProject1.SqlServerUnitTests1.Sales_uspCancelOrderTest threw exception: System.Data.SqlClient.SqlException: You can only cancel open orders.
    

    A continuación, modifique el código para indicar que se espera la excepción.

Modificación del código de la prueba unitaria

  1. En el Explorador de soluciones, expanda TestProject1, haga clic con el botón derecho en SqlServerUnitTests1.cs y seleccione Ver código.

  2. En el editor de código, navegue al método Sales_uspCancelOrderTest. Modifique los atributos del método para que coincidan con el código siguiente:

    [TestMethod(), ExpectedSqlException(Severity=16, MatchFirstError=false, State=1)]
    public void Sales_uspCancelOrderTest()
    

    Especifique que se espera ver una excepción concreta. Opcionalmente, puede especificar un número de error concreto. Si no agrega este atributo, se produce un error en la prueba unitaria y aparece un mensaje en la ventana Resultados de pruebas.

  3. En el menú Archivo, seleccione Guardar SqlServerUnitTests1.cs.

    A continuación, vuelva a ejecutar su prueba unitaria para verificar que falla según lo esperado.

Volver a ejecutar las pruebas unitarias de SQL Server

  1. En Vista de Prueba, haga clic con el botón derecho en Sales_uspCancelOrderTest, y seleccione Ejecutar selección.

  2. Vea el resultado en la ventana Resultados de pruebas .

    La prueba se supera, lo que significa que se produjo un error en el procedimiento cuando se suponía que se debía producir.