Showing posts with label TDD. Show all posts
Showing posts with label TDD. Show all posts

Monday, 17 February 2014

Implementing Specification By Example

Recently I have had the pleasure to work with different teams and companies. The interesting part of seeing how different people work is that I learn a lot from their codebase.  At my current work we follow the concept of specification by example, however these specifications are often a pain point for our teams. I wanted to take the time to explore some successful ways of implementing specification by example.

Background


There are many terms that have been described for these sets of practices that I won't go into. However I think specification by example is the better term, as we tend to describe software via interactions (or examples). To get yourself up to speed I will recommend two great books on the topic:


Recommendations


Below will be a set of topics that I believe are important in having good specification by example. Please take them as a recommendation and not as a rule. I also encourage you to challenge these recommendations to find better ones.

Language


The biggest thing I find when writing these features is the language that is being used. We have to remember that the language that we use needs to reflect the domain we are trying to model. Often I encounter that these features are written through the eyes of the computer.

What we have to remember when writing these features is to focus on the WHAT not the HOW. A great friend of mine has done a fantastic job explaining how to do this. I urge you all to read it.

The language is really important. Try to get other people to read it and get them to explain what the example is trying to do.

Pick your battle


Follow the guidelines of the testing pyramid. Often I see people complain about their tests taking too long and being brittle. Remember that the UI is brittle at times, however in my view the end-to-end test is the most important one. If you can comfortably test a layer below it then go ahead. Use your judgement.

Informative Steps


Often I have seen that some information is missed out because there is no action for that step. This should be avoided. It does not matter if a step performs an action, if it helps with the intent write it in.

Behind the Scenes


Here is the big thing that I think people get wrong (of course this is my opinion). When writing features we seem to forget that we need to still apply all the great concepts we do for our main application. The biggest thing here is knowing what layer does what.

Usually when writing these features, people tend to dump all of their code into the steps file. This quickly becomes a nightmare to manage. Here are some guidelines I have used to make sure this becomes easy to follow:

  1. The steps should only contain the builders and expectations.
  2. Use the concept of a PageObject pattern. If you want a great library use dill.
  3. Limit the use of the World. This just becomes a massive god class.
  4. If you find yourself writing similar code, move it to a reusable module that all your projects can use.
Remember: Treat your test code the same way as your production code.


Creating Preconditions


Often we need to create a precondition (the given step in gherkin speak). What I have found is that people create a table where the key of that table is put through a mapping of the property of the model. This should be avoided. One of the worst things that you can do is create a translation layer. DDD has a concept of Ubiquitous Language, I suggest that you follow it.

Watch your Failures


One of the most underrated techniques I see is that people don't look at the failure message. How often have we seen expected true but got false. These errors don't help. Make sure you get a failing scenario first and read the message. Does it make any sense? Could you diagnose the issue?

Conclusion


These patterns have served me well in the past so I wanted to share them with you all. Feel free to challenge them so we can all learn to do things better. Of course context is king. So if you have any specific examples you would like discussed feel free to share.

Tuesday, 23 April 2013

In-Memory POP3 Server in C#

Background


Today I had a requirement where we needed to download a message from an email server via POP3 and convert it to another message format to be used in a CMS.

As anyone that knows me testing is very important so I wanted to find a way to create an in-memory POP3 server. The reason for this was I wanted a way to test different kinds of messages that needed to be saved in the CMS and not rely on an actual physical server. So after searching for a while I realised that there wasn't much out there so I decided to write my own.

Implementation


I created a gist that shows you the specs that I wrote. An example spec looks like this:



It("should get a message with OpenPop.NET", () =>
    {
        using (var client = new OpenPop.Pop3.Pop3Client()) {
            client.Connect("localhost", 110, false);
            client.Authenticate("test", "test");

            var message = client.GetMessage(1).ToMailMessage();
            message.From.Address.Should().Be("dzs@iname.com");
        }
    });



The email message that I used to test looks like the following:


Return-Path: <dzs@iname.com>
Received: from iname.com (localhost [127.0.0.1])
        by localhost.localdomain (8.8.5/8.8.5) with ESMTP id RAA01110
        for <dzs@localhost>; Sat, 3 Jan 1998 17:46:55 -0800
Sender: dzs@localhost.localdomain
Message-ID: <34AEEA0E.71EA3BCC@iname.com>
Date: Sat, 03 Jan 1998 17:46:55 -0800
From: Doug Steinwand <dzs@iname.com>
To: dzs@localhost.localdomain
Subject: Test Message

Here's the body of my test message

 - Doug

The actual implementation is in the following gist. The library that I chose to use was LumiSoft.Net as it already had an implementation of a POP3 server (it just needed to be extended).

The interesting part is that for some reason the library AE.Net.Mail (which was the one we wanted to use at work) does not work. I get the following error:


1) should get a message with AE.Net.Mail
   Failure/Error: System.IO.IOException: Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.


So I will probably be replacing it for one of the other client libraries.

This is a quick way to enable a POP3 server in memory and I hope this helps someone else in a similar position.

Saturday, 9 March 2013

Lean Projects - Part 2


So some people will read the previous blog and say why are you being so negative? See I don't see it that way, I see it as a place that has a great culture that wants to embrace change and continuous improvement. I also see this as massive opportunity to try out some of the ideas that I will present. A lot of these ideas are not new topics, however they have been tailored for the environment that I am in.

The concept that I am calling this is Lean Projects. A way for us to embrace lean and agile methodologies in an agency environment.


Kanban


Kanban is a method for developing software products and processes with an emphasis on just-in-time delivery while not overloading the software developers. In this approach, the process, from definition of a task to its delivery to the customer, is displayed for participants to see and developers pull work from a queue.

The thing to note from the above statement is that Kanban works on the concept of a pull model.

Visualise Workflow


As stated above, one of the challenges that we face is to visualise our workflow. One way to get started is to map the value stream. The idea behind value stream mapping is to sketch out how you are working as this will help everyone to understand how the process works.

From this visualisation we can create what is called a Kanban board. The idea behind this board is to have a way to show your team what your value stream looks like. An example of a board looks like this:

This board is the single point of truth for everyone working on a product.

If you would like to know how to manage a process of the Kanban board, please read my previous blog Launching Australia's Biggest News Site

Limit Work In Progress


The most important part of the Kanban process is to limit your WIP.

In Kanban, we don’t juggle. We try to limit what we are doing, and get the most important things done, one by one, with a clear focus. It’s not uncommon to find that doing ten things at once takes a week, but doing two things at once takes hours, resulting in twenty things being done by the end of the week.

A great explanation can be found here Why Limit Work In Progress?


Measure and Manage Flow


The important aspect is to make sure that each of the features that is on the board actually goes through to the last step of your flow. We set limits to make sure we don't start picking up more features than the ones already started.

Some teams have the concept of stop the line, where the team gets together to make sure the pipeline clears up for the next features to be pulled in.

Fortunately Kanban has a few ways for us to measure the pipeline, as without measurement we can't improve on things.

Cumulative Flow Diagrams


This diagram is an area graph that depicts the quantity of work in a given state, showing arrivals, time in queue, quantity in queue, and departure. This is a great way to visualise how we are churning features through our work flow.


Lead Time


The term lead time (LT) is just a fancy way to say time to market. It’s essentially the time that elapses (on the calendar) from something is ordered until it is received. In software development, a feature is ordered when someone (like the product owner) asks someone else (the team) to implement it. The same feature is received when it is deployed to the production system and ready to be used by end users.

Why is this important? Well, we can track how long a feature took. This is a really powerful metric, as it can be used to eliminate the entering of hours spent into a system.

How can this be used in Lean Projects? Well when I estimate I always like to estimate in terms of effort, meaning that it is easier for me to think about how easy/hard something is rather than how long it will take. This effort for me is measured using t-shirt sizes, e.g. S, M and L. Now if we start tracking all the features that have been sized using a t-shirt size we can start measuring the lead time for each of these features. We can then take the average of the lead time and this amount can be used to drive the estimates of the next feature.

Make Process Policies Explicit


As mentioned on wikipedia:

Until the mechanism of a process is made explicit it is often hard or impossible to hold a discussion about improving it. Without an explicit understanding of how things work and how work is actually done, any discussion of problems tends to be emotional, anecdotal and subjective. With an explicit understanding it is possible to move to a more rational, empirical, objective discussion of issues. This is more likely to facilitate consensus around improvement suggestions.

LeanKit has a great example of how this can be achieved.

Feedback Loops and Improvement Opportunities


The way to improve this is to provide a way to have some form of feedback loop. I am big fan of Agile Retrospectives. The idea is to meet at a regular time to reflect on how everything is going. With Lean Projects we need to reflect on how efficient the process is and ask the right questions. The way that we can do that is by using the 5 Why's Technique. A good metric for improvement is reducing lead time, as this will help you deliver all features in a better way.

Remember to listen to your team as they are closer to the problem than we usually are. Usually issues tend to show that it is a process problem not a people problem. Lean Projects are about a bottom up approach.

Your people are your most important resource. Ensuring their support and cooperation is vital for all major projects.

Specification By Example


Specification by Example is a set of process patterns that facilitate change in software products to ensure that the right product is delivered efficiently.Wikipedia summarises this quite well:

Teams that apply Specification by example successfully commonly apply the following process patterns:
  1. Deriving scope from goals
  2. Specifying collaboratively – through all-team specification workshops, smaller meetings or teleconference reviews
  3. Illustrating requirements using examples
  4. Refining specifications
  5. Automating tests based on examples
  6. Validating the underlying software frequently using the tests
  7. Evolving a documentation system from specifications with examples to support future development

So what does this all mean for Lean Projects? Well the basic idea is that we want to find a common language to describe the requirements through as a set of examples. For this work we need to do this collaboratively and to make sure that the requirements don't become stale as they will serve as documentation.

Before we can think of an example, we need to think of the value that we are adding. The best format I have found is as follows:

In order to [business value]
As a [role]
I want to [some action]

The first part is the most important and it should reflect one of these values:

  • Protect revenue
  • Increase revenue
  • Manage cost
  • Increase brand value
  • Make the product remarkable
  • Provide more value to your customers

Also think about the role that this feature is for. The reason I mention this is because sometimes we build a feature for the “Highest Paid Person's Opinion”, which most of the time adds no value. A scenario or example has the following format:

Given [context]
When I do [action]
Then I should see [outcome]

The Given step is where you set up the context of your scenario. Every scenario starts with a blank slate. The When step is where you exercise the application in order to accomplish what needs testing. Finally, the Then step is where you verify the result.

This way of working can be though of as outside-in development. So an example feature would look like this:

Feature: Login

In order to access the website content
As a website user
I need to log in to the website

Scenario: valid credentials
Given I am presented with the ability to log in
When I provide the email address "test@mywebsite.com"
And I provide the password "Foo!bar1"
Then I should be successfully logged in

Scenario Outline: invalid credentials
Given I am presented with the ability to log in
When I provide the email address <email>
And I provide the password <password>
Then I should not be logged in
Examples
| email | password |
| test@mywebsite.com | Foo!bar2 |
| test@mywebsite.com | Foo |

Lean Software Development


Lean software development is a translation of lean manufacturing and lean IT principles and practices to the software development domain. Adapted from the Toyota Production System, a pro-lean subculture is emerging from within the Agile community.

Lean software development plays by seven principles.

Eliminate Waste


Waste is anything that interferes with giving customers what they value at the time and place where it will provide the most value. Anything we do that does not add customer value is waste, and any delay that keeps customers from getting value when they want it is also waste.

Some forms of waste are:

  1. unnecessary code or functionality
  2. starting more than can be completed
  3. delay in the software development process
  4. bureaucracy
  5. slow or ineffective communication
  6. partially done work
  7. defects and quality issues
  8. task switching

Build Quality In


The idea here is to start with the frame of mind that quality is important and needs to be done from the start. Your goal is to build quality into the code from the start, not test it in later. You don’t focus on putting defects into a tracking system; you avoid creating defects in the first place.

Extreme Programming is an excellent example of building quality in, some examples are:

Pair Programming


Pair Programming is an agile software development technique in which two programmers work together at one workstation. One, the driver writes code while the other, the observer, reviews each line of code as it is typed in. The two programmers switch roles frequently.

Test Driven Development


Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: first the developer writes an (initially failing) automated test case that defines a desired improvement or new function, then produces the minimum amount of code to pass that test, and finally refactors the new code to acceptable standards.

Continuous Integration


Continuous integration (CI) is the practice, in software engineering, of merging all developer workspaces with a shared mainline several times a day.


Refactoring


Code refactoring is a "disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behaviour", undertaken in order to improve some of the nonfunctional attributes of the software. Advantages include improved code readability and reduced complexity to improve the maintainability of the source code, as well as a more expressive internal architecture or object model to improve extensibility.

Create Knowledge


We have all been in the situation where we have only one person that knows the codebase. There will always naturally be individuals that are stronger than others in specific areas. This is what makes great cross functional teams, however having only one person know something is what is called a single point of failure.

It is important that the whole team has an understanding of how the system works, so that we can eliminate single points of failure. However this is easer said than done as not everyone is always interested in every aspect of every system.

The following provide great ways to create knowledge:


Defer Commitment


Emergency responders are trained to deal with challenging, unpredictable, and often dangerous situations. They are taught to assess a challenging situation and decide how long they can wait before they must make critical decisions. Having set a time-box for such a decision, they learn to wait until the end of the time-box before they commit to action, because that is when they will have the most information.

Basically we want to decide as late as possible, specially for irreversible decisions.

Deciding too early, you run the very likely risk that something significant will have changed, meaning your end product might meet the spec, but it might still be the wrong product! This is one reason why so many projects fail.

Deliver Fast


If we can deliver software fast that means we can get real feedback from actual users, which is the reason you are building the feature in the first place. Another really great side effect of delivering software fast is that you would have had to solve the way you release your features. In order to release quickly means that you need to do it in a repeatable way, this means automation. The way to achieve this is through continuous delivery.

Continuous delivery is a pattern language in growing use in software development to improve the process of software delivery. Techniques such as automated testing, continuous integration and continuous deployment allow software to be developed to a high standard and easily packaged and deployed to test environments, resulting in the ability to rapidly, reliably and repeatedly push out enhancements and bug fixes to customers at low risk and with minimal manual overhead.

Respect People


I think it’s important to treat everyone with the same respect, whatever their job. It doesn’t matter whether they’re the CEO, a developer, project manager, the receptionist or the cleaner, respect everyone equally.

This comes back to the bottom up approach, giving people the responsibility to make decisions about their work. It is important to build knowledge and develop people who can think for themselves.

Respecting people means that teams are given general plans and reasonable goals and are trusted to self-organise to meet the goals. Respect means that instead of telling people what to do and how to do it, you develop a reflexive organisation where people use their heads and figure this out for themselves.

Optimise The Whole


A lean organisation optimises the whole value stream, from the time it receives an order to address a customer need until software is deployed and the need is addressed. If an organisation focuses on optimising something less than the entire value stream, we can just about guarantee that the overall value stream will suffer.

Looking at the whole picture is important. In the past I have spent time just optimising the development practices, however I believe that if you don't love what you are building then what is the point. We should all care about the overall value stream.

Final Thoughts


All of these thoughts have been going around in my head for years and I am truly excited to put these ideas to work in such a vibrant environment. I look forward sharing my findings as I love to see how all these thoughts change over time.

Friday, 1 March 2013

System.Spec - Specifications By Example in C#

System.Spec


I am a big fan of TDD and when I first started doing it I was accustomed to using NUnit in C#. Then I started learning Ruby and fell in love in how they were doing TDD/BDD. The gem they use is called RSpec.

For a while I was jealous that we did not have something as cool in C#. There is NSpec, however for me if did not read that well.

So I decided to create System.Spec. We are currently using at the place I work at and we are really enjoying it. As we continue dogfooding this solution we will build more features into it.

An example specification looks like the following:

namespace YourCompany.Specs
{
    using NSubstitute;
    using System.Spec;

    public class ImportantSpecification : Specification
    {
        protected override void Define()
        {
            Describe("A very cool specification", () => {
                It("should do something that is good", () => {
                    var testInterface = Substitute.For<ITestInterface>();
                    testInterface.Received().TestMethod();
                });
            });
        }
    }
}

As you can see there is some C# ceremonies that we need to take into consideration, Ruby allows for a much cleaner syntax. It follows closely the design of Jasmine.

Moving Forward


The following is what I plan doing in the coming weeks/months:

  1. Add a runner for ReSharper
  2. Add a runner for VS 2010
  3. Add a runner for Xamarin Studio (if possible)
  4. Allow reordering of tests.
I urge you to look at the solution and if you have any thoughts or enhancements just yell out.