Showing posts with label luncht. Show all posts
Showing posts with label luncht. Show all posts

Tuesday, February 14, 2012

Luncht S3E4 - Test Driven DESIGN - Chadrick's Take

There is substantial overhead when doing TDD, but the code is better for it and the knowledge transfer is automatic.

Doing things right takes time and a lot of effort.

What I found was my story bullets, what I call Acceptance Tests, were not completely thought out. It's hard to anticipate what you will be testing until you really spend some time focusing on the feature, which includes how the user will use the system, which in turn means views. Because we were unsure of the acceptance tests we started with wire-framing the two views (ForgotPassword & ResetPassword). Then psudo-coded our implementation in the form of comments so we generally know which services would need to be created. Then at the back-end it was a return to TDD to build our services. Eventually this brought us back up front where we tested our controller actions with mocks of these new service(s). It went pretty well I think, but led me to wonder about a few things.

First, most TDD tutorials only test business rules at the domain level (back end). When in reality we are developing our solution in an all inclusive way. Our features, to be complete need a front to back, or back to front (however you decide) implementation. I'm not saying I want to write a bunch of implementation tests, but we have to be looking at a workflow that covers all these pieces and interaction between these pieces, and I don't think we are there yet.

In the real world, is it possible for the business to write valid acceptance tests that we could convert directly to test methods? How does this work where your features are coming from the business who on one extreme wants to design and architect the entire solution, or on the other extreme doesn't have a clue what he/she wants. I think what we realized is that we developers will almost always end up massaging the acceptance tests while we determine more exact requirements.

Tuesday, February 7, 2012

Luncht S3E3, UI Testing - Chadrick's Take

Because our second session was a bit difficult I looked up a Plural Sight video on TDD and ASP.NET MVC. It was a very helpful video and led us to the conclusions I've already wrote in my post on Session Two.

After we decided what not to do, Brian did basically all the plumbing for us to implement Selenium tests against various environments. If we couldn't do a view test with TDD maybe we would do a view test with Selenium. Once the plumbing was done we wrote integration tests to validate we had a Registration page and we worked it all the way through to the Successful Account Creation page.

When we got this far we took stock of things and determined that we need to think of the Controller Action as a contract, and test it accordingly. Together we decided we would not be doing the Selenium tests as part of our TDD workflow at all. The third session was profitable and again we learned what not to do, but we are on our way to much more productive sessions in the future.

Retrospective

At the beginning of our session I felt like I had to dig into the recesses of my brain too much to determine where we left off. Those recesses are deep and dark so something had to change. Brian had the solution. He brought up our session doc and added a quick paragraph to that end. I'm looking forward to seeing if that helps us jump right into the code.

Wednesday, February 1, 2012

Luncht S3E2, Controller Testing - Chadrick's Take

We spent a lot of time writing controller tests and trying to figure out how to get the rendered HTML from Controller.Index() What we didn't understand at the time was that this is not really the way it is designed to be tested. We still learned a lot even though it was learning how NOT to do things.

Basically if you are going to be testing MVC don't try to test the rendered results of a controller action. You can test that the ViewResult has the correct Model and that the View exists by checking for an empty ViewResult.Name, but don't expect to test the rendered HTML. Brian made a good point when he said, "Our views should be stupid. If anything is going to be smart it needs to the be the business layer and the controller needs to know hot to access the business layer." Now that is not word for word, but it's how I heard it. I question if this would be true for heavy client side scripted apps.

Still having a lot of fun with this, so keep an eye out for our future postings.

Tuesday, January 31, 2012

Luncht v.3 - Password Reset

Not sure if we will get to this feature tonight but I'll try to keep one step ahead of our sessions so we are not wondering what is next.

Password Maintenance

As a user I need to be able to reset my password if I've forgotten what it is or whenever I would like to change it.

  • Key Is Created for forgotten Password
    A key needs to be created that will be sent to the user in the form of a link.
  • Key and New Password Required for Reset
    If key does not match we will error out.
  • New Password Will Be Encrypted
    We never want to see the password so the new one will be encrypted.
  • Email and New Password Will Validate User
    If Email and New Password match the user will be valid.
  • If User is Validated Password Can Change Without Key
    If the user is logged in the key is not required for password reset.

I think this is doable in one session. If not it's not a big deal.

Monday, January 30, 2012

Luncht v.3 - Session One - Chadrick's Take

I want to start by thanking Brian for trying TDD & PPP. I knew he had (maybe "has") a tendancy to shy away from pairing and I appreciate his openness to try it.

I also want to thank Dan Tape for throwing out the suggestion that we try Google Hangout for our dev sessions. As far as I'm concerned it's as good, and perhaps better than real life. Now we can base our showering habits wholly on our wives desires to be around us. if you have not tried Hangouts, do it and save some soap.

I had pre-written a feature called 'Registration' with a few bullets of acceptance tests to start with. I was basically following our precompiler format. Then because we are both familiar and fans of Pivotal Tracker I converted that item to a story with tasks for each of the acceptance tests.

Registration

As a user I need to be able to register for a new account so that I can use the system.

  • Required Property FirstName
    User needs to have a FirstName property and it is required.
  • Required Property LastName
    User needs to have a LastName property and it is required.
  • Required Field Email
    User needs to have a Email property and it is required.
  • Required Field Password
    Password field is encrypted once set.
  • Password Field Needs to be Encrypted
    User needs to have a FirstName property and it is required.
  • Default Chat Notifications
    During registration users are will be signed up to receive chat notifications.
  • Default Deal Notifications
    During registration users are will be signed up to receive deal notifications

When we opened Visual Studio we started with a class library project and loaded NUnit and Moq with Nuget. We had one test at first with all the fields in it, but later refactored it so that each prop had its own test.

[TestFixture(Description = "As a user I need to be able to register for a new account so that I can use the system.")]
public class Registration
{
    [Test(Description = "User needs to have a FirstName property and it is required.")]
    public void RequiredPropertyFirstName()
    {
        // Arrange & Act
        const string firstName = "blah1";
        var user = new User( );
        user.FirstName = firstName;

        // Assert
        Assert.AreEqual(firstName, user.FirstName);
    }

    [Test(Description = "User needs to have a LastName property and it is required.")]
    public void RequiredPropertyLastName()
    {
        // Arrange & Act
        const string lastName = "blah2";
        var user = new User( );
        user.LastName = lastName;

        // Assert
        Assert.AreEqual(lastName, user.LastName);
    }
}

As you can see I've started putting the text inside of Description of the Test. I have an idea for a code generator that would build these tests out with an [Ignore] attribute on them. I might write about this in a future post. But as you can see we build our tests based on the required acceptance tests. Understand properties are not the sexiest of tests to write and perhaps a bit overkill, but it's TDD and we are 100% sure when done means done.

For most of this session we just did domain object tests. They were very basic and that allowed us to practice the Red >> Green >> Refactor Ping Pong Pairing workflow. For those of you who don't know what that is I'll give a quick run-through.


  1. I start by writing a failing test. We decided our code had to compile so we had to create what was necessary for that to happen. I pushed the code to BitBucket for Brian.
  2. He implemented the code to make the test pass and then checked it into HG and pushed it back to BitBucket.
  3. We talked through things if necessary and refactored it accordingly.
  4. Now it was his turn to write the failing test, so we jumped down to the next bullet.
  5. I implement...
  6. He refactors...
  7. ...repeat

I was happy how it went. I'll let Brian give his own take on it.