tSQLt - Database Unit Testing for SQL Server

Database Unit Testing for SQL Server

  • Home
  • Docs
    • Documents
    • Quick Start
    • Articles
  • Training
  • Downloads
tSQLt » dennis » Page 5

Integrating tSQLt with Cruise Control

05.23.2010 by dennis // Leave a Comment

tSQLt test cases can be executed and included in the results of your continuous integration build. This section describes how to integrate tSQLt test results with the popular continuous integration tool, CruiseControl.

CruiseControl executes your build script on a schedule or when code is checked-in to the version control repository. It reports build errors automatically and can include test results. For this discussion, we’ll setup a build in Ant, although other builders can be used.

We want our build to perform the following steps:
1. Create the database which we are testing. It should include the creation of the tables, procedures and other objects.
2. Install tSQLt to the database.
3. Load our tSQLt unit tests into the database.
4. Execute the tests.
5. Get the results from the test cases and store them in a file.

Setting up the build
First lets tell CruiseControl about the build script we will create. After installing CruiseControl, you will find a config.xml in the installation folder. This config file includes your projects (CruiseControl includes a sample project called Connect Four). We’re going to create our own project:

<project name="MyDatabaseProject">
    <listeners>
        <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
    </listeners>

    <modificationset quietperiod="30">
        <filesystem folder="C:/projects/${project.name}"/>
    </modificationset>

    <schedule interval="300">
        <ant anthome="apache-ant-1.7.0" buildfile="c:/projects/${project.name}/build/build.xml">
            <property name="db.server" value="localhost"/>
            <property name="db.name" value="MyUnitTestDatabase"/>
        </ant>
    </schedule>
</project>

This simple build file executes a build every 5 minutes by calling the Ant script stored at c:/projects/MyDatabaseProject/build/build.xml. We are passing two properties to the Ant script: the server and database name which we will create and use to execute the tests.

The Build Script
Now, we’ll create the build script in c:/projects/MyDatabaseProject/build/build.xml. Here is a sample which completes all of the desired steps:

<project name="tSQLt.sourceforge" default="all">
    <target name="all" depends="db.recreate, db.tsqlt.install, db.tests.install, db.tests.run, db.tests.output, db.tests.check.results"/>

    <target name="db.recreate">
        <exec executable="cmd" failonerror="true">
            <arg value="/c"/>
            <arg value="sqlcmd -S ${db.server} -E -I -Q &quot;IF EXISTS(SELECT 1 FROM sys.databases WHERE name='${db.name}') DROP DATABASE ${db.name}; CREATE DATABASE ${db.name};&quot;"/>
            <arg value="sqlcmd -S ${db.server} -E -I -i &quot;CreateSchema.sql&quot;"/>
        </exec>
    </target>

    <target name="db.tsqlt.install">
        <exec executable="cmd" failonerror="true">
            <arg value="/c"/>
            <arg value="sqlcmd -S ${db.server} -d ${db.name} -I -i &quot;test/tSQLt.class.sql&quot;"/>
        </exec>
    </target>

    <target name="db.tests.install">
        <exec executable="cmd" failonerror="true">
            <arg value="/c"/>
            <arg value="sqlcmd -S ${db.server} -d ${db.name} -I -i &quot;test/TestCases.sql&quot;"/>
        </exec>
    </target>

    <target name="db.tests.run">
        <exec executable="cmd" failonerror="true">
            <arg value="/c"/>
            <arg value="sqlcmd -S ${db.server} -d ${db.name} -I -Q &quot;EXEC tSQLt.RunAll;&quot;"/>
        </exec>
    </target>

    <target name="db.tests.output">
        <exec executable="cmd" failonerror="true">
            <arg value="/c"/>
            <arg value="sqlcmd -S ${db.server} -d ${db.name} -h-1 -y0 -I -i &quot;test/GetTestResults.sql&quot; -o &quot;test/results/TestResults.xml&quot;"/>
        </exec>
    </target>

    <target name="db.tests.check.results">
        <exec executable="cmd" failonerror="true">
            <arg value="/c"/>
            <arg value="sqlcmd  -S ${db.server} -d ${db.name} -h-1 -y0 -I -Q &quot;:EXIT(SELECT COUNT(*) FROM tSQLt.TestResult WHERE Result != 'Success')&quot;"/>
        </exec>
    </target>
</project>

Details on each section of the build script
db.recreate: In this section we are dropping and recreating the database. Then we are running the script which populates your database objects, CreateSchema.sql. All file locations are relative to the build folder, however you can enter any paths you wish.

db.tsqlt.install: This section installs tSQLt to your test database.

db.tests.install: Here we put your test cases into the database from the test/TestCases.sql file.

db.tests.run: tSQLt.RunAll executes all of the tests. See Creating and Running Test Cases in tSQLt for other options on running test cases.

db.tests.output: Queries the tSQLt.TestResult table in XML format and stores the results in test/results/TestResults.xml. Here is an example of GetTestResults.sql script which could be used here:

:XML ON
EXEC [tSQLt].[XmlResultFormatter];

Note that the :XML ON command used here is a special sqlcmd directive which allows long XML strings to be output. tSQLt.XmlResultFormatter retrieves the test results as an XML document compatible with CruiseControl.

db.tests.check.results: This last step in the build, causes the build to fail if any test cases have failed or caused an error.

Merging the Test Case Results
Finally, we’ll go back to the config.xml in the CruiseControl installation folder. We need to add a log element to our config script. The log element merges the output of the test results with the CruiseControl log. This is our final project configuration in config.xml:

<project name="MyDatabaseProject">
    <listeners>
        <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
    </listeners>

    <modificationset quietperiod="30">
        <filesystem folder="C:/projects/${project.name}"/>
    </modificationset>

    <schedule interval="300">
        <ant anthome="apache-ant-1.7.0" buildfile="c:/projects/${project.name}/build/build.xml">
            <property name="db.server" value="localhost"/>
            <property name="db.name" value="MyUnitTestDatabase"/>
        </ant>
    </schedule>

    <log>
        <merge dir="c:/projects/${project.name}/build/test/results"/>
    </log>
</project>

Summary
Automating your build process using a tool such as CruiseControl to execute your tests can provide you with constant feedback on your development. This section has demonstrated a very simple way of configuring CruiseControl to work with tSQLt. Your actual build script is likely to also include steps to compile business logic code written in another logic and execute other types of test cases. Having access to your database level tests in your build process is important to maintaining database quality.

 

Share and Enjoy:
  • FacebookFacebook
  • TwitterTwitter
  • LinkedInLinkedIn
  • RedditReddit
  • StumbleUponStumbleUpon
  • TechnoratiTechnorati
  • PrintPrint

Categories // Articles

Using tSQLt.ResultSetFilter

05.23.2010 by dennis // 10 Comments

Overview
The ResultSetFilter procedure provides the ability to retrieve a single result set from a statement which produces multiple result sets. SQL Server comes installed with many stored procedures which return multiple result sets, such as sp_monitor, sp_spaceused and sp_help (when used with certain parameters). It is also common that developers will want to write their own stored procedures which return multiple result sets.

Examples
The most common need to use ResultSetFilter is when you want to capture a specific result set for further processing by another stored procedure. Supposed for example, you wanted to process the data from the second result set of sp_spaceused. This result set contains information on how reserved space in the database is utilized (for data, indexes and unused reserved space).

First we’ll create a table to store the second result set, and then we’ll populate it using the ResultSetFilter. The number 2 that we pass as the first parameter to ResultSetFilter tells us that we want the second result set returned from the stored procedure.

CREATE TABLE #ReservedSpaceUsed (
    reserved VARCHAR(100),
    data VARCHAR(100),
    index_size VARCHAR(100),
    unused VARCHAR(100)
);

INSERT INTO #ReservedSpaceUsed
EXEC tSQLt.ResultSetFilter 2, 'EXEC sp_spaceused';

SELECT * FROM #ReservedSpaceUsed;

Implications to Testing with tSQLt
When you are testing a stored procedure which returns multiple result sets, you will want to use ResultSetFilter to choose an individual result set and store it in a table. The results can then be used with tSQLt.AssertEqualsTable (see Example 3 in the tSQLt Tutorial).

Limitations
Each time you call ResultSetFilter, the procedure you pass as a command is executed. For example, suppose you want to capture both result sets from sp_spaceused with ResultSetFilter:

CREATE TABLE #DatabaseSize (
    database_name nvarchar(128),
    database_size varchar(18),
    unallocated_space varchar(18)
);

CREATE TABLE #ReservedSpaceUsed (
    reserved VARCHAR(18),
    data VARCHAR(18),
    index_size VARCHAR(18),
    unused VARCHAR(18)
);

INSERT INTO #DatabaseSize
EXEC tSQLt.ResultSetFilter 1, 'EXEC sp_spaceused';

INSERT INTO #ReservedSpaceUsed
EXEC tSQLt.ResultSetFilter 2, 'EXEC sp_spaceused';

SELECT * FROM #DatabaseSize;
SELECT * FROM #ReservedSpaceUsed;

Since the procedure is executed twice, it is possible that the size of the database has changed between each call and the two results are no longer in sync. This has a greater impact if you are testing a procedure which causes a state change (changing the data or schema of the database) or the data is time-sensitive.

Summary
tSQLt.ResultSetFilter provide the ability to choose a single result set from a stored procedure which returns multiple result sets. This allows test cases to be written for this type of stored procedure.

Share and Enjoy:
  • FacebookFacebook
  • TwitterTwitter
  • LinkedInLinkedIn
  • RedditReddit
  • StumbleUponStumbleUpon
  • TechnoratiTechnorati
  • PrintPrint

Categories // Articles

tSQLt build.7 Release Notes

05.23.2010 by dennis // Leave a Comment

IMPORTANT: tSQLt now utilizes CLR (Common Language Runtime) stored procedures. In order to install tSQLt, CLRs must be enabled in SQL Server. The SetClrEnabled.sql file has the command which enables CLRs. If CLRs are not already enabled, this command must be executed before installing tSQLt.

New Features:

  1. A new procedure tSQLt.RunAll, executes all test classes created with the tSQLt.NewTestClass procedure. For examples, see Creating and Running Test Cases in tSQLt
  2. Added procedure tSQLt.AssertResultSetsHaveSameMetaData which allows the meta data of two result sets to be compared. This compares several properties of each column of the result set including the column name, data type, length, precision, scale and other properties.
  3. Added procedure tSQLt.ResultSetFilter which returns a single result set from a statement which produces multiple result sets. For example, you want to test a stored procedure which executes several select statements. You can now use ResultSetFilter to choose which result set to emit, and therefore you can capture that result set into a table for use with tSQLt.AssertEqualsTable. For examples, see Using tSQLt.ResultsetFilter
  4. The results of running tests can now be output in an XML format. After calling one of the tSQLt.Run… procedures to execute your test cases, you can call tSQLt.XmlResultFormatter to display the results in XML. The format is compatible with CruiseControl and can be merged into a build log the same way that a JUnit test report is merged. See Integrating tSQLt with Cruise Control for more information.
Share and Enjoy:
  • FacebookFacebook
  • TwitterTwitter
  • LinkedInLinkedIn
  • RedditReddit
  • StumbleUponStumbleUpon
  • TechnoratiTechnorati
  • PrintPrint

Categories // Release Notes

  • « Previous Page
  • 1
  • …
  • 3
  • 4
  • 5
  • 6
  • Next Page »

Navigation

  • Join the conversation
  • Downloads
  • New Logo
  • Sponsors & Contributors
  • Release Notes
  • Articles
  • Training
  • How to get more out of tSQLt
  • Why you should use the tSQLt framework
  • Why you should unit test SQL Server Code
  • Full user guide
  • Documents
    • Quick Start
    • tSQLt Tutorial
    • tSQLt Keyboard Shortcuts
    • Test Creation and Execution
      • NewTestClass
      • DropClass
      • RunAll
      • Run
      • RenameClass
    • Assertions
      • AssertEmptyTable
      • AssertNotEquals
      • AssertObjectDoesNotExist
      • AssertEqualsTableSchema
      • AssertEquals
      • AssertEqualsString
      • AssertEqualsTable
      • AssertObjectExists
      • AssertResultSetsHaveSameMetaData
      • Fail
      • AssertLike
    • Expectations
      • ExpectException
      • ExpectNoException
    • Isolating Dependencies
      • FakeFunction
      • RemoveObjectIfExists
      • ApplyConstraint
      • SpyProcedure
      • FakeTable
      • ApplyTrigger
      • RemoveObject

Links

  • tSQLt on GitHub
  • tSQLt Mailing List
  • twitter hashtag (#tsqlt)
  • tSQLt tag on stackoverflow.com
  • SQL Server Community on Slack (#tsqlt)
  • #tSQLtLive on YouTube

Sponsors

sqlity.net
redgate.com

A sqlity.net llc Web Property. | ©2010 - 2020, All Rights Reserved. | Privacy Policy | Terms of Use