Jon Kruger -
  • About Me
  • Blog
  • Values
  • Presentations
About Me
Blog
Values
Presentations
  • About Me
  • Blog
  • Values
  • Presentations
Jon Kruger
Agile, People

Beyond the code

If you’re a developer, why do you do the work that you do? What’s the goal of all of the frameworks, databases, code, and tests that we swim in every day? I’ve been doing this professionally for ten years now, and I’ve noticed an interesting progression, and it wasn’t one that I had pursued originally.

Early on, I wanted to work with new technology. The goal was to do cool stuff with the latest technology and find new, better ways to do what used to be harder in the previous year’s hotness. Working at a consulting company was great for this. I got to do new projects every 6 months that often were greenfield and we usually got to pick the technology. Now we were smart about it and we weren’t just doing “resume builder” projects where to tried to use some new framework for the wrong purpose. We were delivering value. Everyone would always hope that they would land on that cool project using the latest stuff, and whoever wasn’t on said project would want to talk to everyone on the project and see what they were doing.

Two years ago I joined a Ruby on Rails project and spent a year in the Rails world. This was the pinnacle of hot technology (at least at the time). I loved how elegant the Ruby language was, the Ruby gem ecosystem, and the Ruby community’s focus on quality and testing.

Eventually my time on that team came to an end and I came back to .NET. I have nothing against .NET, but in terms of geek cred, many people would consider .NET a step back from Ruby (but that’s not the point).

What I noticed from my transition to Ruby and back is that no matter what the technology, the code isn’t what’s important. What is really important is how we interact with users and how we can structure our process and teams to best deliver quality software in less time. We need to value people over the tools that we’re using.

The longer I’m in this business, the more I realize that software development is all about people. It’s about using technology to help improve the lives of the people who use our software, that somehow we can use our coding skills to help them be more successful at their job. It’s about the people that we work with on our team, it’s about helping them feel everything that comes along with working alongside others to help the team achieve a common goal. It’s about looking out for those team members who are feeling overwhelmed by their workload and struggling to hold on to their confidence.

I still geek out on code, and I’m still glad that I get to spend most of my workday writing code. The means may be the same, but the ends have changed.

July 6, 2012by Jon Kruger
Design

Emphasizing behavior in your code

Software applications typically deal with two things — data and behaviors. The behaviors of the application use and modify the data and represent the business processes that we model using things like code and databases.

We all know that data is important. Most people think of the data as being very important, and often applications will have a very data-centric feel to them. The app may have some representation of the schema (e.g. using an ORM, creating business objects that mostly have the same properties as a database table). This is all well and good. But many applications struggle because they don’t stress the importance of the behaviors when writing the code.

The Wild West Data Access Strategy

I believe that the following simple rule should apply:

No data should be modified unless some behavior is requiring you to modify it.

If we don’t have some business reason to change data, then we shouldn’t be doing it. I’ll explain this by first showing you how not to do it.

Take ORMs for example. I like ORMs. There’s no reason to write ADO.NET code anymore, there is a much easier way to do data access.

The problem with ORMs is that you can load up any object from the database, change any properties of the object that you want, and then save it. This is very convenient, but too often people don’t make it clear why they are changing the data. You see this when people have huge “manager” classes (e.g. OrderManager) that contains a whole bunch of methods that load, save, and modify data. The problem is that when you have to modify code in those applications, it’s hard to do so because you don’t know what other things might be using that code and it’s not always clear why the code was written in the first place. Sure, maybe my IDE will tell me what methods call my method, but it might not tell me what behavior required that code to be written.

This can get even worse. I’ve used NHibernate on many projects and I’ve gotten to know it pretty well, but NHibernate has this concept of FlushMode. In NHibernate you create a “session” (which is different from the “session” in-memory cache in web frameworks). Within a session, you can load up objects from the database and NHibernate will keep track of what objects are dirty. The default FlushMode in NHibernate is Auto, which means that every time you do anything that accesses the database (be it a call to save or even a query), it will save all dirty objects to the database. This leads to incredibly brittle code. I don’t ever want my data to be modified unless I do it for a very specific reason, and I certainly don’t want data updated when I do a query! (You’re better off with FlushMode.Never, which means that you have to explicitly tell NHibernate to save dirty objects.)

Note: It sounds like I’m ORM bashing here, but I typically like to stay away from stored procs unless I’m doing something that requires SQL (like a complicated search query). I really don’t like any business logic in stored procs because now my application is very tightly coupled with the database. It’s much easier to manage and test business logic in the application code. If you don’t like the heavy handed ORMs like NHibernate and Entity Framework, try “micro-ORMs” like Simple.Data.

A Better Way

How you do your data access actually isn’t the issue here. What I really want to talk about is how to structure your application code to emphasize the behaviors that your applications are doing, which usually involves some data access. Everything needs to driven by some business process that needs to be done. For me, this usually starts with an acceptance test, which may or may not be automated (in my code, it’s usually automated).

Scenario: User deposits money in an account
   Given a bank account
   When the user makes a deposit
   Then the balance should increase by the amount of the deposit

Then I have some class that is going to do this specific task.

public class DepositCommand
{
    public IRepository AccountRepository { get; set; }

    public void Execute(IDepositModel model)
    {
        model.Account.Deposit(model.DepositAmount);
        AccountRepository.Save(model.Account);
    }
}

On my current project, we like having lots of little command classes like this. Each class has a very specific purpose that can be linked back to a business requirement (because we write our requirements using the same command names as the code). We sometimes string a bunch of these commands into a “workflow”, which is nothing more than a series of commands run to complete a larger task.

Back in the day, I would just have big classes like “AccountManager” that would have a bunch of methods on it. When I was on a Ruby on Rails project, we didn’t have to use dependency injection (because Ruby is awesome like that), so our business model objects contained lots of methods that would do things, but these model objects could get really really big. In either situation, I prefer creating smaller command or query classes that either modify something or do some query.

All I’m really doing is rearranging around my code, so what’s the big deal? It’s much cleaner with command classes in my opinion because that class has one specific task. Those command classes often have private methods that help do the work. If I had a huge AccountManager class or a big model object in Rails, it’s not always clear which private methods go with which public methods, or what might be affected if I change them. In a small command class, if I change something in a private method, I know that it can’t affect anything outside of that class. Not only that, everything in my code and my tests is pointing back to some business requirement that is telling me to do something.

What I’ve realized is that the when I place more emphasize on the behaviors that I’m trying to implement in my code, the more I change my code to reflect those behaviors, even down to how I structure my code. By structuring my code in this way, I’m constantly reminded of the behaviors that I’m trying to implement and the reasons why I’m writing the application in the first place.

June 25, 2012by Jon Kruger
Agile

Challenging assumptions

There are many ideas and principles in software development that we believe to be true and often are non-negotiable for us.

Here’s a challenge for you – challenge the assumptions that you have. What if they’re not true?

For example (not that I believe any of this, just throwing it out there):

  • What if TDD is a waste of time?
  • What if estimating in hours is better than estimating in story points?
  • What if pair programming is an inefficient use of your development team?
  • What if pair programming is the most efficient use of your development team?
  • What if a relational database is not the best way to store data?
  • What would happen if you developed a given feature and put it into production without QA testing it at all?
  • What if sitting in a co-located environment is less valuable than being able to sit in a cube with less distractions?

Like I said, I don’t necessarily believe anything I just said. I’m just trying to make your blood pressure rise a little bit when you think about some of your core principles being false.

The reason I think that this is a valuable exercise is that it forces you to think outside the box and honestly evaluate the way you do things. Most of our core principles depend on the situation. That’s why I get frustrated when people take a prescriptive process like Scrum and say that you have to follow the Scrum rules exactly as they’re laid out or you’re introducing “scrum-buts” into the process. If you haven’t adapted your process to fit your team and your environment, that would be a red flag to me that you might not understand your process or that your not trying hard enough to find ways to improve.

I don’t want to ever stop improving. I’m not going to be naive and think that I have everything figured out. At one point I thought that Windows Forms
data binding was awesome, and after that project was over, I realized that that was the totally wrong approach.

I really took to heart a quote that someone said at CodeMash a couple years ago, “If you don’t ever fail, you’re not trying hard enough.” It’s OK to fail, and when you do, you’ll learn something from it and come out a better person. But if you’re never willing to fail or too scared to consider that maybe your way is not the best way, you’re not going to take that next important step.

May 7, 2012by Jon Kruger
Uncategorized

My new marketing material… er, resume

I’ve talked about it for a long time, but I finally refactored my resume. I read a lot of resumes, and most of the time they annoy me because I get annoyed by the way that it’s written, even if the candidate is qualified. Yet my resume was more or less the same thing, so I figured I needed to take my own advice and do something about it. Here’s the thought process that led me to the end result (which you can see here).

Selling services

Go to any tech conference and you get the big bag of vendor pamphlets trying to sell you their product or consulting services. These papers are very colorful and attractive and professional looking. What you don’t find is a black and white piece of paper with a list of 50 bullet points that enumerates their achievements.

We really are no different from those companies. We are trying to sell our services to potential employers or clients. So why aren’t we making our resumes look more like marketing material?

When I read a resume, I pretty much know whether I want to hire someone or not. The interview is just there to confirm my assumptions and potentially break the tie between two candidates. So if your resume is poorly done, you’re already behind the 8-ball before I even get to talk to you.

Answer the right question

Most resumes are answering the wrong question. The question to answer is not, “What did you do?”, the question is, “What sets you apart from the other candidates?”, or, “What experience that you have that can help our team/company improve?”

If you’re a QA person, don’t put “Entered bugs into bug tracking system” on your resume. That is something you did, true, but (a) I assume that a QA person uses a bug tracking system and (b) it doesn’t tell me anything about how you can help my team.

More is less

The way I see it, there are two kinds of people reading your resume. There are those who are briefly glancing at it to decide if they want to learn more. There are those who want to learn more and/or interview you and they will read more of it. No one ever reads it all.

With that in mind, only put things on there that you want someone to read. I know that sounds obvious, but apparently people are not good at it. You want to make it easy for the people glancing over your resume to want to read more, and you want to make it easy for the people doing the interview to find what’s important.

Everything on your resume has a value — but that value can be negative. When I read a resume before an interview, I read through the last couple work assignments and cross out everything I read that doesn’t add value. Then I’m left with the statements that have value. I would’ve much rather just read the good stuff without having the black out all of the cruft.

Also, I don’t really care what you did in 2003. Chances are you were using a technology that is not the technology being used in the job you’re applying for. Just tell me the things that have relevance, either because it’s a similar skill to what the team needs or because it’s something that you did relatively recently.

No more than 2 pages

I’ve never found anything meaningful on page 3 of a resume, so don’t have one. You don’t have to list every place you’ve worked and you don’t have to list every single thing that you did there. This is particularly challenging for consultants because we tend to move from project to project. Remember, you just have to give me enough information to make me want to work with you, you don’t have to tell me your life story.

Write it so someone would want to hire you for the job you want

If I think about my ideal project, it would probably involve Agile, TDD, either .NET or Ruby on Rails, and working in a team environment with people who care about their craft. I tried to make my resume reflect that. On the first page, I highlight how I’ve led Agile projects, I do TDD training and like unit testing and acceptance testing, and how I’ve used Ruby on Rails and ASP.NET MVC, which is my .NET tool of choice. I put a link to my GitHub account because people who tend to think like me like to see that developers hack on stuff and like to be able to look at actual code they’ve written. I also have a link to my blog so that people can learn more about the things I like (and don’t like). While I don’t claim to be great at design, I’ve tried to add some flair so that people can see that I am creative and am capable of thinking outside the box, which I think is an important quality for a software developer.

I actually went through this process when I created the first page of my resume. I made sure I highlighted all of the important stuff that I mentioned and left off everything that was not on that list. There’s room on page 2 for the other less important details.

Things I don’t want to do are nowhere to be found on either page. I’ve done C++, WebForms, and TFS build server administration. I really don’t want to do those things again if I can help it, so I’m not going to list those things anywhere. The people hiring someone for my ideal job wouldn’t care about those things.

Recap

You are selling yourself. There is nothing that mandates that your resume be a sea of bullet points or that you must list everything you’ve ever done. You are much smarter than that, so be creative and come up with your own marketing material. Then walk into the interview knowing that they have the important information they need to want to give you the job.

March 26, 2012by Jon Kruger
Agile

Writing requirements to match your code

I’ve always said that software development is a series of translations — that we need to incrementally translate business processes to business requirements to acceptance criteria to test plans to tests to code to working software. This is why we write acceptance criteria in the Given/When/Then syntax — it’s a common language that developers, BAs, testers, and business people can use to make sure that we’re all speaking the same language. These kinds of requirements define what the system is supposed to do for the business.

All this is good, but there still are problems. Let’s say that your BA writes some requirements and you implement a feature. Several months later, you get a new requirement to change that code, or someone asks you what the code does for a certain feature. How do you find the code for that feature?

Or maybe you have some common validations that happen many times throughout the application. Are your BAs copying and pasting the rules for that validation over and over in the requirements documents?

What seems to be missing here is another layer of translation. We have too big of a jump from our typical business requirements to our code, and no way to map the two to each other. The acceptance criteria tell us what the code should do, but nothing tells us how to do it.

On my current project, they’ve come up with an ingenious way to solve this problem. (I have to preface all of this by saying that none of this was my idea and I can take zero credit for it. They were doing it long before I joined the team.)

Our system does transaction processing with incredibly complicated business rules. All operations are written as command classes and workflow classes (which are a series of commands).

Our requirements are structured the exact same way. In the requirements we have commands and workflows that are named the same as the classes in the code.

Example

Let’s say I’m building an order processing system. Here’s how we might break it all down.

High-level business requirements

When an order is processed, the order total is sum of the cost of the products + tax + shipping. Save the order information and the total price to the database.

Tax depends on where the order is being shipped:
Ohio – 7%
Michigan – 6.5%
Any other state – 0%

Shipping:
If sum of the cost of the products >= 25, shipping is free, otherwise $5.

System requirements

Workflow: Process Order
1. CalculatePriceOfProducts
2. CalculateTax
3. CalculateShipping
4. SaveProcessedOrder

Command: CalculatePriceOfProducts
Total Price = sum of price of each product on the order

Command: CalculateTax
Tax is calculated based on state the order is being shipped to. Can ship to US states only (including DC).
Ohio – 7%
Michigan – 6.5%
Any other state – 0%

Command: CalculateShipping
If total price of products in the order >= 25, shipping = $0
Otherwise, shipping = $5.

Command: SaveProcessedOrder
Save the following information to the database:
– Products in the order (save current price in case the price of a product changes after the order has been processed)
– Tax amount
– Shipping amount

Acceptance tests

We’ll write unit tests for each command. There are 153 different combinations of shipping (>25, =25, <25) and tax (51 states), so our unit tests will cover all of the permutations. We’ll write acceptance tests to cover some of the most likely scenarios.

Scenario: multiple products with total < 25, shipped to Ohio 
    Given an order with the following products:
        | Product  | Price | 
        | Mouse    | 4.00  |
        | Keyboard | 20.99 |
    And the order is being shipped to Ohio
    When I process the order
    Then the tax should be $1.75
    And the shipping should be $5.00
    And the total price should be $31.74

Scenario: one product with total = 25, shipped to Michigan 
    Given an order with the following products:
        | Product | Price | 
        | Mouse   | 25.00 |
    And the order is being shipped to Michigan
    When I process the order
    Then the tax should be $1.63
    And the shipping should be $0.00
    And the total price should be $26.63

Scenario: one product with total > 25, shipped to Indiana 
    Given an order with the following products:
        | Product | Price | 
        | Mouse   | 25.01 |
    And the order is being shipped to Indiana
    When I process the order
    Then the tax should be $0.00
    And the shipping should be $0.00
    And the total price should be $25.01

Why this is awesome

This has made everything so much easier for everyone. Developers and system analysts can easily communicate because we speak the same language. When we get new requirements that change existing code, the systems analysts even specify which commands and workflows we need to change. Now I know exactly where I need to go to change code without having to do any research!

Duplication is bad in code and it’s bad in requirements. When a new workflow needs to be created, they can reference existing commands without having to copy and paste requirements. The commands and workflows are in a big Word document with links so that I can easily navigate around the document.

Because all of the commands and workflows are outlined before we write the code, most of our design work is done for us. I know what classes I need to create. I know the specific things that each command needs to do, and I can easily unit test them. We have some older code in our application from before they switched to writing requirements in the command pattern. These classes tend to be too big and they’re much harder to decipher, partially because I can’t easily figure out how they map to the requirements. Every time we encounter one of these, we want to refactor it to match the requirements.

Estimation has become a lot easier. I can look at each command in a workflow and get a sense of how hard each one is (or which commands are existing commands that I can reuse), and I already know how I’m going to design my code for the most part.

Keeping requirements up to date is a challenge on any project, but this has helped us do a pretty good job of it. But when you have well structured requirements that don’t have stuff copied and pasted all over the place and you can easily compare a class and a section of the requirements with the same name, updating requirements becomes a lot easier.

The command pattern is a good fit for our application, but your app might not lend itself to the command pattern as well as ours. That’s fine, see if you can come up with another pattern if you want. But sit down as early as possible and see if you can come up with a way to structure your requirements and code using the same patterns.

As you can see in the example, we still have acceptance criteria in the Given/When/Then format. The acceptance criteria help define what the system is supposed to do and how we’re going to test it. The business requirements that we write in the command pattern define how the system is going to accomplish those goals. This method has filled that translation gap between business-focused requirements and code and has had a huge impact on our project.

February 28, 2012by Jon Kruger
Agile, QA

Writing requirements with acceptance criteria

Ah, requirements. Gathering requirements is really hard. I’m not a BA, but like most developers, we’ve had to gather requirements at some point. You have to meet with users who might not have enough time for you or might not be able to make up their mind. Then you have to take their ideas and understand the business problem enough so that you can write up requirements. You have to try and find the balance between giving the users what they’re asking for and giving the users what they really need but don’t know it yet. It’s a fine line for sure.

I’m not going to sit here and bash BAs for lousy requirements. I’ve been the one who wrote the requirements only to have a developer mock the requirements (they probably didn’t know that I wrote them or that I was listening, but that’s neither here nor there). I tried really hard and I thought I did a good job. But nevertheless, there were things that I didn’t really think of that the other developers thought of.

Since we know that requirements gathering is hard, what can we do to make sure that we don’t end up with ambiguous requirements, we make it easy to test, and we make sure that we actually give the users what they want?

The key is that we need to find common language that people in different roles can agree on so that we can all be on the same page. Users, BAs, QAs, and developers all think differently and speak different languages. So we need to find a better way to communicate and a better way to write requirements.

The way that we do this is using the Gherkin language, or Given/When/Then format. This goes something like this:

Feature: Transfer money between accounts
    As a user
    I want to be able to transfer money between active checking accounts
    So that I don't overdraw my account
    And I don't have to go to the bank to make the transfer

Scenario: Transfer positive amount
    Given a checking account "A" that has $100
    And a checking account "B" that has $50
    When I transfer $10 from account "A" to account "B"
    Then the transfer should be successful
    Then account "A" should have $90 
    And account "B" should have $60

At the top of the file we have background information about what the user wants to do and why they want to do it. Then we go step by step and identify all of the scenarios in the Given/When/Then syntax.

So what’s the big deal? Aren’t I just writing the same thing in another format? Yes, but the good thing about the Given/When/Then format is that it helps you find the holes in your requirements and think of all the details and edge cases. If you’re requirements are more in paragraph form with some bullet points, it’s really easy to miss things, even if you’re smart and trying to do a good job.

Essentially what we’re doing here is writing test scripts. As a developer, I want to know how QA is going to test my code. Not only that, I can take these scenarios and automate these tests with acceptance testing tools like SpecFlow or Cucumber or with plain old integration tests or unit tests.

What we did here was establish a common language between everyone involved. This will help BAs think in a detailed, logical way that ensures that they don’t miss things in the requirements. This will help developers because they won’t have to write code to hit a moving target or get stuck waiting for answers to requirements questions. This will help testers because all of their test plans get written up front before the development happens, so they don’t get stuck trying to figure everything out on their own after it’s been developed (and the BAs do a lot of their work because they write their test plans for them). Not only that, this gives the development team the chance to automate the tests. This will help users because once we get the Given/When/Thens done, we can take that to the user and ask them to confirm that we’re building the right thing. We’re still using their terminology, and the syntax will help them think of cases that maybe they hadn’t thought of initially.

If you write your requirements this way, if you get everyone involved up front, and if you write your code to make the tests pass, you should be completely done when you finish development. Because you wrote code against detailed requirements that were written without ambiguity in a manner that makes it easy to write tests for it, you should have no bugs (or at least very very few bugs). QA won’t have to spend lots of time afterwards trying to figure out how to test the feature. And hopefully the users are getting what they want.

February 27, 2012by Jon Kruger
TDD, unit testing

When unit tests are better than acceptance tests

In my last post, I talked about how acceptance tests can be more important than unit tests. But clearly there is another side of the coin.

The conventional wisdom is that you should have more unit tests than acceptance tests. This is how I’ve done it in the past (on pretty much every project other than my current one).

A common scenario is a web application that uses an ORM for data access with as few stored procedures as possible. Because I’m using an ORM, my data layer has very little code. I’ll probably write a few basic unit tests and integration tests to test what data layer I have, and I’ll write integration tests to test the stored procs that I have (usually only for queries that need custom SQL).

My data layer primarily contains a really simple repository class that lets me do CRUD operations and get sort of IQueryable so that I can write LINQ queries. (If you’re using Rails, you don’t have to build any of that because it’s all there for you out of the box.) I don’t want my repository methods to have any concept of business logic or specific LINQ queries. Those belong in the business layer. The exception would be any stored procs that I have to have. I’m want to have a really thin data access layer and a fat business layer (yet another reason to use an ORM instead of having lots of SQL code in stored procs).

The business layer is going to contain the meat of the code. This is where I’m going to have a lot of unit tests. Because I kept my data layer so simple, I’m not going to have as many classes to stub out, and when I do, I’m stubbing out simple methods like Save() and Get(), which have no business logic in them.

I also have controllers, which take information from the business layer and return some sort of view model. I’ll write unit tests that verify that that translation happens correctly.

If I have some hardcore JavaScript, I’ll write unit tests for that. If it’s really simple stuff like, “when this radio button is clicked, disable this text box”, I don’t write tests for that. But when you build something that has more logic, you’ll want to test it.

At this point, I’ve tested pretty much everything very extensively. I could add some acceptance tests, which could help me communicate with the business and automate some QA testing. But at the same time, I’ve been on projects where I had excellent unit test coverage and no acceptance tests and it came out just fine. Now, that project was a two-person project with no QA team, so we just trusted our coding abilities and accepted the risk and things came out just fine. The point of saying this is not to say that you should fire your QA team, it just an example of how you can structure your code in a way that will allow you to unit test the code and get it right pretty much all the time.

This is just one example of one project. Your project might be different, with a different architecture, a different team, and a different business. You need to figure out what works best for you.

February 21, 2012by Jon Kruger
Agile, TDD, unit testing

When acceptance tests are better than unit tests

The conventional wisdom on TDD and testing is that unit tests are the preferred kind of tests to write. They help you design your code, and they run fast. Integration tests and acceptance tests are important too, but you should have far fewer of these. They exist so that you can have some end to end tests and to help test things that you can’t easily test with a unit test.

The Automated Testing TriangleYou may have also seen the automated testing triangle diagram, which illustrates how you should have more unit tests than the other kinds of tests and how the unit tests are the foundation of your test suite.

The implication of all of these diagrams and ideas is that this is the best way to do it on every project. But is that true?

I would argue that there are situations where integration tests and acceptance tests are more important than unit tests.

But wait, you say, aren’t you the guy who is always speaking about TDD and the value of unit tests?!? Was that all a lie?

Once again, the correct answer is… it depends!

Take my current project for example. We are writing web services that do back end transaction processing. Our system is very configurable, so we can make the system work very differently based on some configuration tables in the database, and different configurations are used for different types of transactions.

We have a very well defined framework. Even before I start coding a feature, I know what classes I need to create because they were defined up front with a systems analyst. So I’m not really going to get any benefit from TDD designing my code because the design work is already done.

Because the system is so configurable, we can handle new kinds of transactions by inserting new configurations into the database. There is very little coding involved. Sure, I could write unit tests for the configurable components of the application, but unit tests can’t tell me if the system works correctly for my new configuration. The best way to do that is with acceptance tests.

Not only is our framework well defined, we follow the SOLID principles and have lots of small classes that work together. I could write unit tests for all of the small classes, and in some cases I do, but in
most cases I find that the unit tests aren’t testing very much. Not only that, they tend to have lots of stubs and mocks, which makes the unit tests very brittle. Usually the integration tests and acceptance tests are more brittle, in our case, it seems to be the other way around. Nothing seems like a waste of time more than updating an existing unit test that broke because you refactored a seemingly unrelated class, especially when you have a nice acceptance test that is working just fine.

I’ve just shot down many of the positive arguments for unit tests on our project. Because it’s very important for us to test that our system is configured correctly, acceptance tests become very
important.

Well, if I already have a big suite of acceptance tests, do I really need unit tests to test things that are well covered by acceptance tests? Maybe if I have some class that has many different permutations, but if there’s only a couple paths through a class and I’ve covered it with acceptance tests, then I’m just going to skip the unit tests.

We also use stored procedures to do most of our data access. You can’t easily unit test a stored procedure, so we need more acceptance tests and integration tests to take care of that.

We still have about twice as many unit tests as acceptance tests, but that tide is turning. In a couple months, we will probably have twice as many acceptance tests as unit tests.

It honestly took us awhile to convince ourselves that we weren’t doing it wrong based on the conventional wisdom. But when we thought about it it just made sense to do it the way we’re doing it.

The moral of the story is that there are always exceptions to the so-called “best practices”.

February 20, 2012by Jon Kruger
Agile, BDD

Announcing the Columbus ATDD Developers Group

A few of us have been talking and have decided to start the Columbus ATDD Developers Group. If you’re in the Central Ohio area and you use tools like Cucumber and SpecFlow, believe that testing is not just for QA people, or if acceptance test driven development sounds interesting to you, then this group may be for you. This is a developer-focused group, so expect to learn things about how to write code using BDD testing tools, design patterns and practices, how acceptance tests mesh with your unit tests, and other developer topics. QA people are always welcome too, especially the technical-minded ones! Absolutely no experience is required, just come ready to learn.

Testing is not just for QA people, and BDD testing tools like Cucumber and SpecFlow have really helped me speak to business people, BAs, and testers with a common language and automate acceptance testing for my features. This hasn’t all been easy, and I’ve had to learn a new set of workflows, tools, and patterns. I found that I’ve asked a lot of questions about agile testing and BDD tools on Twitter and I’ve called people up when I’ve had questions on how to do things, and having those connections have really helped me out as I work through the learning process.

We are going to meet on the 1st Thursday of the month from 11:30-12:30 at various locations around Columbus. We’ll probably move the group around so that the same people don’t get stuck with the drive every month. This is an informal group so we’ll have open discussions as well as presentations and people showing their code. We want to hear everyone’s questions and ideas.

Our first meeting will be Thursday, March 1 from 11:30-12:30 at IGS Energy in Dublin. We will have an open space style discussion about Adopting ATDD in Your Organization. Some of us are far along down this path and some are just starting out, and we can all learn a lot from each other’s experiences. So come with your questions and ideas to share. And because IGS Energy is awesome, they will hook you up with free pizza and pop.

If you want to keep up with the group, we are in all the usual places:

  • Blog (we’ll post meeting announcements as well as guest posts about ATDD topics!) – http://columbusatdd.wordpress.com
  • Twitter – @ColumbusATDD
  • Google group

I probably won’t post meeting announcements on my blog, so go follow the RSS feed on the blog.

Hope to see some of you there!

February 7, 2012by Jon Kruger
.NET, TDD, unit testing

Changing how I structure unit tests

When I write unit tests, I use the BDD-style GIven/When/Then format so that the tests are descriptive and explain the business functionality that is being implemented. But I’ve recently changed the way that I do it.

Let’s say that I’m implementing bank account functionality and I am writing code to implement the following:

Given a bank account
When I deposit money into the account
Then the balance should increase by the amount of the deposit

The old way

I used to write them like this:

[TestFixture]
public class When_I_deposit_money_into_the_account : Specification
{
    private Account _account;

    public void Establish_context()
    {
        _account = Given_a_bank_account();
    }

    public void Because_of()
    {
        _account.Deposit(10m);
    }

    [Test]
    public void Then_the_balance_should_increase_by_the_amount_of_the_deposit()
    {
        _account.Balance.ShouldEqual(10m);
    }

    private Account Given_a_bank_account()
    {
        return new Account();
    }
}

This style is used by RSpec and many people in the .NET community. I’ve had a lot of success doing it this way, but I’ve always had some complaints.

  • The Given/When/Then phrases are spread out and aren’t in order.
  • We have the Specification base class, which isn’t bad but I think it might confuse new people who know NUnit but don’t know my special base class.
  • If you have a lot of “given” statements, you’re tempted to use inheritance or nested contexts, each with their own level of setup, virtual properties and methods, etc. This is very unreadable and gets unwieldy very quickly.

The new way

This isn’t really a new way, but it’s new to me. I’ve seen it before over the years but I didn’t really start doing it until I joined my current team where they did it this way and I’ve come to like it a lot better than the old way.

[TestFixture]
public class Bank_account_tests
{
    [Test]
    public void Deposit()
    {
        Given_a_bank_account();
        When_I_deposit_money_into_the_account();
        Then_the_balance_should_increase_by_the_amount_of_the_deposit();
    }

#region Helper methods  

    private void Given_a_bank_account()
    {
        _account = new Account();
    }

    private void When_I_deposit_money_into_the_account()
    {
        _account.Deposit(10m);
    }

    private void Then_the_balance_should_increase_by_the_amount_of_the_deposit()
    {
        _account.Balance.ShouldEqual(10m);
    }

#endregion
}

The best thing about doing it this way is that the business functionality is clearly specified at the top of the class and the Given/When/Then statements aren’t spread out all over the place. There are no crazy inheritance hierarchies, base classes, or big setup methods. When I write tests, I just write out the Given/When/Then scenarios in plain text and then use Specs2Tests to generate the test code for me. Then all I have to do is fill in the private helper methods. This is really easy, like filling in the blanks.

Also, I typically hate regions but in this case I find that they work quite well because they hide the helper methods that I typically don’t want to see when I open the class file.

It depends

Obviously there are situations where this is all overkill and you can just write simple tests without Given/When/Then methods all over the place. Just do whatever makes sense. I’ve found that this new-to-me way leads to very readable and easy to maintain tests.

January 18, 2012by Jon Kruger
Page 10 of 24« First...«9101112»20...Last »

About Me

I am a technical leader and software developer in Columbus, OH. Find out more here...

I am a technical leader and software developer in Columbus, OH, currently working as a Senior Engineering Manager at Upstart. Find out more here...