Tuesday, February 24, 2015

Group by test class name in VS2012 Test Explorer

Background

Writing unit test case is always a good practice in programming. It gives confidence to re-factor code and make sure each and every piece is working properly. If individual pieces are working good mostly the application will work after integration.

Basics of Visual studio unit test framework

Visual Studio has out of the box unit testing framework. We can create test classes and those classes can contain test methods. Normally if we follow proper naming convention to relate production code with test projects, it is easy to see how the tests are performing. One of the naming convention for unit test class and methods names can be as follows
  • Let the test project name be same as production project but suffix the test project with .Tests
  • For each production code method, create a unit test class.
  • Each scenario in the production method can be one test method in test class.
  • Test class name can be <Scenario>_<Production Method Name>{}
  • Method name can be <Test case specification>_<Expected behavior>()
eg: Production code

    public static class ObjectFactory
    {
        public static object CreateObject(string fullyQualifiedClassAndAssemblyName, object[] constructorParameters)
        {
//Production code which uses reflection to create object.
        }
    }

Unit test class

[TestClassExcludeFromCodeCoverage]
public class ObjectFactory_CreateObject
{
        [TestMethodTimeout(1000)]
        public void WhenFullyQualifiedClassAndAssemblyNamePassedAndClassIsInternal_ShouldSucceed()
        {
//Test code
        }
        [TestMethod,ExpectedException(typeof(FileNotFoundException))]
        public void WhenFullyQualifiedClassAndNonExistingAssemblyNamePassed_ThrowFileNotFoundException()
        {
//Test code
        }
}

The main benefit of this naming convention is, it does not need any additional documentation to describe the what the test does. When we avoid one more item from maintenance, we are increasing productivity.

Running test cases from visual studio

We can easily trigger the unit test execution and see the results in "Test Results" window in VS 2010. The results will be shown with test name by default. The same functionality is there in VS2012 as well, but the window name is changed from "Test Results" to "Test explorer".

Problem

When the project grows, there are high chance that programmers forget to write test cases. Or even if there is strict enforcement, they will tend to write one test method like below for each and every production method.

[TestClass]
public class EmailSender_Send
{
        [TestMethod]
        public void WithProperparameter_ShouldSucceed()
        {
//Test code
        }
}
[TestClass]
public class Scheduler_CreateSchedule
{
        [TestMethod(), Timeout(30000)]
        public void WithProperParameters_ShouldSuccessed()
        {
//Test code
        }
}

Normally the test results will be displayed only with the test name and the test name is the test method name. That ends up in the test result window with all tests with same name. Its very difficult to understand from the review perspective.

If we want to see the test class name we can group by the test class name as below. This works well in VS2010.
[Photo taken from http://www.ladislavmrnka.com/wp-content/uploads/2012/09/TestView.png]

The same functionality in VS2012 named Test Explorer doesn't have Group by Class name in its earlier production releases. The group by popup is shown as below when try to group by class name.
This is really useless for somebody who want to see the test results. There is no idea why Microsoft removed a useful feature from earlier version in new release. But fortunately its back in later VS2012 updates. When this post is written, the latest update was Update 4.

Happy coding. Yes unit testing is part of coding:)

Tuesday, February 17, 2015

Standalone tools for production debugging

Below are some tools which are standalone and can help in production debugging. Don't confuse this works if we as developers have access to production servers and able to run standalone tools but don't have rights to install applications.

If we have rights to install applications in production server, we can use better tools than these such as Visual studio
  • .Net tools
    • Perfview - to catch exceptions
      • This is useful if we suspect that there are some exceptions eaten in the application and those are causing some other side effects.
  • Database
This is list is growing list. Hopefully I can add more later.


Tuesday, February 10, 2015

WCF DataServices - Date Time comparison in OData query

The concept of WCF data service which uses OData is really great. But I doubt whether that is ready to be used in an enterprise production applications. The main reason is its immaturity and lack of support on some Linq queries and operators. One of the major item is lack of joins. I believe OData specification itself doesn't have join. Below is another scenario which is not supported by WCF Data Services.

Requirement - Compare date in database against current date

Lets take and scenario where a MessageProcessAttempt table is exposed via WCF Data service. There is a field called DequeuedTime which tells when a message is dequeued. We need to list down all the messages which dequeued in last 1 hour.

In normal sense we can obtain the list by subtracting the de-queued time from current time and checking if the difference < 1 hour. The query can be as follows.

List<MessageProcessingAttempt> msgs = (from msg
                           in qProxy.MessageProcessingAttempts
                           where (DateTime.UtcNow- msg.DequeuedTime.Value).TotalHours<1
                           select msg).ToList();

But it will fail with below error message
"No property 'TotalHours' exists in type 'Edm.DateTime' at position 56."
Position will change based on the code.There will be no compile time errors. It just fails at runtime. Tried to find the details about Edm.DateTime class in msdn but able to find out except one EdmDateTimeConstant class.So what can we do

Solution - Calculate target date and compare

Find the target date and do comparison rather than finding the difference in the OData query.


DateTime timeToFilter = DateTime.UtcNow.Subtract(TimeSpan.FromHours(1));
List<MessageProcessingAttempt> msgs = (from msg
                           in qProxy.MessageProcessingAttempts
                           where msg.DequeuedTime.Value >= timeToFilter
                           select msg).ToList();

Here the major difference we can notice that the date subtraction is not happening via operator and its not producing the TimeSpan obejct. We can have DateTime.UtcNow.Subtract(TimeSpan.FromHours(1)) in OData as well instead of variable and it will work. This points to the fact that TotalHours property is not there in a special type called Edm.TotalHours which is produced as part of subtraction operator.

This was found by our development team in India and I didn't agree to them in the beginning. I spend around 2-3 hours and could see WCF Data Service is still not suitable for enterprise apps. Thanks to the team for finding the workaround.

Happy coding...

Tuesday, February 3, 2015

Dynamic SQL View using CONTEX_INFO

SQL Server supports creating views and I hope all knows what is a view. According to wiki its just a result set of query on data. Users can access it just like another table but it doesn't contain its own data like table. If we google for different between view and table we can get ton of links.

Below is a normal view definition.

CREATE VIEW CreditCards 
AS 
  (SELECT * 
   FROM   adventureworks2012.sales.creditcard 
   WHERE  cardtype = 'Vista')

In our day to day life most of the views we are creating has a static 'where' clause. Here we are
going to see how that part can be dynamic.

Create view by getting values from CONTEXT_INFO

CONTEXT_INFO gives us option to store values in the context of a session. It can be more compared to a static variable in programming. Here we are going to see how a view can be created which is affected by CONTEXT_INFO value.

Below is a sample view which is consuming the CONTEXT_INFO

CREATE VIEW creditcards 
AS 
  (SELECT * 
   FROM   adventureworks2012.sales.creditcard 
   WHERE  CardType = CONVERT(VARCHAR(25), Context_info())) 

If somebody call this view without setting the CONTEXT_INFO it will return the view which matches the where condition(CardType) with NULL. Else it returns proper data set.

Setting the CONTEXT_INFO

If we have already a view defined we can set the CONTEXT_INFO to our own values and select the view. The view will return proper values.

DECLARE @contextInfo VARBINARY(128) 

SET @contextInfo = CONVERT(VARBINARY(128), 'Vista') 
SET context_info @contextInfo 

SELECT * 
FROM   adventureworks2012.dbo.creditcards

The above query will return all the Sales.CreditCard with CardType='Vista'

One advantage is we can set this CONTEXT_INFO from code. More precisely from central data access before executing any other query. This way we can control centrally, what the tracks are getting from this view if they go via common data access.

http://jasondentler.com/blog/2010/01/exploiting-context_info-for-fun-and-audit/