<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>SSIS Junkie : sql server, Datadude, unit testing</title><link>http://sqlblog.com/blogs/jamie_thomson/archive/tags/sql+server/Datadude/unit+testing/default.aspx</link><description>Tags: sql server, Datadude, unit testing</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Enforcing naming conventions using database unit testing</title><link>http://sqlblog.com/blogs/jamie_thomson/archive/2010/10/06/enforcing-naming-conventions-using-database-unit-testing.aspx</link><pubDate>Tue, 05 Oct 2010 22:42:17 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:29199</guid><dc:creator>jamiet</dc:creator><slash:comments>6</slash:comments><comments>http://sqlblog.com/blogs/jamie_thomson/comments/29199.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/jamie_thomson/commentrss.aspx?PostID=29199</wfw:commentRss><wfw:comment>http://sqlblog.com/blogs/jamie_thomson/rsscomments.aspx?PostID=29199</wfw:comment><description>&lt;h3&gt;My naming convention obsession&lt;/h3&gt;  &lt;p&gt;Anyone that has ever worked with me will tell you that I am a stickler for naming conventions. I have a somewhat obsessive reputation for it; I can’t help it – I seem to have a deep seated uncontrollable desire to ensure that every object in my database(s) is/are named consistently (is there anyone else out there equally as obsessive?). &lt;/p&gt;  &lt;p&gt;I have tried various techniques down the years to try and enforce naming conventions but none of them really worked. I’ve got scripts that alter object names (such a script is in my &lt;a href="http://sqlblog.com/blogs/jamie_thomson/archive/2010/10/03/take-your-script-library-with-you-t-sql.aspx" target="_blank"&gt;script library&lt;/a&gt; in fact) but these are only any use if they actually get run, they don’t actually &lt;em&gt;enforce &lt;/em&gt;the conventions – that’s a manual step. I’ve thought about using Policy-Based Management (PBM) to enforce naming conventions but given I’m a developer and not a DBA that’s not something that is readily available to me and besides, using PBM to enforce naming conventions is reactive rather than proactive if you are developing the code on a machine where the policies are not enforced.&lt;/p&gt;  &lt;p&gt;Another option I looked into using was Team Foundation Server (TFS) check-in policies; these are policies that can be applied to artefacts when they get checked-in to TFS’s source control system. This option really appealed to me because the naming conventions could be enforced during check-in (i.e. very very early) and didn’t require DBA intervention. In practice though enforcing naming conventions using TFS check-in policies has a few sizable issues:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Its not easy. It would require you to parse the file that was getting checked-in, decide what sort of object is defined in the file, and then check the name of the object based on things like object name, schema, etc... &lt;/li&gt;    &lt;li&gt;TFS check-in policies are not installed on the TFS server, they are installed on the development workstations. This means there is a dependency and, even though the source code for the check-in policies can be distributed with your application source code, I didn’t really like this. &lt;/li&gt;    &lt;li&gt;You’re relying on each developer to enforce the check-in policy and with the greatest will in the world….that aint gonna happen. Its too easy to turn them off. &lt;/li&gt;    &lt;li&gt;There is the obvious dependency on using TFS, not something every development shop uses even in the Microsoft space. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Database unit testing to the rescue&lt;/h3&gt;  &lt;p&gt;No, a better solution was needed and I came up with one in the shape of automated database unit testing. I have spoken recently about how I have become a big fan of database unit testing (see my post &lt;a href="http://sqlblog.com/blogs/jamie_thomson/archive/2010/09/18/experiences-from-writing-sp-cascadingdataviewer-db-unit-testing-and-code-distribution.aspx" target="_blank"&gt;Experiences from writing sp_CascadingDataViewer – DB unit testing and code distribution&lt;/a&gt;) and being able to enforce naming conventions is one very good reason for that. Enforcing naming conventions using automated unit tests has a number of advantages:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;They can be written against the metadata of the objects themselves (i.e. by querying SQL Server’s system views) so there’s no parsing that needs to be done. &lt;/li&gt;    &lt;li&gt;They can be employed as part of a Continuous Integration (CI) process and run as a build verification test (BVT). Someone checks-in an object that violates the naming convention? Bang: broken build! &lt;/li&gt;    &lt;li&gt;Developers can’t circumvent the tests. &lt;/li&gt;    &lt;li&gt;Nothing needs to be installed on the development workstations. The tests live wholly as part of your source code. &lt;/li&gt;    &lt;li&gt;Not dependent on use of a particular source control system &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Hence I have written some unit tests that enforce the following naming conventions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Check constraints must be of the form CK_&amp;lt;schemaName&amp;gt;&amp;lt;tableName&amp;gt;_XXX &lt;/li&gt;    &lt;li&gt;Column names must begin with a capital letter &lt;/li&gt;    &lt;li&gt;Column names cannot contain underscores &lt;/li&gt;    &lt;li&gt;Default constraints must be named DF_&amp;lt;schemaName&amp;gt;&amp;lt;tableName&amp;gt;_&amp;lt;ColumnName&amp;gt; &lt;/li&gt;    &lt;li&gt;Foreign keys must be of the form FK_&amp;lt;parentObjectSchema&amp;gt;&amp;lt;parentObject&amp;gt;_REF_&amp;lt;referencedObjectSchema&amp;gt;&amp;lt;referencedObject&amp;gt;XXX &lt;/li&gt;    &lt;li&gt;Non-unique clustered keys must be of the form IXC_&amp;lt;schemaName&amp;lt;TableName&amp;gt;_&amp;lt;Column&amp;gt;&amp;lt;Column&amp;gt;&amp;lt;Column&amp;gt;… &lt;/li&gt;    &lt;li&gt;Non-unique non-clustered keys must be of the form IX_&amp;lt;schemaName&amp;gt;&amp;lt;TableName&amp;gt;_&amp;lt;Column&amp;gt;&amp;lt;Column&amp;gt;&amp;lt;Column&amp;gt;... &lt;/li&gt;    &lt;li&gt;Unique clustered keys must be of the form IXUN_&amp;lt;schemaName&amp;gt;&amp;lt;TableName&amp;gt;_&amp;lt;Column&amp;gt;&amp;lt;Column&amp;gt;&amp;lt;Column&amp;gt;… &lt;/li&gt;    &lt;li&gt;Unique non-clustered keys must be of the form IXUN_&amp;lt;schemaName&amp;gt;&amp;lt;TableName&amp;gt;_&amp;lt;ColumnColumnColumn&amp;gt;...      &lt;ul&gt;&lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Primary keys must be of the form PK_&amp;lt;schemaName&amp;gt;&amp;lt;tableName&amp;gt; &lt;/li&gt;    &lt;li&gt;Stored procedure names should not contain underscores &lt;/li&gt;    &lt;li&gt;Stored procedure names must begin with a capital letter &lt;/li&gt;    &lt;li&gt;Table names must not contain underscores &lt;/li&gt;    &lt;li&gt;Table names must begin with a capital letter &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I’m not stating that you should agree with these naming conventions (I don’t necessarily agree with them myself – they were defined before I arrived on my current project), the point here is that all of these rules can be enforced and its very easy to do it. Here’s the code for the unit test that enforces the&amp;#160; primary key naming convention:&lt;/p&gt; &lt;code style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;&lt;font face="Consolas"&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;&lt;font face="Consolas"&gt;/*PK name is PK_&amp;lt;schemaName&amp;gt;&amp;lt;tableName&amp;gt;*/       &lt;br /&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;font face="Consolas"&gt;&lt;span style="color:blue;"&gt;SET NOCOUNT ON       &lt;br /&gt;&amp;#160;&amp;#160; DECLARE &lt;/span&gt;&lt;span style="color:#434343;"&gt;@cnt&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;;       &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;#160; &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;*       &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;INTO&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:#434343;"&gt;#t       &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;(       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;#160; &lt;/span&gt;&lt;span style="color:magenta;"&gt;OBJECT_NAME&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;c.[parent_object_id]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;[TableName]&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:black;"&gt;OBJECT_SCHEMA_NAME&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;c.[parent_object_id]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;[SchemaName]&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:black;"&gt;c.&lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;*       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:black;"&gt;[sys].[key_constraints] c       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;INNER JOIN &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:black;"&gt;[sys].[tables] t        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;ON&amp;#160; &lt;/span&gt;&lt;span style="color:black;"&gt;c.[parent_object_id] &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:black;"&gt;t.[object_id]&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:magenta;"&gt;LEFT &lt;/span&gt;&lt;span style="color:gray;"&gt;OUTER &lt;/span&gt;&lt;span style="color:blue;"&gt;JOIN &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:black;"&gt;sys.extended_properties ep       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;ON&amp;#160; &lt;/span&gt;&lt;span style="color:black;"&gt;t.[object_id] &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:black;"&gt;ep.major_id       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:gray;"&gt;AND &lt;/span&gt;&lt;span style="color:black;"&gt;ep.[name] &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:red;"&gt;'microsoft_database_tools_support'       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE &lt;/span&gt;&lt;span style="color:black;"&gt;ep.[major_id] &lt;/span&gt;&lt;span style="color:blue;"&gt;IS &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;NULL       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND &lt;/span&gt;&lt;span style="color:black;"&gt;c.[type] &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:red;"&gt;'PK'       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:black;"&gt;q       &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:black;"&gt;[name] &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;&amp;gt; &lt;/span&gt;&lt;span style="color:red;"&gt;N'PK_' &lt;/span&gt;&lt;span style="color:gray;"&gt;+ &lt;/span&gt;&lt;span style="color:black;"&gt;[SchemaName] &lt;/span&gt;&lt;span style="color:gray;"&gt;+ &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:black;"&gt;[TableName]       &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:#434343;"&gt;@cnt &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:#434343;"&gt;@@ROWCOUNT&lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;;       &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;IF&amp;#160; &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:#434343;"&gt;@cnt &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color:black;"&gt;0&lt;/span&gt;&lt;/font&gt;&lt;span style="color:gray;"&gt;&lt;font face="Consolas"&gt;)       &lt;br /&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;font face="Consolas"&gt;&lt;span style="color:blue;"&gt;BEGIN       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DECLARE &lt;/span&gt;&lt;span style="color:#434343;"&gt;@msg &lt;/span&gt;&lt;span style="color:blue;"&gt;NVARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;2048&lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;#160; &lt;/span&gt;&lt;span style="color:#434343;"&gt;@msg &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:red;"&gt;'%d Primary Keys do not conform to naming convention (PK_&amp;lt;schemaName&amp;gt;&amp;lt;tableName&amp;gt;):' &lt;/span&gt;&lt;span style="color:gray;"&gt;+ &lt;/span&gt;&lt;span style="color:magenta;"&gt;STUFF&lt;/span&gt;&lt;span style="color:gray;"&gt;((&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:red;"&gt;', ' &lt;/span&gt;&lt;span style="color:gray;"&gt;+ &lt;/span&gt;&lt;span style="color:black;"&gt;[name] &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:#434343;"&gt;#t &lt;/span&gt;&lt;span style="color:black;"&gt;a &lt;/span&gt;&lt;span style="color:blue;"&gt;FOR XML &lt;/span&gt;&lt;span style="color:black;"&gt;PATH&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;''&lt;/span&gt;&lt;span style="color:gray;"&gt;) ),&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:red;"&gt;''&lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;(       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;#160; &lt;/span&gt;&lt;span style="color:black;"&gt;1 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;[Id]&lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;,*       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:#434343;"&gt;#t &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:black;"&gt;t       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:black;"&gt;q       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;GROUP&amp;#160;&amp;#160; BY &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:black;"&gt;q.[Id]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:#434343;"&gt;@msg       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;RAISERROR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:#434343;"&gt;@msg&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:black;"&gt;11&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:#434343;"&gt;@cnt&lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span style="color:gray;"&gt;);       &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;/font&gt;&lt;/code&gt;  &lt;p&gt;Essentially all it does is pull all of the primary keys out of &lt;font size="1" face="Consolas"&gt;&lt;span style="color:black;"&gt;[sys].[key_constraints]&lt;/span&gt;&lt;/font&gt;, checks to see what the name &lt;em&gt;should &lt;/em&gt;be, then if it finds any that violate the naming convention raise an error containing the names of all the primary keys in question. Here’s the error obtained when running the test against [AdventureWorks] (I’ve highlighted the pertinent bit):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Test method Prs.SchemaTests.NamingConventions.PrimaryKeys threw exception:      &lt;br /&gt;System.Data.SqlClient.SqlException: &lt;strong&gt;70 Primary Keys do not conform to naming convention (PK_&amp;lt;schemaName&amp;gt;&amp;lt;tableName&amp;gt;)&lt;/strong&gt;:PK_ErrorLog_ErrorLogID, PK_Address_AddressID, PK_AddressType_AddressTypeID, PK_AWBuildVersion_SystemInformationID, PK_BillOfMaterials_BillOfMaterialsID, PK_Contact_ContactID, PK_ContactCreditCard_ContactID_CreditCardID, PK_ContactType_ContactTypeID, PK_CountryRegionCurrency_CountryRegionCode_CurrencyCode, PK_CountryRegion_CountryRegionCode, PK_CreditCard_CreditCardID, PK_Culture_CultureID, PK_Currency_CurrencyCode, PK_CurrencyRate_CurrencyRateID, PK_Customer_CustomerID, PK_CustomerAddress_CustomerID_AddressID, PK_DatabaseLog_DatabaseLogID, PK_Department_DepartmentID, PK_Document_DocumentID, PK_Employee_EmployeeID, PK_EmployeeAddress_EmployeeID_AddressID, PK_EmployeeDepartmentHistory_EmployeeID_StartDate_DepartmentID, PK_EmployeePayHistory_EmployeeID_RateChangeDate, PK_Illustration_IllustrationID, PK_Individual_CustomerID, PK_JobCandidate_JobCandidateID, PK_Location_LocationID, PK_Product_ProductID, PK_ProductCategory_ProductCategoryID, PK_ProductCostHistory_ProductID_StartDate, PK_ProductDescription_ProductDescriptionID, PK_ProductDocument_ProductID_DocumentID, PK_ProductInventory_ProductID_LocationID, PK_ProductListPriceHistory_ProductID_StartDate, PK_ProductModel_ProductModelID, PK_ProductModelIllustration_ProductModelID_IllustrationID, PK_ProductModelProductDescriptionCulture_ProductModelID_ProductDescriptionID_CultureID, PK_ProductPhoto_ProductPhotoID, PK_ProductProductPhoto_ProductID_ProductPhotoID, PK_ProductReview_ProductReviewID, PK_ProductSubcategory_ProductSubcategoryID, PK_ProductVendor_ProductID_VendorID, PK_PurchaseOrderDetail_PurchaseOrderID_PurchaseOrderDetailID, PK_PurchaseOrderHeader_PurchaseOrderID, PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID, PK_SalesOrderHeader_SalesOrderID, PK_SalesOrderHeaderSalesReason_SalesOrderID_SalesReasonID, PK_SalesPerson_SalesPersonID, PK_SalesPersonQuotaHistory_SalesPersonID_QuotaDate, PK_SalesReason_SalesReasonID, PK_SalesTaxRate_SalesTaxRateID, PK_SalesTerritory_Territor...&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I am currently including these tests inside a C# test project inside Visual Studio 2010. Visual Studio has a rather nice feature that allows you to link to artefacts in other projects and hence we can host our single test class containing all of these tests in one place and link to it from whichever test project we want (typically you will have a test project per database) thus following the &lt;a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself" target="_blank"&gt;DRY principle&lt;/a&gt;. Here I show the dialog that demonstrates adding a link to an existing test class:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/jamie_thomson/image_799DEAA6.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblog.com/blogs/jamie_thomson/image_thumb_55B5134C.png" width="619" height="424" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;And how it appears in the project. Note that NamingConventions.cs exists in both test projects but one is just a link to the other:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/jamie_thomson/image_12F5C814.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblog.com/blogs/jamie_thomson/image_thumb_5FB98EAA.png" width="244" height="229" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;Wrap-up&lt;/h3&gt;  &lt;p&gt;I’m not sure my colleagues are too happy about these new tests given that they’re now breaking the build more often but nonetheless I think they realise the value (I guess I’ll find out tomorrow when they read this!!!) &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://sqlblog.com/blogs/jamie_thomson/wlEmoticon-smile_7770C610.png" /&gt; All-in-all its working very well for us and I’m now a very happy bunny knowing that naming conventions are being enforced and will continue to be so with zero effort from here on in. I have made the test class that contains all of the tests that I detailed above available on my SkyDrive at &lt;a title="http://cid-550f681dad532637.office.live.com/self.aspx/Public/BlogShare/20101005/MIControlTest.zip" href="http://cid-550f681dad532637.office.live.com/self.aspx/Public/BlogShare/20101005/MIControlTest.zip"&gt;http://cid-550f681dad532637.office.live.com/self.aspx/Public/BlogShare/20101005/MIControlTest.zip&lt;/a&gt;. If you want to use it you should simply be able to drop it into an existing C# database test project and away you go (change the tests to suit your naming conventions of course though).&lt;/p&gt;  &lt;p&gt;Hope this helps. If it does please let me know, I’d really love some feedback on this.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://twitter.com/jamiet"&gt;@Jamiet&lt;/a&gt;&lt;/p&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=29199" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/Datadude/default.aspx">Datadude</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/naming+conventions/default.aspx">naming conventions</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/unit+testing/default.aspx">unit testing</category></item><item><title>Experiences from writing sp_CascadingDataViewer – DB unit testing and code distribution</title><link>http://sqlblog.com/blogs/jamie_thomson/archive/2010/09/18/experiences-from-writing-sp-cascadingdataviewer-db-unit-testing-and-code-distribution.aspx</link><pubDate>Sat, 18 Sep 2010 16:41:55 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:28849</guid><dc:creator>jamiet</dc:creator><slash:comments>3</slash:comments><comments>http://sqlblog.com/blogs/jamie_thomson/comments/28849.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/jamie_thomson/commentrss.aspx?PostID=28849</wfw:commentRss><wfw:comment>http://sqlblog.com/blogs/jamie_thomson/rsscomments.aspx?PostID=28849</wfw:comment><description>&lt;p&gt;Its now been a month since I &lt;a href="http://sqlblog.com/blogs/jamie_thomson/archive/2010/08/11/introducing-sp-cascadingdataviewer.aspx" target="_blank"&gt;introduced sp_CascadingDataViewer&lt;/a&gt; and I wanted to take the opportunity to talk about a couple of my experiences while writing it.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;SQL Server needs packages&lt;/h2&gt;  &lt;p&gt;Version 1 of sp_CascadingDataViewer is an 899 line stored procedure (view the code at &lt;a href="http://cascadingdataviewer.codeplex.com/SourceControl/changeset/view/58999#1568990" target="_blank"&gt;changeset 58999&lt;/a&gt;), that’s a lot of code and much of it is repeated. I would have loved to have hived off different parts into dedicated functions but I couldn’t do that because my aim was to keep everything in a single stored procedure thus making it as easy as possible for someone to add it to their SQL Server instance. That is an unfortunate trade-off that we have to make with SQL Server.&lt;/p&gt;  &lt;p&gt;Oracle has a solution to this problem called packages. A package is ostensibly a collection of stored procedures and functions that can be distributed and installed as a single unit. That makes them extremely portable and would be an ideal mechanism for me to distribute a collection of stored procedures and functions that make up Cascading Data Viewer.&lt;/p&gt;  &lt;p&gt;SQL Server needs something equivalent to Oracle packages.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;You need to be doing automated database unit testing&lt;/h2&gt;  &lt;p&gt;sp_CascadingDataViewer wouldn’t exist without automated database unit testing in Visual Studio. Period.&lt;/p&gt;  &lt;p&gt;With something as complicated as sp_CascadingDataViewer there were many many combinations of code, schema and data that could cause is to break. I had to deal with all those combinations and have a way of ensuring that any changes that I made did not break something else and automated testing was the means with which I did that.&lt;/p&gt;  &lt;p&gt;I wrote the code for sp_CascadingDataViewer in Visual Studio rather than SQL Server Management Studio (as I do for all my T-SQL code these days) which meant that my code and the tests lived in the same solution. At the time of writing that solution includes 30 tests and all are available in &lt;a href="http://cascadingdataviewer.codeplex.com/SourceControl/list/changesets" target="_blank"&gt;the source code on Codeplex&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/jamie_thomson/image_5F31D6E2.png"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblog.com/blogs/jamie_thomson/image_thumb_79CE4D2E.png" width="529" height="628" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;With a simple key chord (CTRL+R, CTRL+A) I could deploy my code and run all my tests against it – that’s an incredibly powerful mechanism and I actually find it to be very productive method of development even if you have many tests that need to be run.&lt;/p&gt;  &lt;p&gt;Writing sp_CascadingDataViewer switched me on to the value of automated database unit testing and I now advocate its use wherever I go.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://twitter.com/jamiet"&gt;@jamiet&lt;/a&gt;&lt;/p&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=28849" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/Datadude/default.aspx">Datadude</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/unit+testing/default.aspx">unit testing</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/Visual+Studio+2010/default.aspx">Visual Studio 2010</category></item><item><title>Microsoft publish Visual Studio 2010 Database Project Guidance</title><link>http://sqlblog.com/blogs/jamie_thomson/archive/2010/08/23/microsoft-publish-visual-studio-2010-database-project-guidance.aspx</link><pubDate>Mon, 23 Aug 2010 11:33:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:28174</guid><dc:creator>jamiet</dc:creator><slash:comments>1</slash:comments><comments>http://sqlblog.com/blogs/jamie_thomson/comments/28174.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/jamie_thomson/commentrss.aspx?PostID=28174</wfw:commentRss><wfw:comment>http://sqlblog.com/blogs/jamie_thomson/rsscomments.aspx?PostID=28174</wfw:comment><description>&lt;SPAN class=Apple-style-span style="WORD-SPACING:0px;FONT:medium 'Times New Roman';TEXT-TRANSFORM:none;TEXT-INDENT:0px;WHITE-SPACE:normal;LETTER-SPACING:normal;BORDER-COLLAPSE:separate;orphans:2;widows:2;-webkit-border-horizontal-spacing:0px;-webkit-border-vertical-spacing:0px;-webkit-text-decorations-in-effect:none;-webkit-text-size-adjust:auto;-webkit-text-stroke-width:0px;"&gt;
&lt;DIV style="PADDING-RIGHT:8px;PADDING-LEFT:8px;FONT-SIZE:10pt;PADDING-BOTTOM:8px;PADDING-TOP:8px;FONT-FAMILY:Arial, Helvetica, sans-serif;"&gt;Three days ago I wrote a blog post entitled&amp;nbsp;&lt;A class="" href="http://sqlblog.com/blogs/jamie_thomson/archive/2010/08/20/setting-up-database-unit-testing-as-part-of-a-continuous-integration-build-process-vs2010-db-tools-datadude.aspx"&gt;Setting up database unit testing as part of a Continuous Integration build process [VS2010 DB Tools - Datadude]&lt;/A&gt;&amp;nbsp;which goes through some of the intracasies of using Visual Studio 2010 Database projects (aka datadude projects) and database unit testing as part of a continuous integration build. Well it turns out I needn't have bothered because today Microsoft have (or, more accurately, Jens Suessmeyer has) published a 91-page guidance document on using datadude projects and on page 57&amp;nbsp;it covers exactly what I covered in my blog post (plus a lot more besides). Ah well...&lt;/DIV&gt;
&lt;DIV style="PADDING-RIGHT:8px;PADDING-LEFT:8px;FONT-SIZE:10pt;PADDING-BOTTOM:8px;PADDING-TOP:8px;FONT-FAMILY:Arial, Helvetica, sans-serif;"&gt;Anyway, if you want to take a read of this tome head to &lt;A href="http://vsdatabaseguide.codeplex.com/"&gt;http://vsdatabaseguide.codeplex.com/&lt;/A&gt;&amp;nbsp;and/or go and read Jens' blog post on the matter &lt;A class="" href="http://blogs.msdn.com/b/jenss/archive/2010/08/21/alm-visual-studio-database-projects-guidance-is-out-in-the-wild.aspx"&gt;ALM Visual Studio Database Projects Guidance is out in the wild !&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="PADDING-RIGHT:8px;PADDING-LEFT:8px;FONT-SIZE:10pt;PADDING-BOTTOM:8px;PADDING-TOP:8px;FONT-FAMILY:Arial, Helvetica, sans-serif;"&gt;&lt;A class="" href="http://twitter.com/jamiet"&gt;@Jamiet&lt;/A&gt;&lt;/DIV&gt;&lt;/SPAN&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=28174" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/Datadude/default.aspx">Datadude</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/unit+testing/default.aspx">unit testing</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/Visual+Studio+2010/default.aspx">Visual Studio 2010</category></item><item><title>Setting up database unit testing as part of a Continuous Integration build process [VS2010 DB Tools - Datadude]</title><link>http://sqlblog.com/blogs/jamie_thomson/archive/2010/08/20/setting-up-database-unit-testing-as-part-of-a-continuous-integration-build-process-vs2010-db-tools-datadude.aspx</link><pubDate>Fri, 20 Aug 2010 18:41:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:28103</guid><dc:creator>jamiet</dc:creator><slash:comments>18</slash:comments><comments>http://sqlblog.com/blogs/jamie_thomson/comments/28103.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/jamie_thomson/commentrss.aspx?PostID=28103</wfw:commentRss><wfw:comment>http://sqlblog.com/blogs/jamie_thomson/rsscomments.aspx?PostID=28103</wfw:comment><description>&lt;P&gt;&lt;I&gt;&lt;FONT face=Consolas&gt;[This blog post assumes a familiarity with the terms Continuous Integration (CI), MSBuild &amp;amp; MSTest. If you don’t have a good appreciation of those terms then this blog post probably isn’t for you anyway so don’t worry about it!]&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;Over the past few days I have been working to get database unit tests executing as part of our Continuous Integration (CI) build and in this blog post I’ll explain how I went about it because it is decidedly &lt;I&gt;not&lt;/I&gt; straightforward.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;We are using the &lt;STRONG&gt;DB Tools in Visual Studio 2010&lt;/STRONG&gt; (aka &lt;STRONG&gt;DBPro&lt;/STRONG&gt; or &lt;STRONG&gt;Datadude&lt;/STRONG&gt; - I will refer to it as Datadude from here on in) which includes unit testing functionality. The rest of this blog post also assumes a familiarity with database unit testing in Datadude although if you want to do some background reading an excellent place to start is Jamie Laflen’s whitepaper &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/magazine/cc164243.aspx"&gt;&lt;FONT face=Consolas&gt;Apply Test-Driven Development to your Database Projects&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Consolas&gt; on MSDN.&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Consolas&gt;
&lt;HR&gt;
&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;We got to the point where we had a C# test project containing database unit tests that executed successfully inside Visual Studio. For demonstration purposes I have put together a solution that contains a simple database project and a test project containing a database unit test:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image001_png01CB4075_1B0AD4EE.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="Solution Explorer screenshot" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=433 alt="solution explorer" src="http://sqlblog.com/blogs/jamie_thomson/cid_image001_png01CB4075_thumb_7DC4E149.png" width=506 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;And just to prove that the test executes successfully in Visual Studio:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image002_png01CB4075_10D5E829.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="Visual Studio Test Results screenshot" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=249 alt="Visual Studio Test Results screenshot" src="http://sqlblog.com/blogs/jamie_thomson/cid_image002_png01CB4075_thumb_1DCFC83A.png" width=856 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;N.B. The code for the database object(s) and the unit test itself are not important, that is outside the scope of this blog post.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;At this point we have some tests that run in our development sandbox, the configuration for which is done using the Database Test Configuration dialog:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image003_png01CB4076_14938CF9.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="database test configuration choice" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=382 alt="database test configuration choice" src="http://sqlblog.com/blogs/jamie_thomson/cid_image003_png01CB4076_thumb_057CAE1F.png" width=786 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image004_png01CB4076_70AAB59E.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="database test configuration dialog" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=638 alt="database test configuration dialog" src="http://sqlblog.com/blogs/jamie_thomson/cid_image004_png01CB4076_thumb_4FB742F7.png" width=508 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;Those config settings are stored in the app.config file which exists as part of our test project (screenshot of which is at the top of this blog post). If we take a look inside that file we can see the&lt;/FONT&gt; &lt;FONT face="Courier New"&gt;ConnectionString&lt;/FONT&gt; &lt;FONT face=Consolas&gt;that we defined in the Database Test Configuration dialog:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image005_png01CB4076_5F76D7FB.png"&gt;&lt;IMG title="app config connectionString DatabaseUnitTesting" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=271 alt="app config connectionString DatabaseUnitTesting" src="http://sqlblog.com/blogs/jamie_thomson/cid_image005_png01CB4076_thumb_17491C1F.png" width=959 border=0&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;Note the&lt;/FONT&gt; &lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#c0504d&gt;DatabaseUnitTesting&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT face=Consolas&gt;element, we’re going to be coming back to that a little later!!&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Consolas&gt;
&lt;HR&gt;
&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;Once we have the tests running in Visual Studio the next step is to get them running inside a CI build and for that we call out to MSTest.exe from inside an MSBuild script:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image006_png01CB407D_54F603DB.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="msbuild script mstest" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=155 alt="msbuild script mstest" src="http://sqlblog.com/blogs/jamie_thomson/cid_image006_png01CB407D_thumb_733FF92A.png" width=1069 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;When we execute that script we get some positive results and all looks peachy:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image007_png01CB407D_380C1D5F.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="msbuild mstest output" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=534 alt="msbuild mstest output" src="http://sqlblog.com/blogs/jamie_thomson/cid_image007_png01CB407D_thumb_4837E558.png" width=650 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;FONT face=Consolas&gt;
&lt;HR&gt;
&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;OK, we now have a test that runs successfully both in Visual Studio and by calling MSTest.exe directly from MSBuild. The problem I have to solve now though (and this is the real crux of this blog post) is that the test is still running against the server I specified in app.config; I don’t want this, I want the test to run against a server of my choosing, namely my build server. For this I had to call on the help of the aforementioned Jamie Laflen (who, luckily, I have met in the past) and he gave me guidance on how to achieve it. Below are the steps that you need to take.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;Firstly you need to tell Datadude that you want to specify some different credentials and that is done by adding an attribute&lt;/FONT&gt; &lt;FONT face="Courier New"&gt;&lt;FONT color=#ff0000&gt;AllowConfigurationOverride&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;"&lt;/FONT&gt;&lt;FONT face=Consolas&gt; to the&lt;/FONT&gt; &lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#c0504d&gt;DatabaseUnitTesting&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT face=Consolas&gt;element of app.config like so:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image008_png01CB407E_32F9B9E3.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="app config DatabaseUnitTesting AllowConfigurationOverride" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=345 alt="app config DatabaseUnitTesting AllowConfigurationOverride" src="http://sqlblog.com/blogs/jamie_thomson/cid_image008_png01CB407E_thumb_23E2DB09.png" width=643 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;I&gt;&lt;FONT face=Consolas&gt;Don’t forget to build your test project after changing the app.config file!!!&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;This will cause datadude unit testing framework to go and search for a file called&lt;/FONT&gt; &lt;FONT face="Courier New"&gt;*.dbunittest.config&lt;/FONT&gt; &lt;FONT face=Consolas&gt;where the * indicates either:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face=Consolas&gt;The name of machine upon which the tests are being run or&lt;/FONT&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Consolas&gt;The name of the user running the tests&lt;/FONT&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;According to Jamie L datadude runs the following precedence checks:&lt;/FONT&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT face=Consolas&gt;Is an override specified in app.config? If not, use app.config&lt;/FONT&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Consolas&gt;Does an override file exist called &amp;lt;machinename&amp;gt;.dbunittest.config? If so, use it, if not…&lt;/FONT&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Consolas&gt;Does an override file exist called &amp;lt;username&amp;gt;.dbunittest.config? If so, use it, if not…&lt;/FONT&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Consolas&gt;Fail!&lt;/FONT&gt; &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;“So”, you may be asking, “what goes in this &lt;/FONT&gt;&lt;FONT face="Courier New"&gt;*.dbunittest.config&lt;/FONT&gt; file then?”. &lt;FONT face=Consolas&gt;Fair question, that’s where the&lt;/FONT&gt; &lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#c0504d&gt;DatabaseUnitTesting&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT face=Consolas&gt;element that I mentioned earlier comes in. Copy that element from the app.config file into your &lt;FONT face="Courier New"&gt;*.dbunittest.config&lt;/FONT&gt; file, remove the&lt;/FONT&gt;&amp;nbsp;&lt;FONT face="Courier New"&gt;&lt;FONT color=#ff0000&gt;AllowConfigurationOverride&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;"&lt;/FONT&gt;&lt;FONT face=Consolas&gt; attribute and change the&lt;/FONT&gt; &lt;FONT face="Courier New"&gt;ConnectionString&lt;/FONT&gt; &lt;FONT face=Consolas&gt;property accordingly:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image009_png01CB4081_20ED7656.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="dbunittest.config ConnectionString" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=236 alt="dbunittest.config ConnectionString" src="http://sqlblog.com/blogs/jamie_thomson/cid_image009_png01CB4081_thumb_7464466F.png" width=847 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;The next step is to tell MSTest.exe that there is another file that it needs to be aware of when it runs the tests and to do that we need to create a custom testsettings file that will be used instead of the default Local.testsettings. To create a new testsettings file use the Add New Item dialog:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image010_png01CB4083_7D049EFB.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="add new test settings" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=466 alt="add new test settings" src="http://sqlblog.com/blogs/jamie_thomson/cid_image010_png01CB4083_thumb_1BDB12DA.png" width=825 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;In the Test Settings dialog go to ‘Deployment’, click ‘Enable deployment’, then ‘Add File…’. Browse to your&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; *.dbunittest.config &lt;/FONT&gt;&lt;FONT face=Consolas&gt;file and add it to the project:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image011_png01CB4083_39D920CE.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="test settings dialog" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=655 alt="test settings dialog" src="http://sqlblog.com/blogs/jamie_thomson/cid_image011_png01CB4083_thumb_3FB3C467.png" width=892 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;At this point you’re good to go and all you need to do edit your call to MSTest.exe and tell it to use your new testsettings file:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image012_png01CB4084_5CD96C71.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="msbuild script mstest testsettings" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=163 alt="msbuild script mstest testsettings" src="http://sqlblog.com/blogs/jamie_thomson/cid_image012_png01CB4084_thumb_70865605.png" width=1011 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;Notice the extra information in the output:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image013_png01CB4084_2F0BA3AC.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="msbuild script output" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=577 alt="msbuild script output" src="http://sqlblog.com/blogs/jamie_thomson/cid_image013_png01CB4084_thumb_4DE2178A.png" width=702 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;You’ll have to trust me that it used the new config file and therefore the new &lt;/FONT&gt;&lt;FONT face="Courier New"&gt;ConnectionString&lt;/FONT&gt;&lt;FONT face=Consolas&gt;, although having said that you do get some useful information in the test results file (*.trx) that MSTest.exe creates:&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/jamie_thomson/cid_image014_png01CB4085_248ACF8C.png"&gt;&lt;FONT face=Consolas&gt;&lt;IMG title="mstest test results trx output" style="BORDER-TOP-WIDTH:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-LEFT:0px;BORDER-LEFT-WIDTH:0px;BACKGROUND-IMAGE:none;BORDER-BOTTOM-WIDTH:0px;PADDING-TOP:0px;BORDER-RIGHT-WIDTH:0px;" height=255 alt="mstest test results trx output" src="http://sqlblog.com/blogs/jamie_thomson/cid_image014_png01CB4085_thumb_2A657325.png" width=991 border=0&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;FONT face=Consolas&gt;
&lt;HR&gt;
&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;I think its fair to say that this process is a little fiddly to say the least so I’m hoping that Microsoft come up with a better solution in the future, one that integrates better into the whole testing infrastructure. Meanwhile you can download the demo that I put together for this blog post from my &lt;/FONT&gt;&lt;A href="http://bit.ly/cYYIdq" target=_blank&gt;&lt;FONT face=Consolas&gt;SkyDrive&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Consolas&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;Hope that helps! Comments are welcome.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://twitter.com/jamiet" target=_blank&gt;&lt;FONT face=Consolas&gt;Jamiet&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;SPAN class=Apple-style-span style="WORD-SPACING:0px;FONT:medium 'Times New Roman';TEXT-TRANSFORM:none;TEXT-INDENT:0px;WHITE-SPACE:normal;LETTER-SPACING:normal;BORDER-COLLAPSE:separate;orphans:2;widows:2;-webkit-border-horizontal-spacing:0px;-webkit-border-vertical-spacing:0px;-webkit-text-decorations-in-effect:none;-webkit-text-size-adjust:auto;-webkit-text-stroke-width:0px;"&gt;&lt;SPAN class=Apple-style-span style="FONT-SIZE:13px;FONT-FAMILY:Arial, Helvetica, sans-serif;"&gt;
&lt;P&gt;UPDATE: Atul Verma has written a 3-part blog series on how to write your database unit tests so if Jamie Laflen's whitepaper (linked to above) doesn't tickle your fancy try reading Atul's series instead:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A class="" href="http://blogs.msdn.com/b/atverma/archive/2010/07/28/how-to-unit-test-sql-server-2008-database-using-visual-studio-2010.aspx"&gt;How to unit test SQL Server 2008 database using Visual Studio 2010&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://blogs.msdn.com/b/atverma/archive/2010/08/22/how-to-unit-test-sql-server-2008-database-using-visual-studio-2010-part-2.aspx"&gt;How to unit test SQL Server 2008 database using Visual Studio 2010 – Part 2&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://blogs.msdn.com/b/atverma/archive/2010/08/22/how-to-unit-test-sql-server-2008-database-using-visual-studio-2010-part-3.aspx"&gt;How to unit test SQL Server 2008 database using Visual Studio 2010 – Part 3&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=28103" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/Continuous+Integration/default.aspx">Continuous Integration</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/Datadude/default.aspx">Datadude</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/msbuild/default.aspx">msbuild</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/mstest/default.aspx">mstest</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/unit+testing/default.aspx">unit testing</category><category domain="http://sqlblog.com/blogs/jamie_thomson/archive/tags/Visual+Studio+2010/default.aspx">Visual Studio 2010</category></item></channel></rss>