4 Common Follies Made In Unit/Integration Testing

by Donn Felker 3. October 2008 09:19

I was having a discussion with a colleague last week and we got on the topic of unit testing. What unfolded is what stemmed this post... It started like this...

Colleague: "There is no need to test getter's and setter's in a property, because 'I know they work'."

Me: "WHOA WHOA WHOA!! You know they work? How? Please inform me, because I KNOW my code works too, but I also know I MAKE MISTAKES, A LOT OF STUPID MISTAKES... "

The conversation continued and eventually spawned this post ... but before we get started, I'd first like to say I've been burned by all four of these follies, so I know first hand how important they are.

  1. Not Testing Components
  2. Using a shared database
  3. Testing code that depends on external objects
  4. Writing a test stub and not finishing the test

 

1. Not Testing Components

"I don't need to test that, I know they work." - you, me, everyone (at one point in time) :)  

Why its a Folly: A few questions in regards to this should set us up nicely ... Why are you even trying to perform testing of any kind if you're not testing even the basic stuff? This is the REAL SIMPLE stuff that should not be ignored. Seriously, If you write code and you KNOW its solid, then why write tests for it if your so confident? Think about that... That doesn't make sense! WE'RE ALL HUMAN, WE ALL MAKE MISTAKES. That's why. No one's code is perfect. I don't care who you are. Also, what happens after you check in your code and then tomorrow Developer X checks out the code, makes a change to a setter and then checks it back in. How do you know if that did or did not break anything? YOU DON'T.

Example:

Your original code - a simple read only property that returns the order total:

public double OrderTotal { get; } 

 

Developer X's code after he changed it. He added the new "customer level pricing discount" feature that was requested by your boss.

private double orderTotal; 
public double  OrderTotal 
{ 
	get 
	{ 
		if(customerLevel == CustomerLevel.Platinum)
		{ 
			orderTotal = TotalOrderAfterCustomerDiscountAppliedFor(customerLevel); 
		}
		return orderTotal; 
	} 
}

 

Unfortunately, because no test was written to act as a parachute to catch us (to make us fail early) we are now possibly introducing a bug into the system. Also we have no unit test backing up the new business functionality. Unfortunately because "you know it works" doesn't cut it in this case. The QAT team fires up the app and notices the system has some "odd behavior" at certain times of execution. A bug is submitted and you eventually trace down the source of the error to the property accessor change. Oops.

 

What To Do: Test your properties. Its easy, its quick and it will save your *ss in a bind. Trust me, I've been that guy that said "I know this works, its part of the framework." . If you want to make life real easy on yourself you can even set up a ReSharper Template for it. Its not that hard.

 

Notes: For example - I'm not saying to go out and test that the FileInfo class actually does what it says. If your code or the framework offer the ability for a bug to exist, then test for it. Regarless if its there OR NOT. It's your parachute. You don't see skydivers skimping out on their equipment do you? They do have an EMERGENCY pack. Yeah, THEY KNOW their main pack works. But what if it doesn't? We all need a back up plan to help us out.

 

 

2. Using a  Shared Database

At times you will NEED to connect to a database to perform some type of integration testing.

 

Why its a Folly: Most teams that I've worked have begun working from a shared "dev" database. This introduces so many problems with the dev workflow environment that only an example is the best way to describe the madness going on here.

It usually goes like this (you've probably seen this before too):

  • DevA updates a SprocX on the Dev DB server
    • Changes are validated by "running the app"
  • DevB updates a table definition on the Dev DB Server
    • Changes are validated by "running the app"
  • DevA develops some new functionality, runs app to debug and then it breaks on some code that he DID NOT CHANGE.
    • He gets a SQL Exception stating that column "CustomerNo" is not found in SprocX.
      • What? Huh? I just validated this 20 minutes ago. WTF?!
      • He looks at the code, talks to his peers, finds out that DevB had to make a change for Feature123 that made him change the column name to "CustomerNumber".

It's complete madness working with a shared model. DB Objects get overwritten, changed, updated, you name it - it WILL HAPPEN. Murphy loves to come visit during this time. The amount of un-managed change is too much to handle for any team. Following a shared model usually creates far too much friction for any team to succeed in any time boxed environment (and who doesn't live in one of those).

 

What To Do: Implement a Database Sandbox for each developer. In this example we provide a separate development or test database for each developer.

Note: Managing changes in a database is a challenging task all in itself. This can be intensified in any multi-developer environment. Read K. Scott Allen's series on version control for a database.

  1. Three Rules for database work (note the first bolded topic in this post... )
  2. The Baseline
  3. Change Scripts
  4. Views, Stored Procedures and the like
  5. Branching and Merging

 

 

3. Testing Code that depends on external objects (network, file, web service)

Continuing with the previous item, when writing unit tests that depend on an external service (in this case - a database) states that you are making the following assumptions: 

  1. The Network is up and working
  2. The remote machine your connecting to up and running
  3. The database server is running
  4. The database server is accepting remote connections
  5. The database in question is ACTUALLY ON THAT SERVER
  6. The connection string is correct
  7. No one has messed with what you're about to test
  8. and ... the planets align correctly

We're assuming that the database is in the correct state. What if this is a shared environment? What  if someone changed something? What if the network hiccups? Trust me, if it can happen, it will happen. I know first hand because all of this has happened to me.

 

Why this is a folly: Again, you're betting on the fact that 1-7 above (if not more) are going to succeed. What if this is a web service? What types of things are you betting on there?

  1. The network is up
  2. The the Internet connection is up
  3. The remote server is up
  4. The web service address is correct
  5. The web service interface has not changed
  6. The web service in face does what you expect it to do
  7. blah, blah, blah - too much!

The same follies again! A file is no different. Heck, even another class can be this way. Imagine working with a class that requires HttpContext to be available? It would be a mess to try to reconstruct this object graph to ensure that my test result was the same.

 

What To Do: This is a lot harder than it sounds - break your dependencies. Testing is not the only thing you'll get from this. You'll get flexibility, functionality and the ability to become more agile with your software. How do you break your dependencies... implement some dependency injection techniques into your code. After you break these dependencies you can mock them out with fake implementations to streamline your testing.

 

4. Writing a Test Stub & Not Finishing The Test

I'll leave the easy one for last... this one is easy to fix. :)

Ok, I'll be the first to admit, I'm guilty of this from time to time. However, I have become older and wiser and I have now started implementing an initial not implemented exception throw upon the test getting created.

Here's what I'm talking about when we forget (this test will pass):

[Test]
public void Customer_must_be_21_to_drink_booze()
{
	ICustomer customer = new Customer("FirstName", "LastName"); 
	// TODO: Finish Test. Ran out of time this afternoon! :) 
}

 

Why this is a folly: Its not a completed test. It does not do anything.

 

What to do: Here is what I do to eliminate this (this test will fail):

[Test]
public void Customer_must_be_21_to_drink_booze()
{
	throw new NotImplementedException(); 
}

 

 

 

Conclusion

We all make mistakes, I hope that this post helps at least a few people NOT make these mistakes. :)

Currently rated 4.7 by 3 people

  • Currently 4.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET | TDD | Testing

Unit Testing - It's not what most of you think ...

by Donn Felker 19. September 2008 08:37

Unit Testing

Purpose: To test an individual unit of code to ensure that it is working properly.

This is where the most confusion lies, so I'm going to focus the majority of the beginning series on this area. Possibly to the effect of a few posts.

Normally you'll hear a developer say "I have unit tests for this" but in reality the tests are actually integration tests. 

At a very basic level integration testing is the combining of two units that have already been tested into a component where the interface between them is tested. In this sense a component is an aggregate of more than one unit.

Basically - if you're code has outside dependencies, and you're testing the main calling interface (maybe a method), you are probably testing the entire stack beneath the method, in turn testing how the code integrates together. AKA: Integration testing. A full post on integration tests is coming soon...

The trouble comes with understanding how to test individual units of code without testing their dependencies. Code that has tight coupling suffers from problematic testing and is very brittle and challenging to change.

Here is an example snippet of a system via a diagram for reference:

image

At a high level, here's how the application works:

image

Lets look at some legacy code that every single one of us have written at some point in our lives. This will be the code that we are trying to test. This code is located inside of the "CustomerService" shown above.

        public void SaveCustomer(Customer customer)
        {
            customer.EditDate = DateTime.Now;
            var repository = new CustomerRepository();
            repository.Update(customer);
        }

 

Can you write a unit test for this?  No. (Well, that's not 100% true. You can, kind of. But you'd have to be using a tool like TypeMock to do so - which in this exact example would be cheating in regards to OOP in this instance. More on this at a later time.) In this case - to ensure a unit test was secured around this code you'd have to do the following:

  1. New up an instance of Customer Service
  2. Create a customer
  3. Ensure the CustomerRespository Works (who knows what that means, maybe you didn't write it)
  4. Be sure that everything the customer repository touches in the "Update" method works as well (again, who knows what it does, maybe you're not the developer who wrote it)

The code for the above would look something like this:

        [Test]
        public void UpdateCustomeShouldCallUpdateOnResponsitory_Legacy()
        {
            CustomerRepository repository = new CustomerRepository();
            CustomerService service = new CustomerService(repository);
            Customer customer = new Customer();
            service.SaveCustomer(customer);
        }

 

At this point you've already introduced too many dependencies into your code. If any of these outside dependencies break - our test breaks. In this case our outside dependency is the CustomerRepository. These outside dependencies could be a network connection, a file, a database, a web service, anything. Those are all things we mare NOT trying to test. We're trying to TEST one unit of code, the update call on the repository. I'm wanting to make sure that the customer repositories "update" method gets called with the customer inside of it. I don't actually want the repository code to be called thought. I just want to know that it was called. That's all I care about. I'll write another test to ensure that the value of the customer's edit date was updated properly at a later time. I'll write more tests to ensure that the customer repository works the way it should.

 

How can we fix this?

We can test this unit of code if we follow some basic OOP principles. Mainly dependency injection.

Here's the code refactored. It is far from perfect, but this code will allow you to test in isolation of outside dependencies:

public class CustomerService : ICustomerService
{
    private ICustomerRepository customerRepository;

    public CustomerService(ICustomerRepository customerRepository)
    {
        this.customerRepository = customerRepository;
    }
    public void SaveCustomer(ICustomer customer)
    {
        customer.EditDate = DateTime.Now;
        customerRepository.Update(customer);
    }
}
In this case we can inject our dependencies (customer repository and customer) as interfaces. In the test through the use of a mocking framework we can then mock out and stub our calls to the customer repository and call expectations on them. The test would look like this:
    [TestFixture]
    public class CustomerServiceTests
    {
        MockRepository mockery = new MockRepository();
        private ICustomerRepository customerRepositoryMock;
        private CustomerService customerService;
        private ICustomer customerStub;

        [SetUp]
        public void Setup()
        {
            customerStub = mockery.Stub<ICustomer>();
            customerRepositoryMock = mockery.DynamicMock<ICustomerRepository>();
        }


        [Test]
        public void UpdateCustomerShouldCallUpdateOnRepository()
        {
            With.Mocks(mockery)
            .Expecting(delegate
            {
                Expect.Call(delegate { customerRepositoryMock.Update(null); })
                .IgnoreArguments().Repeat.AtLeastOnce();
            })
            .Verify(delegate
            {
                customerService = new CustomerService(customerRepositoryMock);
                customerService.SaveCustomer(customerStub);
            });
        }
    }

At this point we're only testing one unit of operation, therefore this is a "unit test".

Testing code that is similar to the legacy code shown above is not going to be a unit test. If you were to wrap a test around the legacy code you would be creating an integration test.

It will "look" like a unit test but what its doing is actually integration testing. This is because you would be inferring that all the other pieces of the code are going work as expected.

This is not necessary true. Trust me ,I've been down this road.

 

Problems arise when you begin to make these assumptions about your dependencies. In my experience I've had the following happen:

  • The database is down - TEST FAILS
  • The database is in an unknown state - TEST FAILS
  • The network is down - TEST FAILS
  • The file is not available - TEST FAILS
  • The file is locked - TEST FAILS
  • The file is read only - TEST FAILS
  • The SMTP Server is not up and running - TEST FAILS
  • The web service is not responding - TEST FAILS

 

All of these instances also bring up good problematic areas that you should test for. Utilizing proper OOP and Unit tests will allow you to simulate these events so that you can code for them in your application.

 

 

Review

 

What we are not doing here:

  • We are not testing the whole stack from top to bottom.
  • We are not testing two classes together.

 

What we are doing here:

  • Testing one logical piece of code.
  • Executing a Unit Test.

 

Popular Testing Frameworks:

Popular Mocking Frameworks:

 

Recommended Reading:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

TDD | Testing

Testing For Developers Series

by Donn Felker 19. September 2008 08:25

Over the next few weeks I'm going to cover some topics will help alleviate the pain of understanding the difference between different tests in application development.

The series will consist of the following articles:

Disclaimer: I've had to explain this so many times that I figured I might as well type it out on my blog and send people the link to save myself time and to give friends a place to bookmark for reference. Also, these topics carry quite the heavy controversial and opinionated crowd - to the point where some people have vastly different opinions on what each of these topics actually mean (and some people WILL disagree with me and I'm ok with that). These are my opinions that I have gleaned from my years in the field utilizing various testing methodologies.

As a developer, when you're first getting into testing your code via a testing framework you will start to notice that testing terms are thrown around like they're ingredients in code soup. Unit, integration, functional, acceptance, regression, load, etc... WHOA, hold the phone buddy. What the ...?!?! Confusion sets in immediately. You probably have an idea of "what" you want to do but you're not sure of the actual name for it.

A lot of time developers will say "yeah, there are unit tests backing it up" when in fact those unit tests are actually  repeatable "integration tests". This is completely fine if this is what they meant to do. But unfortunately they don't know what they are saying and they're probably confusing themselves as well as their peers. I'm hoping this series will act as a reference for some people who are just getting started in testing from a developer standpoint. By no means is this a be-all/end-all series for testing, it is just meant as a springboard for developers just getting started. Testing (TDD in general) has a huge learning curve as it requires quite the paradigm shift to get started. This series will be refined as I find ways to improve it and it will be updated throughout time.

The end goal of this series is to help newcomers to the testing world identify the differences between the types of testing. I will also provide some examples of how to test in each of these scenarios (some more than others) and I will provide information about some of the tools that you can use in each of the testing categories.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

TDD | Testing

Resources from Desert Code Camp

by Donn Felker 3. June 2008 04:10

This past weekend I presented the topic "Intro to Dependency Injection and Inversion of Control" at the Phoenix Desert Code Camp. A big thank you goes out to everyone who attended. It was such a popular topic that it actually moved up to the largest room in the conference location, the Theater at UAT! Thanks again everyone!

At the bottom of this post are the resources from this presentation.

 

Resolution from Error During the Presentation

For those of you were present when I ran into an issue with this "DynamicMethod" error, I have figured out the issue. It's a bug in Unity. It looks like its been fixed and should be available in the next release.

image

I was able to work around this issue by moving the Dependency attribute into the Interface. I have updated the code in the download below to reflect this.

 

Presentation Resource Download

 

Full Solution Download (900K)

PowerPoint Presentation

You can also view the presentation online - located here.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET | Dependency Injection | Events | TDD

Intro to Microsoft Unity - Dependency Injection Container

by Donn Felker 25. May 2008 19:40

 

Note: A full solution is supplied at the bottom of this post if you would like to download it and run it.

A couple of days ago Matt wrote about the new Unity Application Block. The Unity MSDN article describes Unity as:

The Unity Application Block (Unity) is a lightweight, extensible dependency injection container. It facilitates building loosely coupled applications and provides developers with the following advantages:

  • Simplified object creation, especially for hierarchical object structures and dependencies
  • Abstraction of requirements; this allows developers to specify dependencies at run time or in configuration and simplify management of crosscutting concerns
  • Increased flexibility by deferring component configuration to the container
  • Service location capability; this allows clients to store or cache the container

Designing a software system architecture with loosely coupled components makes life easier in the long run. A few of the benefits of loose coupling are : maximizing testability, modularizing components, and increase the maintainability of the code.

This is a simple introduction into Unity that exemplifies the simplicity of the container setup. I will cover two options for type registration:

  1. Manual Method based type Registration
  2. Configuration file (XML Based) type Registration

 

The Example Application

The application that is included at the bottom of this post is visualized via the class diagram below. This simple application utilizes very simple implementations of the repository, mapper, domain model, data transfer object (DTO) and service layer patterns for example purposes.

The application follows a very simple flow as shown below:

image

 

The console application calls into the Service layer which calls into the repository to get the data which calls into the DB. A domain object is created from the Repository call, which is passed up to the service layer. The Service layer returns a DTO via the DTO Mapper to the parent caller (the console app) and then the console app displays the customer name via a write line call.

None of these layers have any inter-dependent dependencies coded inside of them. I'm using constructor injection to inject dependencies into the calling object.

Once unity is set up, it will find the dependencies and supply them to the program at runtime. Therefore, if I need a ICustomerRepository for the service layer to work properly, Unity will give the Service layer a CustomerRepository instance. Since CustomerRepository inherits from ICustomerRepository Unity is able to make this link (once you've set it up) and supply the proper instance.

Class Diagram

image

 

The Setup & Code

The easiest way to see HOW Unity works is to get into the code. My recommendation is to download the sample below, fire it up in Visual Studio and set some break points to see how the code is interacting. Seeing is believing!

Before Unity can supply your application types at runtime, you have to tell Unity WHAT you want it to supply and where to find it. This can be done multiple ways as described here. Today we will go over manual configuration inside of the console app, and xml configuration.

Manual Configuration

image

The manual configuration that I've utilized here utilizes the fluent interface of the container.

Explanation of code: Here we are telling Unity to register a type. We're saying "If someone requests ICustomerRepository, give them an instance of CustomerRepository. If someone requests ICustomerDTOMapper, then give them an instance of CustomerDTOMapper. ..." and so on.

 

 

Using the Container From Manual Configuration

After you've set up the types of objects the container should resolve, you can then ask the container for a instance of "ICustomerService" and then invoke a method call on it. At this very point in time Unity will give you the CustomerService, and then when the customer service needs a repository Unity will then give it a instance of CustomerRepository, etc. At this point in time, everything is mapped for you behind the scenes. The only thing you have to do is ask for the first object and Unity will walk the dependency graph and fill in the blanks for you (if as long as you've given Unity the proper types it needs).

Here's how to do this in the code:

image

 

 

 

XML Configuration

XML configuration utilizes an external XML file (app.config/web.config) to create its dependency graph. This allows for a lot more freedom in what you would like to do with your app. If you're not happy with a certain version of "ICustomerRepository" you can create a new one, drop the DLL in the bin folder and change this config file to point to the new one and you're done. No recompiling!

In this implementation I'm using the app.config file because this is a Console App for example purposes. The full schema for XML configuration can be found here on the MSDN.

To utilize the XML configuration you'll need to utilize a custom config section. You can do this by placing this code into your config section of your app.config file:

image

Next, you'll need to add the container and type definition as shown below (this is just a snippet, full code is included at the bottom of the post):

image

The container gets its types from the config file at runtime.

Each type is declared in the config file as the "type" of object to find and the "mapTo" defines which object to return when the "type" is requested.

The type definitions are declared as type, assembly.

 

 

 

 

 

 

Using the Container From XML Configuration

To force Unity to use the XML Configuration you have to perform few extra set up steps in the application code as shown below. Essentially you're telling Unity that it's configuration/mappings are stored in a config file. The config section configures the container for you, as shown below.

image

To have Unity resolve an instance, its the same as the manual configuration option above. Here is the same image from above that displays how to do this:

image

 

 

 

 

Conclusion

Overall, using Unity as quite simple for this example. The docs on MSDN were pretty good, however I didn't really like the examples that were contained with the download because they did not show you how to utilize XML configuration as I wanted to. It didn't take but a few minutes to figure out what I needed to do. I think Unity is a decent solution at this time. I plan to investigate further into the depths of Unity to see if it may possibly be an alternative for my favorite container tool, Windsor Container.

 

Download The Code For This Post

FooTheory.UnityExample.zip (~477K)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET | Agile | Dependency Injection | TDD

TIP: Utilizing Fluent Syntax with the &quot;Is&quot; Keyword in Rhino Mocks and NUnit

by Donn Felker 23. May 2008 10:13

Rhino Mocks and NUnit both have a "Is" keyword, both used for a fluent style of syntax. Unfortunately this causes testing problems when you need to use them together. The .NET compiler can only understand one "Is" keyword at a time. We can't use both unless we full qualify the second one.

Having said that, I've fully qualified the "Is" keyword for Rhino Mocks and NUnit before and I find it clunky and I feel its a code smell to me.

In the figure below an example of a fully qualified "Is" keyword for Rhino Mocks is declared.

1 [Test] 2 public void ExampleTest() 3 { 4 // ... items ommited for brevity 5 6 With.Mocks(mockery) 7 .Expecting(delegate 8 { 9 Expect.Call(databaseMock.GetStoredProcCommand(null)) 10 .IgnoreArguments() 11 .Constraints(Rhino.Mocks.Constraints.Is.NotNull()) 12 .Return(databaseCommandStub); 13 }) 14 .Verify(delegate 15 { 16 IQuery query = ExampleResultQuery.GetInsertResultQueryFrom(someparameter); 17 IDatabaseCommand command = query.PrepareCommandUsing(databaseMock); 18 Assert.That(command, Is.SameAs(databaseCommandStub)); 19 }); 20 }

On line 11, we can see the fully qualified name: Rhino.Mocks.Constraints.Is.NotNull() method called.

This, my friends, is a code smell (IMO).

 

How To Fix

The NUnit testing framework provides a "Iz" syntax helper that VB.NET developers use because "Is" in VB.NET is a keyword.

Since we're using .NET Managed code we can use the Iz keyword and it will achieve the same results as Is did. Therefore we can use the Is keyword in Rhino Mocks and we can use the Iz keyword in NUnit. This saves a lot of key strokes over the course of a day.

Final Example:

1 2 [Test] 3 public void ExampleTest() 4 { 5 // ... items ommited for brevity 6 7 With.Mocks(mockery) 8 .Expecting(delegate 9 { 10 Expect.Call(databaseMock.GetStoredProcCommand(null)) 11 .IgnoreArguments() 12 .Constraints(Is.NotNull()) 13 .Return(databaseCommandStub); 14 }) 15 .Verify(delegate 16 { 17 IQuery query = ExampleResultQuery.GetInsertResultQueryFrom(someparameter); 18 IDatabaseCommand command = query.PrepareCommandUsing(databaseMock); 19 Assert.That(command, Iz.SameAs(databaseCommandStub)); 20 }); 21 }

Please note: Line 12 has the normal "Is.NotNull()" call from Rhino Mocks, and Line 19 utilizes the Iz syntax helper from NUnit.

I find this much easier on the wrist. :)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET | TDD

The Importance of Unit Testing WCF Attributes

by Donn Felker 7. May 2008 10:04

Normally unit testing is used to verify that state is being altered as expected and interactions are occurring as expected (state based testing or interaction based testing). We also write integration/functional tests to ensure that layers and components are working together correctly in the overall picture.

While in the field I've noticed that most tests neglect the attributes of the WCF ServiceContract. Shouldn’t these be tested as well? Yes, they definitely should!

You may say .... "OperationContractAttribute  is just an attribute that indicates that this method is part of a service contract in a WCF application, so why do I need to test the attribute?" 

Good question... consider this scenario:

You're the developer on a large enterprise system and you've created a WCF Service that handles processing sets of data. Depending on the parameters, this data can take hours process. Therefore you've decided to implement the "IsOneWay" attribute value on the OperationContractAttribute.

Is One Way explanation:

Use the IsOneWay property to indicate that an operation does not return a reply message.
...
If the IsOneWay property is set to false (the default), even methods that return void result in a reply message. In this case, the infrastructure creates and sends an empty message to indicate to the caller that the method has returned. (Using this approach enables the infrastructure to send SOAP faults back to the client.) Setting IsOneWay to true is the only way to cancel the creation and dispatch of a response message.

 

Why Testing IsOneWay Matters

Now that you've set the IsOneWay value to true in your service, the calling applications can fire off a request and let the service crunch away on the request (remember, in this scenario, it may take hours to complete). This is an expected behavior of your service - having the method return as soon as its sent without waiting for a response message from the service.

Fast forward 4 weeks .... Joe Developer decides to remove the "IsOneWay" value (which in turn changes it to false, which is its default) because its not working for his new application as he expects. Everything works for him now, and he checks in the code to source control. Everything builds on your continuous integration environment. All tests pass, everything looks golden.

The new service updates and application updates get applied to production and almost immediately users start complaining about another line of business application "freezing up" when they click a certain button.

"All of a sudden, when I clicked the <Load Data> button, the application just froze. I just left for lunch and when I came back everything was normal. Now, its doing it again. I'm not sure what's going on. This application sucks."

You check the app logs, event viewers, traces, etc and then realize that the application IS WORKING but it stops for quite awhile at the service call. The weird thing is that the code does not throw any errors, it just takes forever to return from that call. This problem seems to be a performance problem. If you're not careful this problem could masquerade itself as another probelm in your mind:

"Is the network slow?"

"Is the service down?"

"Is it doing a retry?"

"Are all the packets getting transmitted?"

The list could go on and on.

The Reason For the Slow Down in the App

Why is the app performing so poorly at this service call? Because IsOneWay was set to false (default when not preset in the attribute values). The app that was written 4 weeks ago expects IsOneWay set to true so it does not block the current thread waiting for a response from the service call.

Since the call is set the value of IsOneWay is set to false, the application is now hanging.

How To Prevent This

The continuous integration environment should have had a test for this. Either unit test or integration test. Unfortunately it did not, and in most companies I don't see a test for this kind of thing, ever.

To fix this we need to implement a unit test for this attribute. We need to make sure that it is set to TRUE so that we dont break anything.

 

Code

Below is the code to implement the test for the IsOneWay attribute value.

FooTheory.WcfServiceExample.cs  - The service we need to test.

1 using System.ServiceModel; 2 3 namespace FooTheory.WcfServiceExample 4 { 5 [ServiceContract] 6 public interface IFooTheoryWcf 7 { 8 [OperationContract(IsOneWay = true)] 9 void Execute(); 10 11 } 12 }

The Unit Test

FooTheoryWcfContractTests.cs

 

1 using System; 2 using System.ServiceModel; 3 using FooTheory.WcfServiceExample; 4 using NUnit.Framework; 5 using NUnit.Framework.SyntaxHelpers; 6 7 namespace FooTheory.WcfExampleTests 8 { 9 [TestFixture] 10 public class FooTheoryWcfContractTests 11 { 12 private readonly string ONE_WAY_METHOD_NAME = "Execute"; 13 14 [Test] 15 public void Execute_Should_Be_OneWay() 16 { 17 object[] atts = typeof (IFooTheoryWcf) 18 .GetMethod(ONE_WAY_METHOD_NAME) 19 .GetCustomAttributes(false); 20 21 OperationContractAttribute opAttribute = 22 (OperationContractAttribute) Array.Find(atts, 23 delegate(object obj) 24 { 25 if (obj is OperationContractAttribute) 26 return true; 27 return false; 28 }); 29 30 Assert.That(opAttribute, Is.Not.Null, 31 "Could not find the attribute connected to the method that is needed."); 32 Assert.That(opAttribute.IsOneWay, Is.True, 33 "Method should be marked as IsOneWay for Application X"); 34 } 35 } 36 }

Code Explanation

The unit test uses reflection to get the attribute of OperationContract and then it checks to see if its not null and also checks to see value of the IsOneWay property.

 

Conclusion

If either one of these asserts fail, the build will break in the continuous integration environment. This will let the dev's know that something they did broke an expectation on the service contract. Catching this type of problem early in the cycle can help immensely. Not only does it save time, but it saves money in both dev time as well as end user time.

If you don't catch this early on, you could be calculating the costs of lost time of a couple of devs as well as numerous end users who are using the dependent application(s). If you're using this Service in a SaaS approach, you could really been in some hot water with those clients that utilizing your service. No one wants to use a service that is unreliable.

So, remember, test early and test often! Get those WCF Attributes under test!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET | TDD | WCF

Beginner Test Driven Development Habits

by Donn Felker 23. March 2008 10:28

Having worked on quite a few teams where I've been the lead responsible for helping implement TDD or been an Agile Coach - I've seen a group of habits develop when teams first start utilizing TDD. These are ...

 

1. No test isolation

All functionality that is being tested is in one test. Tests are heavily over specified.

How to fix: Spend some time pairing with the developers that are having the issue. Help explain why we want to break tests apart into smaller units, aka: "UNIT" tests. Let them know that we do not want to test the entire class in one unit test. Just because it can be done doesn't mean it should be done. Ya know, I COULD drive into oncoming traffic, but its just not a good idea. :)

 

2. Failure to recognize the TDD Mantra tddcycle

Most  new TDD'rs will go from Red to Green to - I'm done! Nope. I'm sorry guys, we have one more in that list - Refactor. Let's say it together.  Red/Green/ReFactor, Red/Green/ReFactor :)

How To Fix: Help the developers realize that we want to refactor for a reason. We have a passing test, we know what to expect from our results. Now lets clean up our code, maybe introduce some interfaces, change some variable names, introduce some fields, extract some methods, etc. Doing this allows us to clean up the code as well as have the confidence that our changes did not muck up the expected result. Run the unit tests after you refactor. If it breaks, oops, lets go figure out WHY it broke. We caught the error early, its a lot cheaper now. :)

 

3. The previous lends itself to Insufficient Test Coverage/TDD is my new Debugger

The developers usually will do enough to get the test passing and then move onto the next task. They think of TDD as a new debugger.

How To Fix: Sit down with the developers that have this issue and explain: Just because we can now unit test a method/object and step through it with a debugger doesn't mean that this is the new debugger.  That's not the point. Just because the test passes doesn't mean we're done. Just because your method passes if you pass a valid object into it doesn't mean that its fully tested. What happens if I pass a null object into it? What happens if I pass a new'd up object with nothing instantiated? Have those instances been tested? Have we tested that our objects are interacting as we expect them to? Do we know if the Logger got called? How do we know if we didn't test it?  That its the classic question: How do we know it works, if we don't have a test to prove it?

 

4. No concept of separation of concerns or IoC/dependency injection.

This is not a big deal and I expect it of most new TDD converts. Usually while learning TDD the first few tests do not need DI/IoC, but this is something that will help in the future and will need to be understood to really grasp. This really comes into play when we start separating our concerns and breaking dependencies between objects. The refactoring that takes place here can really get deep into DI/IoC sometimes.

How To Fix: Give them a great intro into interfaces and how they're used. Show them great articles on DI/IoC written by Martin Fowler, Jeremy D. Miller, Ayende, and have them join certain mailing lists such as altdotnet to join in/read the discussions. On that list alone, DI/IoC discussions occur on a daily basis.

5. TDD Complaints

I've seen complaints such as:

    1. It takes too long to write the tests
    2. I write more test code than real code.
    3. The tests are harder to write than the real code.
    4. How is this going to help me get my project done? I can just hit F5 and test it and I can tell if it works or not with my own eyes.
    5. Who cares if it passes a unit test, I'm the only person who works on this project.

How To Fix: This is one of those habits I've seen in every place I've coached. These are classic examples of someone who hasn't "seen the light" of TDD yet. In my experience, the easiest way to help them see the light is to pair with with them while writing unit tests. They will instantly see why the unit tests help them and the team. Every single time I do this I help the TDD newcomer realize that by writing this test they've exposed X bugs that they didn't think about before. It usually goes like this: "Ok, that test passes, what would happen if an empty string was passed into this? Would the DB accept an empty string?" Them: "Oh... good point, I didn't think of that." Instantly lights start turning on. Another thing that works great to help developers see the light is to ensure that you're utilizing Continuous Integration such as CCNET, or TeamCity. Have them create a unit test for a section of code. Check it in. Watch it build and watch unit tests pass. . Then have them change the code (the code which is under test) and ensure it returns a different result. Maybe it returned a user's name, such as "bob", now have it return the users name with some characters appended to the end of it, such as "bob123". Have them check it in, watch the build fail because the unit test failed. Explaining to them that this helps catch errors before the product is live is crucial. Once they have the "Ohhh!! I get it now moment", they won't want to stop writing tests.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Agile | TDD

Gleaning Clarity Through Unit Test Names

by Donn Felker 7. February 2008 20:56

You're unit testing, right? .... right? (If not... shame on you... ) It's known that TDD/nDD types of development dramatically increase the ability to refactor with confidence, increase code readability and help define and enforce business rules (in the tests). Unit testing helps with TONS of things in development (literally the list could go on and on), but what about the unit test names? What do those do for us as developers? 

Predecessors In The Name Game

Roy Osherove has a good post on Unit Test names. Jean-Paul also has tons of good info about unit test names on his blog. I tend to follow these same guidelines. Also - awhile back on the altnet list there was a thread which spawned this post, but unfortunately I could not find it. If I do run across the post I'll augment this thread with the link.

Background

But what about when a bug report comes in? In my work I've used an alternative method so I thought I'd post it here.

  • Lets say the bug report says that "CalculatePayment" is returning the wrong value when the system is in a certain state. This kind of test was completely missed during development. Heck, it happens! Your task is to implement a solution for this bug.
  • Most likely you're going to write a unit test to assert that the solution you specified has been implemented as expected.

 

Naming Convention

When naming these unit tests I will add the word FIX_<WorkItemNumber>_<MethodName>_<StateUnderTest>_<ExpectedBehavior>() as the method name.

Example:

FIX_186_CalculatePayment_WhenRateLessThan1000_ThrowPaymentException()
{ ... }

From this test fixture name I can glean that this is a fix for bug 186, for the CalculatePayment method, for the state when a rate is less than 1000, the method should throw an exception. I've now documented my code as well as created a very readable and understandable unit test name.

I know this is not something everyone wants to do or would do, but in certain companies I've worked at this has helped with work item issue resolution and tracking.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

TDD

Frustrating MS Test Issue - blah blah blah is not trusted

by Donn Felker 18. November 2007 19:01

I'm not going to lie, I'm a NUnit guy. I've used it for years. But just recently I've decided to start using MSTest. I run Team Suite and I've been using it for some basic integration and functional tests, but not full on TDD. Well this weekend I embarked on a task that utilizes full on TDD and I decided to make the jump and try to do it with MS Test.

So the first thing I had to do was reference and import Rhino Mocks. I then ran the test real quick (I had a test that did not depend on mocks yet) to make sure nothing in the import broke it (it shouldn't, but hey, I'm ADD when it comes to this TDD business). To my utter amazement, something broke. I was seeing red.

This was the beautiful error:

Microsoft.VisualStudio.TestTools.TestManagement.ExecutionException: Test Run deployment issue: The location of the file or directory '(path omitted)\main\Source\SharedBinaries\Rhino.Mocks.dll' is not trusted.

WTF? It's on my local machine. It's not a file share, hell, its even included in my project in my SharedBinaries folder. WTF MAN!?

After some looking around, I was able to figure it out.

If you download a DLL from the Internet, or get it in an email or where ever and you saved it to your disk (including a DLL in a zip too) it has some extra info attached to it called an "AES" file. (see my reference below for more info)...

To fix this annoying issue, go to the DLL, right click and then click "Unblock". See the screen shot below. Once that is done, your test will work.

unblockdll

 

Source: MSDN Forums

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET | Agile | ASP.NET | TDD

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

About the author

Donn Felker

Senior Consultant
MCTS
ScrumMaster
Agile Practitioner

About Me | Books I Recommend

Gotta Pay The Bills


Tag cloud

    Popular Posts

    RecentComments

    Comment RSS

    Calendar

    <<  December 2008  >>
    MoTuWeThFrSaSu
    24252627282930
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    View posts in large calendar