views:

77

answers:

2

I am writing a bunch of integration tests for a project. I want to call each individual integration point method wrapped in a try/catch block so that when it fails, I get some sort of feedback to display, rather than just crashing the app. I also want to be able to time how long the calls take, and check return values when needed. So, I have an IntegrationResult class with some basic description, result and time elapsed properties:

class IntegrationResult
{
  private StopWatch _watch;

  public string Description {get;set;}

  public string ResultMessage {get;set;}

  public bool TestPassed {get;set;}

  public string TimeElapsed {get { return _watch == null ? "0" : _watch.Elapsed.TotalMilliseconds.ToString(); } }

  public void Start()
  {
    _watch = StopWatch.StartNew();
  }  

  public void Stop()
  {
    _watch.Stop();
  }
}

The code I keep writing looks like this:

IntegrationResult result = new IntegrationResult();
result.Description = "T-SQL returns expected results";

    try
    {
      result.Start();
      SomeIntegrationPoint("potential arguments"); //This is the line being tested
      result.Stop();

      //do some check that correct data is present

      result.TestPassed = true;
      result.ResultMessage = "Pulled 10 correct rows";
    }
    catch(Exception e)
    {

      result.TestPassed = false;
      result.ResultMessage = String.Format("Error: {0}", e.Message);
    }

I would really like to be able to just pass the SomeIntegrationPoint method in as an argument and a delegate or something to check the results, but I can't figure out if that's even possible. Are there any frameworks to handle this type of testing, or do you have any suggestions on how I might simplify the code for better reuse? I'm tired of typing this block ;)

A: 

Have you looked into AOP? PostSharp looks like a nice place to start. There is also an example on exception handling aspects.

m0sa
Definitely and interesting piece of software, but I don't think that's exactly what I'm after
scottm
Was going to suggest this too. Wrote something that had the same code that checked if user was authenticated, etc. Used AOP to tag the item as needing authentication, and worked great.
Bryce Fischer
+3  A: 

(I'm assuming this is C#, as tagged... though the syntax was not in the question.)

You can do this. Just change your result class to include:

class IntegrationResult
{
      string Description { get; set; }
      string SuccessResultMessage { get; set; }
      string FailResultMessage { get; set; }

      public IntegrationResult(string desc, string success, string fail)
      {
          this.Description = desc;
          this.SuccessResultMessage = success;
          this.FailResultMessage = fail;
      }

      public bool ExecuteTest(Func<IntegrationResult, bool> test)
      {
          bool success = true;
          try
          {
              this.Start();
              success = test(this);
              this.Stop();
              this.ResultMessage = success ? 
                                      this.SuccessResultMessage : 
                                      this.FailResultMessage;
              this.TestPassed = true;
          }
          catch(Exception e)
          {
               this.TestPassed = false;
               this.ResultMessage = String.Format("Error: {0}", e.Message);
               success = false;
          }
          return success;
      }
       ...

You could then change your code for your tests to:

private void myDoTestMethod(string argumentOne, string argumentTwo)
{
    IntegrationResult result = new IntegrationResult(
                                   "T-SQL returns expected results", 
                                   "Pulled 10 correct rows",
                                   "Wrong number of rows received");
    result.Execute( r=>
    {
         integrationPoint.call(argumentOne, argumentTwo);
         //do some check that correct data is present (return false if not)
         return true;
    });
 }

This can easily be extended to include your timings as well.

Reed Copsey
This is C#, and I can't seem to find any reference to a Callable class. Also, this seems to assume no arguments for the integration point.
scottm
@scottm: I reworked it to include arguments.... You can use closures in the lambdas to include them here...
Reed Copsey
@scottm: Also, if you included the Description + ResultMessage in your IntegrationResult class itself, you could do this simpler, since you could move the description/result/start/stop calls out of the test methods, as well...
Reed Copsey
@Scott: I tweaked this to show you waht I mean - it's much cleaner now, and shorter per test...
Reed Copsey
Cool. Let me wrap my head around it and see if this is going to work for me.
scottm
Exactly what I was looking for
scottm