Home ::  Admin

chris carter's web log

Crazy Hack of the Day

3:29 PM Friday Mar 16, 2007 Comments: 0

Today, with a suggestion from the USDA Breakmaster, I completed an amazing hack, that I'm really pretty proud of.  We're trying to move an application to the .NET 2.0 framework.  It was a nobrainer conversion, and it was all but deployed until we found a bug a boo in one of the pages that interfaces with another web application.  Invalid Cast Exception...blah blah blah.  The other application(ASP.NET 1.1) pops up a browser window pointing to a page in our site(now on the 2.0 runtime).  It does some stuff in our site, and when they are done the "OK" button gets pressed.  The "OK" button is on our site, posts back to our site, does some other stuff, sets some hidden variables in the codebehind, then writes out some javascript to run when the page loads that looks like this:

document.forms[0].action = "http://someotherside.com/somepage.aspx";

The net effect is that our page posts to another site. Well, .NET 1.1 viewstate apparently does not like .NET 2.0 viewstate.  There are some workarounds that didn't work for us, or we weren't patient enough to figure out how to get them to work.  Either way, the hack we came up works, and it's just as bad as the problem it's solving.

The first take of this hack had me setting the __VIEWSTATE variable to an empty string.  That hack was NOT well received by the other application.  The Breakmaster suggested getting the viewstate from the 1.1 page first, then substituting that for the 2.0 viewstate.  It's a little confusing but it actually worked.  Right before we do the post to the other site, we request the page from the other site, parse out the __VIEWSTATE contents using nothing but string manipulation, then do something like this on the 2.0 site:

document.getElementById('__VIEWSTATE').value = 'the viewstate we scraped from the 1.1 site';

Anyway, the entire solution is ridiculously stupid, and I successfully made it even more stupid, it was a good day...

Breaking the Ice

8:41 PM Thursday Mar 15, 2007 Comments: 0

I was inspired by this blog post titled breaking the ice to start my retro-testing effort at my day job today.  I was determined to get something tested in a monster of application I created and now maintain.  Zero percent code coverage was the start of a good day of testing. 

Since this is crappy old code(jeez, it's almost 2 years old!), it's very difficult to test parts of it without being required to consume some external resource, a database, a webservice, the filesystem, whatever.  So I made the executive decision that I would use two test projects for now, one I call IntegrationTests and one called UnitTests.  IntegrationTests are anything that needs to read a config file, hit the database, or any external resource.  UnitTests are not to utilize any external resource and will not have a config file.

There's a certain comfort factor that I forget exists when you test you code.  I mean if I've passed a null, empty string, zero, or some other kind of bad input to a method and accounted for all possible scenarios for why a method may fail, I feel complete and successful.

I finished today's round of testing with 27 percent code coverage. I was really excited until I realized that that was 27 percent code coverage on one massive class :( Definitely NOT what I was going for, but hey, at least I broke the ice...

Here Ya Go: Example Sh*t Test Code By Yours Truly

7:19 PM Tuesday Mar 13, 2007 Comments: 0

I stumbled onto this one today, way too much going on:

[Test]
public void VerifyCanMockSubsidiaryProcess()
{
  MockRepository mocks = new MockRepository();
  IList participants = new ArrayList();
  Participant participant = new Participant();
  participant.CoreCustomerIdentifier = 666;
  EntityOwner owner = new EntityOwner(participant);
  owner.CoreCustomerIdentifier = 777;
  participant.Owners.Add(owner);
  participants.Add(participant);

EligibilityContent[] expectedParticipantResults = new EligibilityContent[1]; expectedParticipantResults[0] = new EligibilityContent(); expectedParticipantResults[0].EligibilityTypeCode = "HEL"; expectedParticipantResults[0].Eligibility = "Y"; expectedParticipantResults[0].CertificationValue = "Compliant";

EligibilityContent[] expectedOwnerResults = new EligibilityContent[1]; expectedOwnerResults[0] = new EligibilityContent(); expectedOwnerResults[0].EligibilityTypeCode = "HEL"; expectedOwnerResults[0].Eligibility = "Y"; expectedOwnerResults[0].CertificationValue = "Really Compliant";

SubsidiaryEligibility subel = (SubsidiaryEligibility)mocks.CreateMock(typeof(SubsidiaryEligibility), null, null, null); Expect.Call(subel.GetEligibility(participant.CoreCustomerIdentifier, participant.TaxIdentification, participant.TaxIdentificationTypeCode, 2007)) .Return(expectedParticipantResults); Expect.Call(subel.GetEligibility(owner.CoreCustomerIdentifier, owner.TaxIdentification, owner.TaxIdentificationTypeCode, 2007)).Return(expectedOwnerResults); IMessageData messageData = (IMessageData)mocks.CreateMock(typeof(IMessageData)); Expect.Call(messageData.GetMessages()).Return(getMessages()).Repeat.Any(); mocks.ReplayAll(); MessageRepository messages = new MessageRepository(); messages.Load(messageData); Assert.IsNotNull(messages.DataSource); Assert.AreEqual("SubsidiaryEligibilityFailed", messages[Messages.SubsidiaryEligibilityFailed].Name); PaymentEligibility pe = new PaymentEligibility(null, null, subel, messages); Assert.AreEqual("N", participant.HighlyErodibleLandInd); Assert.AreEqual("NOT FOUND", participant.HighlyErodibleLandCompliance); Assert.AreEqual("N", participant.Owners[0].HighlyErodibleLandInd); Assert.AreEqual("NOT FOUND", participant.Owners[0].HighlyErodibleLandCompliance); pe.UpdateSubsidiary(participants); Assert.AreEqual("Y", participant.HighlyErodibleLandInd); Assert.AreEqual("Compliant", participant.HighlyErodibleLandCompliance); Assert.AreEqual("Y", participant.Owners[0].HighlyErodibleLandInd); Assert.AreEqual("Really Compliant", participant.Owners[0].HighlyErodibleLandCompliance); }

Legacy Code Sucks...Testing it Sucks More

5:28 PM Tuesday Mar 13, 2007 Comments: 0

I'm sick of shitty legacy code.  It seems that it's everywhere and some days, like today, it takes over and makes me feel like shit.  I hate not being able to right click and choose Run Tests... and verify beyond a shadow of a doubt that code works, at least as it was intended to work.

The legacy code I'm talking about is any code I've written or helped to write that is not testable or really really difficult to test.  I'm maintaining a code base at work that grew into a monster.  It has very few tests and changing any code is major pain in my ass and usually ends up introducing new bugs.  Another project I'm working on has similar issues, rules spread out all over the place, no tests to confirm anything, totally sucks.

One thing that is common is that both projects depend heavily on hitting up external resources, database, filesystem, web pages, web services, all of the above.  One of them uses DataTables all over the place, so the consistency and reliability to know what's in it is totally missing, as opposed to just using interfaces or classes.  If you've ever heard of Mystery Meat Navigation, this is the same thing, Mystery Meat Objects, no guarantee on what's inside...

I'm not alone.  Just google for testing legacy code and see many others enduring the same pain.

I've also noticed that some of the tests that I have written are too complicated.  The type of tests I'm talking about are ones that involve complex object models, they make it hard to follow what's actually being tested.

Grrrr... I hate legacy code


Http Post: Programmatically

9:19 PM Monday Mar 12, 2007 Comments: 0

I keep needing this snippet so I figured I'd post this as a reminder to myself:

public HttpWebResponse FormPost(string postData, string url)
{
  HttpWebResponse response = null;
  if (postData == null || url == null)
    return response;

  ASCIIEncoding encoding = new ASCIIEncoding();
  byte[] data = encoding.GetBytes(postData);
  HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
  request.Method = WebRequestMethods.Http.Post;
  request.ContentType = "application/x-www-form-urlencoded";
  request.ContentLength = data.Length;
  using (Stream stream = request.GetRequestStream())
  {
    stream.Write(data, 0, data.Length);
  }     	
  response = request.GetResponse();
  return response;
}

DataTable Code Generator

8:42 AM Sunday Mar 11, 2007 Comments: 0

I hated having to depend on the database being available in order to test out what happens to my page or form when data is retrieved from database.  Many times if I'm working on stuff at home, I won't have access to the database anyway.  So I wrote a little tool that I've noticed also lends itself useful in test driven development as well.  Basically, you can craft whatever the data in your datatable should look like and the code to run this is generated for you.  Copy and paste the code into your project and now you have data to play with while working on whatever feature needed sample data to begin with.  Check it out: datatable-code-generator-1.wmv.  I need to clean up the code a little bit then I'll post the app source for download.

Silly Tool

5:34 PM Saturday Mar 10, 2007 Comments: 0

Recently, it seems as though I need to be able to test connections from any environment. So I made a simple tool that just tests connections and I use it more often then not.  Anywho, the app is about as simple as an app can get but tools like this seem to be the ones I use the most...Here's the code:

using System;
using System.Data;
using System.Data.SqlClient;

public class Driver{
  public static void Main(string[] args){
    try{
      using (SqlConnection cn = new SqlConnection(args[0])){
        cn.Open();
        Console.WriteLine(cn.State);
      }
    }catch(Exception ex){
      Console.WriteLine(ex.ToString());
    }
    Console.WriteLine("Done...");
    Console.ReadLine();
  }
}