• Unit test asp.net with your own MVC pattern

    Making ASP.Net unit testable

     

    So, previously I took a stab at trying to explain (in detail) how to get to some unit testable asp.net code from your legacy code. I failed because instead of explaining the goal, I was explaining the step by step of how to get there.

     

    Let’s set this up for everyone first in a few different ways.

     

    First, let’s talk about what currently exists in your legacy asp.net code and why it becomes impossible for you to test it without opening yourself up for a lot of dangerous changes!

     

    For those who are familiar with UML this should be pretty straightforward. Imagine you have “AccountDetailsPage” in your project and it has the following class structure:

    image002.gif

     

    The difficult part about your code is probably that inside BindData() you’re making some calls to web services, pulling in some account object, binding fields to the labels, maybe storing some stuff in view state or session state, maybe checking against some conditions. Then in FilterGridByDate() you’re maybe iterating through a collection of transactions, removing some that don’t have the right date or getting a new list of transactions from the back end.

     

    There’s three different types of behavior going on here… at least!

     

    Let’s identify them.

    First, there’s the view data/behavior that’s happening… OnLoad(), OnInit(), Session[], ViewState[], all of those labels, the data grid.

     

    Second there’s some specific domain behavior happening, such as the loading of an account object, loading of transaction history objects.

     

    Then, there’s some non-technology specific UI logic that is happening here, such as Filtering by date.

     

    But lastly, and the thing that is probably most difficult to decide what to do when trying to unit test is the operations that are sharing data between those different responsibilities: When we copy stuff from a domain object into the ui objects during binding, when we iterate through domain objects with some UI logic, and when we load something from session or view state into some UI logic or into some business logic.

     

    Let’s take a look at the different areas of concern first and put some names to them.

     

    1. Page Objects: technology specific (ASP.NET)
    2. UI Logic : Non-tech specific (Sorting, filtering, presentation changes)
    3. Business Logic : specific business data being operated on in a way that the business decided. Business rules!

     

    Note: ignore that I’m assuming your business doesn’t dictate your presentation J because they do! (which is why we have to validate against the presentation separated from the technology)

     

    Consider the MVC pattern now:

    http://en.wikipedia.org/wiki/Model-view-controller

     

    Your page Object would become your view, your UI Logic would become your controller, and your business object would become your Model.

     

    How would this play out with our class above and how do we break the joint dependencies?

     

    First of all, let’s create the 3 types we know of for the behavior we know about:

    image004.gif

     

    Now, let’s address the question “How do I test the UI and Business logic without testing asp.net?”

     

    First, the controller is the UI logic so we have to call controller logic from our events/overrides in the page. Let’s look at how we would do that. Pretty simple actually, because it’s OK for our page to depend on the controller (because we won’t be unit testing the page, we can just have a reference to the controller right inside the page!)

     

    That would look like this then:

    image006.gif

     

    Ok, wait a sec though… how am I suppose to set the text on the page INSIDE THE CONTROLLER???

     

    Ok that’s a little more challenging, because we cannot pass the page reference into the controller or then our controller is dependent on the page class and we’re untestable again. What we have to do is resort to using an interface so that we can create a fake page in testing (or a mock). That would look something like this:

    image008.gif

     

    Effectively, we are going to send a page instance into the controller via the interface reference so that it’s decoupled. Then when we unit test the controller logic, we just create a Fake object that Implements the interface and use ‘sensing’ to see if the right values are going into the view. It would look like this in the test harness:

    image010.gif

     

     

    Full story

    Comments (0)

  • Our backlog items are too big!

    A tough situation I think some people face with the most basic implementation of scrum is that their backlog items are too big. Well this backlog item is "Foo" functionality and it delivers no business value without the whole thing so it's all or nothing.

    Is this happening in your organization?

    When we go into sprint planning, we have the opportunity to estimate that backlog item again, mentioning how big it is. Hypothetically let's say your backlog item is sized (relative point size) as 150 and you know your team velocity is 150 points. This means that you will onlly be able to do that 1 backlog item of 150 points that whole sprint.

    So what happens?

    Someone says: Surely you could do more than just that one thing! You got more people than could possibly work on that item!

    Well, yes and no... we have more people than could possibly work on that item, however, we have more item than we could possibly work on with this much iteration length as well!

    So one answer that's out there, which is proven and tested in the field, is user stories.

    Mike Cohn describes user stories in a couple different flavors... the most basic and small sized stories are just called user stories, but when you have something as large as a whole iteration, you're probably dealing with what he calls an epic! Maybe it's bigger than an Epic and it's a whole theme! (i may be getting theme and epic mixed up but the point remains the same)

    An epic is a collection of functionality that represents one functional whole to the user. Take this Epic for example:

    As a web bank user I would like to transfer money from my savings account to my credit card.

    That seems innocuous enough right? Well, maybe... let's look more into it though. Can we identify smaller stories in there?

    As web bank user I cannot transfer more than my available balance from my savings account to my credit card.

    as a web bank user i cannot transfer less than 1 dollar from my savings account to my credit card.

    As a web bank user i can do recurring transfers from my savings account to my credit card.

    As a web bank user i can do scheduled transfers from my savings account to my credit card.

    As a web bank user i can do a minimum balance payment from my savings account to my credit card.

    -=== and so on.

    And just for the sake of mentioning... a theme would be something like

    As a web bank user, i want to transfer funds.

    as a web bank user, i want to pay bills online

    Full story

    Comments (0)

  • Scrum is not a Silver Bullet

    "How does scrum address this issue?"

    I hear this pretty often. The most difficult thing for people to understand is the answer that I give them...

    "Scrum doesn't address problems, it only uncovers them... Scrum has done it's part, now it's your turn."

    Think about this for a second.

    Who do you need to make software in your organization?

    as an example, let's say we need:

    A business analyst/tech writer to write documentation, a tester to work with the business to validate agreements have been met, a programmer to write the code and unit tests, a business person to make decisions about what to make, and a user or user proxy to ask questions about the functionality.

    so i got a ba, programmer, tester, business, and user and i put them on the team and the business guy writes out a list of functionality by priority. The team selects what they think they can do in 30 days. They start working on the highest priority item.

    Day 1: scrum meeting:

    programmer says "i can't write the UI functionality because no one has told me what fields of data we need to have, i'm impeded"

    scrum master says "Who can help programmer do this?"

    business person says "I can do this"

    scrum master says "ok you two are going to get together and resolve this problem"

    That i think is pretty understandable from most everyone in the scrum community right? I have a programming tasks i can't do, something is in my way, the team has someone who can resolve the problem, the team fixes it.

    Here's another example:

    programmer, "I cannot do this part because we're interfacing with a vendor application and they won't settle on what interfaces to use, we cannot get agreement"

    scrum master, "who can help with this?"

    <silence>

    scrum master, "Let's get together after this scrum meeting and decide how we're going to solve this problem".

    the team gets together and makes a decision... they can:

    Get a vendor resource on the team (if they're really lucky)

    cancel the sprint

    remove the backlog item from the sprint (lower it's priority below everything on the sprint)

    ... or maybe they come up with something more innovative (i hate answering questions like these for the team because it limits their creativity).

    To me, this is the mechanics of how scrum surfaces problems and how a team could possibly address them.

     

    Full story

    Comments (0)

  • Scrum: No product owner?

    Are you flailing around without a product owner? I have the simple cure... appoint yourself. Not because you want to be the product owner, but because everyone who really wants to be the product owner will come out of the woodwork!

    In just declaring what the priorities are and watching other people's 'beloved' items fall below the iceberg water line sprint after sprint... you'll get some help in prioritizing. You may even find your strongest candidate for a real product owner!

    Happy Sprinting Agilistas!

    Full story

    Comments (0)

  • Muds, are they dead?

    I use to play a lot of text based games. Even wrote (ok well i hacked an existing) one.

     

    SO i ask, are muds dead? if not, what kind of mud would someone like to play?

    Full story

    Comments (0)

  • Refactoring, my definition

    Recently one of my teammates started refactoring a 2000 line code behind in one of our asp.net pages. When he mentioned that he was going to refactor this page, a few ears perked up. I got the vibe that when they heard the word refactor... they heard "Re-Write" and i felt inclined to jump in and provide a definition for them. Which i stole from Martin Fowler's definitive book on refactoring.

    Refactoring is the process of improving the internal structure of the code without changing the external behavior of the code.

    One of the other team members said "Sure, that's YOUR opinion".

    I'll let you be the judge on that.

     

    Anyhow, I was reading the Fowler book and found a nice little tidbit regarding BIG classes... namingly big UI classes. That works out well since that is what my friend is doing.

    Basically he says if you have a large UI class with lots of instance variables to move those variables over to the domain class.

    Then, he says, if you don't have a domain class... create one!

    Well this probably would work out really well for this particular refactoring project because we have a LOT of domain data going on and all of this should be in the domain class. Unfortunately, we already have 'domain classes' that only have data and no behavior.

    So my thinking is that a good way to do this is to use the decorator pattern to extend them with some functionality while maintaining the data that they have since they're coming from an object provider (n-tier architecture).

    For example, consider this domain class.

        public class Person

        {

            public string firstName;

            public string lastName;

        }

    it's only data. if we wanted to add a method on here, such as "getFullName", we would have to extend this class. However, the problem raised here is that the web service gives us THIS class and we cannot modify that class's structure.

    So let's try the decorator pattern like this:

        public class DecoratorPerson : Person

        {

            private Person _personData;

            public DecoratorPerson(Person personData)

            {

                _personData = personData;

            }

     

            public new string firstName

            {

                get { return _personData.firstName; }

                set { _personData.firstName = value; }

            }

            public new string lastName

            {

                get { return _personData.lastName; }

                set { _personData.lastName = value; }

            }

            public string fullName

            {

                get { return _personData.firstName + " " + _personData.lastName; }

            }

        }

    So now I can get first name, last name, and the new functionality of “fullName” all with the ability to use this object interchangeably where I was previously using the “Person” object.

     

    Full story

    Comments (0)