Article posted on ProjectConnections
TDD vs. BDD? Really? 3
public class AgileSoftwareDevelopmentTest extends TestCase {
public void testShouldBeEvolutionary() {
assertTrue(new AgileSoftwareDevelopment().isEvolutionary());
}
}
So there it is, a test that ensures that Agile Software Development
is evolutionary, TDD style.
Ok, so on to the next example, one of the Ruby/RSpec variety.
describe "Agile Software Development" do it "should be evolutionary" do AgileSoftwareDevelopment.new.should be_evolutionary end endI personally see little difference between the two... Now, with RSpec you can generate the nice readable documentation which, by the way, is totally sweet using the RSpec command spec agile_spec.rb --format specdoc
Agile Software Development - Should be evolutionaryUsing a tool called AgileDox I can get the same results, in fact, BDD was inspired by AgileDox and created by Dan North in order to eliminate some of the confusion and learning curve involved with proper TDD. Let's look at an AgileDox version of the JUnit test to see what we would need to do to the test to be able to generate the RSpec style documentation using AgileDox:
public class AgileSoftwareDevelopmentTest extends TestCase {
public void testShouldBeEvolutionary() {
assertTrue(new AgileSoftwareDevelopment().isEvolutionary());
}
}
See the difference? It's subtle... It's so subtle it's invisible, no changes required.
By simply removing the word test from the system, you get the same
effect.
I have no problems with using the term BDD, in fact I think it is
very beneficial to focus people on what's important in the test. It
unfortunately seems to me that whenever the two are brought up, they
are promoted as competitors in the same space, not as complementary
techniques. I guess I should get over it and tell people I do BDD
using JUnit...
Eclipse to Visual Studio + ReSharper 1
Another keystroke I discovered today:
In Eclipse, I can type Ctrl+/ in order to comment out/uncomment a line of code. I've found a couple of ways to do this in Visual Studio:
- Ctrl+K, C for commenting out a block and Ctl+K, U for uncommenting a block.
- Ctrl+Alt+/ for toggling between commenting out and uncommenting
The latter is a ReSharper key combination which I find I prefer because I don't have to think about it, it just toggles between the two.
Eclipse to Visual Studio + ReSharper
Moving from Eclipse to Visual Studio + ReSharper is proving to be difficult. I thought I would post some of the things I figure out along the way so I won't forget them.
"Show In > Package Explorer"
When editing a file, I sometimes need to view it in the package explorer. In Eclipse, I can press Alt+Shift+W, P, which will activate package explorer and highlight the current file.
In Visual Studio you can achieve the same effect by pressing Alt+Shift+L while editing a file. This changes focus to the Solution Explorer and highlights the current file.
One shortcut down, only about 250 to go...
Standup Meetings Too Large?
We were having a problem with focusing on the stories during the standup meeting so we made a simple change. Moving the whiteboard containing the stories to the standup area. Normally this wouldn't be a problem but because the open workspace is not completely finished, we had to make some adjustments.
That was two days ago... So how did it work? Well, in a nutshell, not as good has we had hoped. As I thought about it some more, I think that part of the problem revolves around the fact that we've got a very large agile team, on the order of 20 or so people at each standup. This causes the standups to be incredibly long. We've ranged anywhere from 20-35 minutes a meeting, and that leads to people getting bored and not paying attention. Not to mention standing that long isn't the most fun thing in the world.
I'm thinking of trying something new. With a team this large, it may be better to focus on discussing the status of each of the stories instead of each individual. Doing so may do a better job of focusing the team on the current iteration's deliverables as well as bringing the meeting down to an acceptable timeframe (10-15 minutes). I see one potential problem with this scenario. By focusing on the deliverables more than the team, some of the team members may slip through the cracks, struggling through problem areas without asking for help, therefore adversely impacting team throughput.
Iteration Focus... It's the little things
Out of the frying pan...
Jott + GTD
Agile Metrics Part 2
In an earlier post, I talked about the burndown/burnup chart used in agile processes to report the status of a project. What I like the most about the chart is that it gives you a simple to use and maintain tool for making decisions about your project.
Suppose we are writing a store management system that focuses on bicycle shops. We know that the software needs to be ready in time for its debut at Interbike 2008. There's just one problem, our burndown shows that we won't be ready until November of 2008, nearly two months after the show.
Decision Time
What we have on our hands is a fixed date project. What can we do to bring the date in by two months? When the date doesn't look good on an agile project, there are generally three proposed solutions:
- Add Staff
- Move the release date
- Cut scope
Of the three, adding staff is usually the worst option. Remember Brook's Law:
Adding manpower to a late software project makes it later.
The next option, moving the release date, depends a lot on context. In our example, being ready for the Interbike show provides a major opportunity for securing new business, so we cannot afford to miss the show.
The final option, cutting scope, makes the most sense for us at this time. Having a prioritized backlog allows us to cut out some of the lower priority features in exchange for having a releasable product ready for Interbike.
Now, what happens if you can't cut scope? So we've got a fixed date, fixed scope project. There's no other option right? We need to add staff... I don't think so, there are other options.
Alternative metrics
At the Agile 2007 conference this year I had the pleasure of hearing from Niel Nickolaisen about his Purpose Based Alignment model. By applying his model to the features in your project, you can gain insight about other ways to bring your project's date in to where you need it to be. In the next part of my post on Metrics, I'll take a look at at how you can use Niel's model to help bring in that date.
Easy(ier) Mock 1
public class StoreTest extends TestCase {
@Test
public void testThatCheckoutSendsPaymentInfoToProcessor() {
CreditCardProcessor processor = EasyMock.createMock( CreditCardProcessor.class );
PaymentInfo pi = new CreditCardPayment( "1234567890123456", "01/2008", 25.50 );
EasyMock.expect( processor.handlePayment( pi ) ).andReturn( "confirmation-code" );
EasyMock.replay( processor );
Store store = new Store();
store.setCreditCardProcessor( processor );
store.checkout( pi );
EasyMock.verify( processor );
}
}
Pretty straightforward, but it's a bit wordy. The first thing we did is use a static import to take care of the requirement to fully qualify the easymock methods. Our test now looks like this:
public class StoreTest extends TestCase {
@Test
public void testThatCheckoutSendsPaymentInfoToProcessor() {
CreditCardProcessor processor = createMock( CreditCardProcessor.class );
PaymentInfo pi = new CreditCardPayment( "1234567890123456", "01/2008", 25.50 );
expect( processor.handlePayment( pi ) ).andReturn( "confirmation-code" );
replay( processor );
Store store = new Store();
store.setCreditCardProcessor( processor );
store.checkout( pi );
verify( processor );
}
}
That's a bit better (less typing), but the next issue came into the picture when we added additional mocks.
public class StoreTest extends TestCase {
@Test
public void testThatCheckoutSendsPaymentInfoToProcessor() {
double orderTotal = 25.50
double receivablesBalance = orderTotal;
CreditCardProcessor processor = createMock( CreditCardProcessor.class );
AccountsReceivable receivables = createMock( AccountsReceivable.class );
Order o = new Order( "123456",orderTotal );
PaymentInfo pi = new CreditCardPayment( "1234567890123456", "01/2008", o );
expect( processor.handlePayment( pi ) ).andReturn( "confirmation-code" );
expect( receivables.add( o ) ).andReturn( receivablesBalance );
replay( processor, receivables );
Store store = new Store();
store.setCreditCardProcessor( processor );
store.setAccountsReceivable( receivables );
store.checkout( pi );
verify( processor, receivables );
}
}
The problem with the above code is that it's easy to forget to replay and verify the new mock, it's three steps instead of one. To resolve this, we turned to Java 5 generics and a new base class:
public class TestCaseWithMocks {
private List<Object> mocksUsed;
@Before
protected void createMockList() {
mocksUsed = new ArrayList<Object>();
}
protected <T> T mock(Class<T> target) {
T mock = EasyMock.createMock(target);
mocksUsed.add( mock );
return mock;
}
protected void replay() {
EasyMock.replay( mocksUsed.toArray() );
}
protected void verify() {
EasyMock.verify( mocksUsed.toArray() );
}
}
Our base class now creates the mocks for us and keeps track of the mocks created by our test. Then, when verifying/replaying the mocks, it will verify/replay them all.
Our test case now looks like the following:
public class StoreTest extends TestCase {
@Test
public void testThatCheckoutSendsPaymentInfoToProcessor() {
double orderTotal = 25.50
double receivablesBalance = orderTotal;
CreditCardProcessor processor = mock( CreditCardProcessor.class );
AccountsReceivable receivables = mock( AccountsReceivable.class );
Order o = new Order( "123456",orderTotal );
PaymentInfo pi = new CreditCardPayment( "1234567890123456", "01/2008", o );
expect( processor.handlePayment( pi ) ).andReturn( "confirmation-code" );
expect( receivables.add( o ) ).andReturn( receivablesBalance );
replay();
Store store = new Store();
store.setCreditCardProcessor( processor );
store.setAccountsReceivable( receivables );
store.checkout( pi );
verify();
}
}
Now, when we add a new mock, we add it in one place, the replay and verify take care of themselves.
Older posts: 1 2