Hints For Creating Custom Test Condition for SSDT in Visual Studio 2013

I use the steps described in the MSDN article How to: Create Test Conditions for the SQL Server Unit Test Designer and found some variations while repeating it in Visual Studio 2013.

1) in step 5 we can use a newer version of dll if we have a newer version of SQL Server installed on local machine. Then number 110 in the path means SQL Server 2012, 120 – SQL Server 2014.

2) in step 8 we need to change the VS version number from 10.0 to 12.0. So you need to add these lines:

Hint: import of Microsoft.CSharp.targets is located at the end of the file.

3) in step 10 we need to include two namespaces to derive from class TestCondition. Add these directives to your class:

4) in step 13 we need to copy dll file from bin\Debug or bin\Release folder to C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\SQLDB\TestConditions. You will see readme.txt file there.

Debugging In SSDT Database Unit Test

“SSDT now enables you to develop, debug and execute database unit tests interactively in Visual Studio…”

I was pleased when I read this in the post in SSDT team blog.
But I was confused a little when I could not set a breakpoint in unit test as I always do in Visual Studio. Yeah! You can’t click on the grey sidebar to the left from the unit test code (it’s on the red frame on the screenshot below).
place to set breakpoint
I’ve found a topic How to: Debug Database Objects on the MSDN that describe the steps needed to debug unit test.
1) enable SQL debugging on test project:

  • right-click test project in Solution Explorer, then click Properties
  • click Debug
  • check the option Enable SQL Server debugging
enable sql debugging
2) increase execution timeout:
  • double-click on app.config in Server Explorer
app.config in solution explorer
  • set CommandTimeout in the line ExecutionContext to a greater value (for example, 300 seconds)
app.config
  • rebuild the test project to apply changes in app.config
3) set breakpoint in stored procedure we are debugging. You can open it in your database project or via SQL Server Object Explorer (View -> SQL Server Object Explorer).
breakpoint
4) start the debugging:
  • open Test Explorer;
  • right-click the test
  • click Debug Selected Tests
Immediately after that you will see the debug panels in Visual Studio. But it’s too early to press any buttons to step into or over. You should wait some time while Visual Studio loads and runs all the actions before it reach the breakpoint. At this time the breakpoint is shown as a white circle with a red rim.
When the execution stops at breakpoint the line will be highlighted with yellow color. Now you can step forward over the commands of the stored procedure being debugged.
debugging

Problem With Duplicate Names of Database Objects And Execution Context in SQL Server

SQL Server has a capability to create many database objects with the same name. But they must belong to different schema. Let’s look how we can deal with this.

My simple test case:

  1. Create a new schema tst
  2. Create a new login test
  3. Create a new database user test for that login and assign schema tst to him
  4. Make the user test to be the owner of schema tst
  5. Create two table with the same name in dbo and tst schema
  6. Insert different values to the correspondent tables

Script can be downloaded from db_object_names_resolution

Now we can check the rows in both tables. That’s alright, we see exactly the same values that were inserted earlier. Pay attention to the fact we use schema names when accessing the tables.
explicit schema names

This time we run SELECT command without schema name. What should we see? ‘dbo’ or ‘tst’?
The answer is ‘dbo’.

implicit dbo

Try to change execution context to user test and run the same command.

implicit tst

We’ve just got the results from the table in tst schema. Why?
If you look at the User Mapping in the Login Properties window, you see the user and default schema for that particular login.

user mapping

Do you understand what happens?
When I connect to SQL Server as Administrator, I run the query as user dbo and have a default schema dbo. The results are taken from [dbo].[Clients].
When I connect as test, I run the query as user test, so the default schema for that user is tst. The results are taken from [tst].[Clients].

The next question – what will be if the user test run the query from table in dbo schema without denoting the schema name? There are 2 possible answers: the query will return the results from that table or will not be executed. What do you think about that?

To sum up, I would recommend to use unique names for database objects even if they belong to different schema.

Hint: the first search to resolve the database object’s name is made in user default schema, then in dbo schema.

MatchFirstError Property in SSDT Database Unit Test And Multiple SQL Errors

When I explored the negative unit testing (see here) I encountered a new property MatchFirstError in ExpectedSqlException.

attributes of test method

According to MSDN, true value means that the expected severity, state, and error number must match to the first SqlError in the exception; false value – to any SqlError in the exception.

I was wondering in which situations a SQL error could not be the first. If it’s not the first, it can be the second error and so on. The next question – how can I raise two errors?
When SQL server executes T-SQL commands, the error interrupts that batch and raises an exception. So this error will be the the first and the only error.
But when we use try – catch blocks, there can be errors both in try and catch block. Therefore there can be multiple errors. It can be check in a very simple way.
We execute a code that tries to delete non-existing stored procedures in try and catch block.

nested errors

The result is two(!) errors from one stored procedure.

Let’s return back to MatchFirstError property. The default value (true) means that expected error will be the only exception or the cause of other consequent exceptions (in another words, it won’t be raised by another error).

SSDT Negative Database Unit Test

In one of my previous post I’ve faced with exception that occurred during unit test. Placing an appropriate command to disable constraints helps to avoid exception. But what should we do if we want to check that T-SQL code really fires an exception? The answer is very simple – we need to write a test that will handle the exception. This technique is called “negative testing”.

I will use the same example that I described in my previous test.

  • I change the Pre-test section to enforce constraints. Just place this command:

  • open the C# code of unit test: right-click the test in Solution Explorer, then click View Code
view csharp code of unit test
  • find the definition of our test (search for string dbo_CreateClientTest)
  • change the line in square brackets above the definition by adding a ExpectedSqlException attribute
attributes of test method

Message number and severity code was taken from the output of failed test that was run before. All possible properties that can be used in ExpectedSqlException declaration are explained here.
Note: The test will work even if you omit all the properties but using the exact values gives you the better level of granularity to check the right kind of exceptions.

 Now we can run our test. This time we see a green mark – our test passes.

Finding Dependencies Between Database Objects in SQL Server

When I need to analyze dependencies, I should find the answer for 2 questions:

1) which objects does my piece of code depends on? In this case, I get the impact from the others.
When you look at this view definition, you understand that the view depends on two tables.

2) which objects does my piece of code influence on? Now I produce the impact to others.

Microsoft SQL Server has some capabilities to analyze dependencies.

  • catalog view sys.objects
This view shows all database objects and dependencies between parent and child objects such as constraints and triggers. Additional info can be found in MSDN
sys.objects
  • INFORMATION_SCHEMA views
There are 20 views that can obtain various information about database metadata from different angles. Full list is in MSDN
information_schema
  • system stored procedure sp_depends

According to information in MSDN, this stored procedure will be removed in the future.

sp_depends
  • dynamic managements functions sys.dm_sql_referenced_entities and sys.dm_sql_referencing_entities

dm_reference

Working With Dependencies In SSDT Unit Test: Disable Contstraints

When we run a piece of T-SQL code, it can be dependent on another T-SQL code such as function. For example, stored procedure queries data with only one SELECT command. In this command you can use scalar functions in SELECT clause, table-valued functions or views in FROM clause, scalar functions in WHERE clause (that’s a very bad habit, but it’s possible), etc.

Our T-SQL code can be affected by other database objects such as constraints and triggers. When we insert or update data, these objects can prevent to enter incorrect values, so our command would fail.

Let’s look at how they would impact on database unit testing.
I modify the test case I’ve created earlier in this post and add a simple constraint.

Table with constraint

My test passed because ClientName (‘John Smith’) consists of 10 chars. Now I change to something shorter, and the test failed.

failed test

There’s no error in stored procedure I’ve been testing, it’s a violation of constraint. So to pass this test (I mean to test the functionality of stored procedure) I should eliminate constraint from being applied during the test. It can be done in the following manner:

  • choose an item Pre-test in the dropdown list shown below
Create post-test
  • Click the link Click here to create in the center of Test Designer.
  • Write T-SQL code to disable the constraint.

Alternatively, we can disable all constraints in a table with one command:

Now our test really passed.

pre-test disable constraint
But don’t forget to enable constraint in Post-Test section of unit test.

Deleting All Stored Procedures In SQL Server Database

This is a quite simple task to do with cursor because we need to execute command DROP PROCEDURE. So we create a cursor, fetch all names of stored procedure and drop them.

Here’s the script that implement the above logic.

Update 2015-11-26: The original script with SELECT name FROM sys.objects … works well if you have only the dbo schema. To delete all stored procedures in all schemas we need to use two-part objects names schema.object.

If we change the object type in first WHERE clause (for example, ‘FN’ for scalar functions) and use appropriate command in EXEC statement (DROP FUNCTION in this case) we can delete all database objects of another type. Full list of object types can be found here

NULL Values In WHERE Predicate of SQL Queries (IN, NOT IN And EXISTS). How to Avoid Wrong Results

As you know SQL Server can hold NULL values in table’s columns. It usually means that a value of the column is unknown. For example, what is better to answer the question about on which floor does your friend live: on the 1st or 2nd, maybe 5th, N-th or just say “I’m afraid I don’t know exactly”. So NULL values can save this situation.

But when we try to match values we should be cautious about NULL values. Let’s look at the following examples.
I create two tables with sample data in tempdb.

data
So we have two matches by first name and one row in Clients table has no match. You can find matches with the help of subqueries starting with IN or EXISTS.
matched rows
OK! We have the correct result. Now we want to find mismatches. Just add NOT before a subquery.
unmatched rows with null
OK! It works correctly.
Now I will insert a new row into Clients table with no first name (there will be a NULL value in the column).
data with null
Match queries find the exact rows as shown above but the results of mismatch queries are different.
unmatched rows with null
It’s somewhat surprising that first query with NOT IN could not find the row with NULL value. To include NULL values you can add additional comparison like OR FirstName IS NULL in ther WHERE clause.
The T-SQL code snippets can be downloaded from null_values_in_where_predicate
To sum up, I would recommend the following:
  1. Don’t use NULL columns if it doesn’t really needed
  2. Test thoroughly your queries for NULL/NOT NULL matches

Calling SQL Server Stored Procedure With Table-Valued Parameter in C#

In one of my previous post I described how to use table-value parameter in T-SQL code. Today I will show how to use it in your .NET application.

This is a sample C# console application. The most important things you should pay attention to are the following:

  1. create DataTable with structure equivalent to table type defined in SQL database (in my case string for varchar(20), and Int16 for smallint)
  2. fill your DataTable with data
  3. add parameter to SqlCommand object with type SqlDbType.Structured
  4. assign DataTable to parameter’s Value property