Archive for January, 2008

Automated Unit Tests and the Dreaded Random Data

Recently I’ve been reviewing some unit tests for one of our major projects. And a coding practice I have noticed in these tests has started to annoy me. Sadly I am the one to blame for this coding practice, as I started it, but it is one that I hope to fix for all future tests (and some of the old ones). It is the use of random data in an automated test case. This practice emerged from our tests needing be repeatable on a system that has unique constraints on certain tables in the database, such as a Username, the test cases would randomly generate a valid username and register the user as a part of the test. Ok this is fine, but then the practice spread to all data being put into the system, including measurements, dates company names, even phone numbers. We wrote functions to create valid random data, and even randomly pick codes.

This gives great looking test data not just for your automated tests but also for any user-interactive testing etc. The problem for me lies in the fact that in a Unit Test you want to keep your variables to a minimum. A well designed Unit Test should be repeatable now or 10 years from now giving exactly the same results every time you run it. It should be able to specifically check that certain things do or do not happen. When random data is used for values that the test depends on, this can lead to tests giving false negatives, or worse, false positives (but only some of the time).

Example

   1:  [Test]
   2:  private void UpdateUserAge()
   3:  {
   4:      Random rand = new Random();
   5:      User user = UserData.GetUserByID(1);
   6:      int originalAge = user.Age;
   7:      user.Age = rand.Next(100);
   8:      UserData.UpdateUser(user);
   9:      User updatedUser = UserData.GetUserByID(1);
  10:      Assert.AreNotEqual(originalAge, updatedUser.Age);
  11:  }

In this example, a simple function gets out a User by ID 1 from a database (please ignore the fact the ID is hard-coded), updates the Age in the database with a random number between 0 and 100 and checks that the UserData.UpdateUser() function properly performed the update.

So what’s wrong with this code?

Well imagine that the UpdateUser function accidently ommitted the Age property in it’s updates (this actually happened to us a while back where a field was added to a database but it was left out of the update logic). Roughly 1 in 100 times this function would give a false positive that the updateUser.Age was correctly changed. Now if you were unlucky enough to have this occur when you were initially developing you may never have noticed that UserData.UpdateUser() did nothing.

Ok, this is a simple example but it can show how your Unit Tests are creating (or hiding) bugs of their own. Here’s the point I’m trying to make… Go to the effort of setting up a known scenario for your test, then change that known scenario, and double check everything equals what you expected it to. In the above example I’m also assuming an existing User… what if two developers were running this test at once? Create the data from scratch, it makes your tests larger (much larger) and if this becomes a problem create an ordered test where the scenario is created for a whole suite of test cases, that are run in sequence.

Leave a comment

Nuttiness of SQL Server Reporting Services ASP.NET Report Viewer Control

Recently I was attempting to create a simple test ASP.NET web application for viewing reports. The test was to use our administrative reports just to see how the Report Viewer control worked. Our SQL Reports Server was configured to use NT Integrated authentication, despite it being hosted on a server outside our network. I added the control to my web form like so:

<rsweb:ReportViewer ID="ReportViewer1" runat="server">
    <ServerReport ReportServerUrl="http://www.ourserver.com/ourreportserver" ReportPath="/Test/Test Report" />
</rsweb:ReportViewer>

And thought to myself "now I’ll just hard-code the credentials into the control in code" but to my surprise there was no straight forward way to do this… Searches on the internet revealed I needed to create a class that implemented IReportServerCredentials. Fair enough, kind of surprising MS didn’t do this for me when all I wanted was to pass a NetworkCredential. Anyway, I add the following class to my project:

public class ReportCredentials : IReportServerCredentials
{
    #region IReportServerCredentials Members
    
    public bool GetFormsCredentials(out System.Net.Cookie authCookie, out string userName, out string password, out string authority)
        {
            //throw new NotImplementedException(); 
            userName = password = authority = null;
            authCookie = null;
        return true;
        }

        public System.Security.Principal.WindowsIdentity ImpersonationUser
        {
            get { return null; }
        }

        public System.Net.ICredentials NetworkCredentials
        {
            get {
                return new NetworkCredential(@"reportserveruser", "reportserverpassword");
            }
        }

        #endregion
}

Unfortunately this does not work and I receive the error Logon Failed (rsLogonFailed), upon debugging I noticed that GetFormsCredentials was being called, and this confused me, despite the fact the Report Server only uses Integrated Windows auth. But to placate the server I made the following alteration to my class to make it return both a NetworkCredential and create a FormsCredential:

public bool GetFormsCredentials(out System.Net.Cookie authCookie, out string userName, out string password, out string authority)
{
    //throw new NotImplementedException(); 
    userName = password = authority = null;
    userName = "reportserveruser";
    password = "reportserverpassword";
    // The cookie name is specified in the <forms> element in Web.config (.ASPXAUTH by default)
    HttpCookie cookie = HttpContext.Current.Request.Cookies[".ASPXAUTH"];
    if (cookie == null) return false;
        //HttpContext.Current.Response.Redirect("login.aspx");
    Cookie netCookie = new Cookie(cookie.Name, cookie.Value);
    if (cookie.Domain == null)
    {
        netCookie.Domain = HttpContext.Current.Request.ServerVariables["SERVER_NAME"].ToUpper();
    }
    netCookie.Expires = cookie.Expires;
    netCookie.Path = cookie.Path;
    netCookie.Secure = cookie.Secure;
    authCookie = netCookie;
    return true;
}

Success! the report works beautifully. So here’s the tip, when using NT Authentication you need to return both a NetworkCredential() from NetworkCredentials property and fill the output parameters of GetFormsCredentials with a valid AuthCookie (I assume this requirement has something to do with ASP.NET more than Reporting Services itself).

2 Comments

Dispatcher where have you been all my life?

I’ve been working a project for my company dealing with WPF, and while a lot is touted about the cool graphics, the amazing 3D visuals, as a developer on of the simplest, yet most rockin’ features of this presentation framework is it’s threading model. When I first heard that WPF was (essentially) single threaded I was most disappointed. That was until I learned what was meant by "essentially". WPF uses a Dispatcher class which acts as a wrapper for a Thread, the power of this class comes with two pieces of functionality. A DispatcherPriority enumeration and PushFrame(). DispatcherPriority allows you to specify whether the work to be done on the UI thread is more urgent than displaying the UI itself (which it rarely is if your doing stuff on the UI thread).  The benefit of this becomes more apparent when you learn that if you use WPF’s DependencyObject as a base class for your data objects, that all your data objects must be created the UI thread. Hang on.. that’s a detriment not a benefit… now when I de-serialize from disk have to do it on the UI thread. This is the stumbling block I hit when coding our application. I was faced with two options either invoke the de-serialize on the UI thread or not use DependencyObject. Well DependencyObject makes data-binding work properly (for the first time in the history of any UI framework I might add) so I wasn’t about to do that. The alternative… Dispatcher.BeginInvoke(DispatcherPriority.Background). 

If you’ve worked with Windows Forms you’d realise that using BeginInvoke on the UI only partially solves your problem the whole block of code you invoke still locks the UI thread and then so does the corresponding UI update that inevitably happens next. The only benefit of BeginInvoke in WinForms is you aren’t waiting around for the UI to start running the code. But with the magic of WPF, the Dispatcher dispenses with this issue because the Data-binding code that occurs for it is automatically scheduled after you’ve changed the fields on the object. This means you get a super-responsive UI as your objects are created and added to a ListView for example as my code (which loads a single object) exits without waiting for a UI update, data-binding takes care of it at some later point.

All this led me to create a new type of threading component called the ForegroundWorker, based on similar principles to the BackgroundWorker where you call RunMultipleAsync(IEnumerable<T>) and the worker splits up the work to be performed on each object separately, By calling the DoWork function on the foreground thread.  This lead to massive performance improvements in my UI and I highly recommend doing this if you have to work with Serialized DependencyObjects.

I could go on and on about how Dispatcher "just seems" faster and better than Thread.Start or ThreadPool.QueueUserWorkItem, and how I got major performance improvements using DispatcherTimer over Timer. But that’s enough rant from me for one day.

Leave a comment