After much anticipation, Maven 2.1.0 has been released. My personal favorite new feature is the parallel downloads of artifacts. This alone should significantly speed up builds on CI servers that refresh the repo on each build.
Go get yours today.
If you're new here, you may want to subscribe to my RSS feed. Thanks for visiting!
March 23rd, 2009 @ 1:19 pm by Nayan Hajratwala | Posted in CI, Maven | No Comments
My sister’s book is now available on amazon. Go check it out!


February 24th, 2009 @ 11:52 am by Nayan Hajratwala | Posted in Uncategorized | 1 Comment
I started using OCMock yesterday, and was quickly hit by a problem when trying to stub out return values.
My test method was (sorry for the lack of highlighting - the plugin i’m using doesn’t support Objective-C)
- (void)testReturnsStubbedReturnValue
{
id mock = [OCMockObject mockForClass:[NSString class]];
[[[mock stub] andReturn:@"megamock"] lowercaseString];
id returnValue = [mock lowercaseString];
STAssertEqualObjects(@"megamock", returnValue, @"Should have returned stubbed value.");
}
However, when running it, I would get the error:
warning no '-stub' method found
warning no '-andReturn' method found
After scrolling through all the OCMock test code, I finally was able to get it work by adding:
#import <OCMock/OCMock.h>
That’s where the methods are defined, but not being an Obj-C guru, I don’t fully understand how the code knows it’s actually using the OCMock class, etc.
Anyway, it appears that the minimal code needed to get an OCMock test running is (i wish this was on their web site!):
In OCMockSampleTest2.h:
#import <SenTestingKit/SenTestingKit.h>
@interface OCMockSampleTest2 : SenTestCase {
}
@end
In OCMockSampleTest2.m:
#import "OCMockSampleTest2.h"
#import <OCMock/OCMock.h>
#import <OCMock/OCMConstraint.h>
@implementation OCMockSampleTest2
- (void)testReturnsStubbedReturnValue
{
id mock = [OCMockObject mockForClass:[NSString class]];
[[[mock stub] andReturn:@"megamock"] lowercaseString];
id returnValue = [mock lowercaseString];
STAssertEqualObjects(@"megamock", returnValue, @"Should have returned stubbed value.");
}
@end
I hope this helps someone!
February 19th, 2009 @ 4:35 pm by Nayan Hajratwala | Posted in Uncategorized | No Comments
I was asked recently why I like Maven so much. Here’s why:
I’m pretty sure there’s more I like about Maven, but these are the ones that came to me right away.
February 12th, 2009 @ 12:26 pm by Nayan Hajratwala | Posted in Uncategorized | No Comments
I’m working on the Ruby Koans by Edgecase which has been a really nice way to introduce myself (again) to Ruby. It’s the right mix of hand-holding and “solve-it-yourself” problems.
I just finished the about_proxy_object_project.rb Koan, and while it works, I fear that I’ve fairly well mangled Ruby, and there are probably infinitely more elegant ways to do this. My code looks like Java transcribed into Ruby.
Anyway, here is the code. If you have some spare time, take a look and see what I could have done better. I wrote the Proxy class, the rest was supplied.
# Project: Create a Proxy Class
#
# In this assignment, create a proxy class (one is started for you
# below). You should be able to initialize the proxy object with any
# object. Any messages sent to the proxy object should be forwarded
# to the target object. As each message is sent, the proxy should
# record the name of the method send.
#
# The proxy class is started for you. You will need to add a method
# missing handler and any other supporting methods. The specification
# of the Proxy class is given in the AboutProxyObjectProject koan.
class Proxy
class MessageLog
attr_accessor :message_name
attr_accessor :count
def initialize(message_name)
@message_name = message_name
@count = 1
end
def increment_count
@count = @count + 1
end
end
def initialize(target_object)
@object = target_object
@messages = []
end
def method_missing(method_name, *args, &block)
if @object.respond_to?(method_name)
increment_message_count(method_name)
@object.send(method_name, *args, &block)
else
super(method_name, *args, &block)
end
end
def increment_message_count(message_name)
message_log = called?(message_name)
if message_log.nil?
@messages < < MessageLog.new(message_name)
else
message_log.increment_count
end
end
def messages
@messages.collect { |message_log| message_log.message_name }
end
def called?(command)
matched_message_log = nil
@messages.each do |message_log|
if message_log.message_name == command
matched_message_log = message_log
end
end
matched_message_log
end
def number_of_times_called(command)
message_log = called?(command)
message_log.nil? ? 0 : message_log.count
end
end
# The proxy object should pass the following Koan:
#
class AboutProxyObjectProject < EdgeCase::Koan
def test_proxy_method_returns_wrapped_object
# NOTE: The Television class is defined below
tv = Proxy.new(Television.new)
assert tv.instance_of?(Proxy)
end
def test_tv_methods_still_perform_their_function
tv = Proxy.new(Television.new)
tv.channel = 10
tv.power
assert_equal 10, tv.channel
assert tv.on?
end
def test_proxy_records_messages_sent_to_tv
tv = Proxy.new(Television.new)
tv.power
tv.channel = 10
assert_equal [:power, :channel=], tv.messages
end
def test_proxy_handles_invalid_messages
tv = Proxy.new(Television.new)
assert_raise(NoMethodError) do
tv.no_such_method
end
end
def test_proxy_reports_methods_have_been_called
tv = Proxy.new(Television.new)
tv.power
tv.power
assert tv.called?(:power)
assert ! tv.called?(:channel)
end
def test_proxy_counts_method_calls
tv = Proxy.new(Television.new)
tv.power
tv.channel = 48
tv.power
assert_equal 2, tv.number_of_times_called(:power)
assert_equal 1, tv.number_of_times_called(:channel=)
assert_equal 0, tv.number_of_times_called(:on?)
end
def test_proxy_can_record_more_than_just_tv_objects
proxy = Proxy.new("Code Mash 2009")
proxy.upcase!
result = proxy.split
assert_equal ["CODE", "MASH", "2009"], result
assert_equal [:upcase!, :split], proxy.messages
end
end
# ====================================================================
# The following code is to support the testing of the Proxy class. No
# changes should be necessary to anything below this comment.
# Example class using in the proxy testing above.
class Television
attr_accessor :channel
def power
if @power == :on
@power = :off
else
@power = :on
end
end
def on?
@power == :on
end
end
# Tests for the Television class. All of theses tests should pass.
class TelevisionTest < EdgeCase::Koan
def test_it_turns_on
tv = Television.new
tv.power
assert tv.on?
end
def test_it_also_turns_off
tv = Television.new
tv.power
tv.power
assert ! tv.on?
end
def test_edge_case_on_off
tv = Television.new
tv.power
tv.power
tv.power
assert tv.on?
tv.power
assert ! tv.on?
end
def test_can_set_the_channel
tv = Television.new
tv.channel = 11
assert_equal 11, tv.channel
end
end
February 5th, 2009 @ 4:53 pm by Nayan Hajratwala | Posted in Uncategorized | No Comments
Uncle Bob has posted a nice video covering basic usage of the new SLIM framework within FitNesse. It appears to streamline some (but not all) of the annoyances of the current FitNesse processing.
I have yet to try it, but it certainly looks promising, especially for people writing tests for multiple platforms.
November 18th, 2008 @ 4:09 pm by Nayan Hajratwala | Posted in Agile | 1 Comment
The sessions for the upcoming CodeMash conference were announced on the email list last night. It looks like a great list of sessions that will be posted shortly on the official site.
Unfortunately, the sessions that I submitted were not selected. There’s always next year, but in the spirit of optimism there are a couple nice side effects of this:
- More free time since I don’t have to prepare presentations.
- More time at the conference to play Rock Band. Please tell me someone is bringing it. =)
Anyway, for those who are interested, here are the abstracts that I submitted:
Enterprise Build & Deployment Ecosystems
One of the most forgotten/ignored aspects of software development is the build/deployment process. Teams tend not to give it much thought until a couple weeks before actual deployment time, and then ad hoc solutions are rushed into place that sometimes create more problems than they solve.
Build/Deploy nirvana consists of:
- Low setup-cost for new team members
- Code AND Database version control
- Easily repeatable builds
- Automated release versioning
- Pushbutton deployments to all environments.
This session will present a set of Best Practices(TM) needed to make this vision a reality, as well as one possible implementation using Maven (Build), Hudson (Continuous Integration), and LiquiBase (Database Change Management).
ICEfaces: Ajax Interfaces with JEE Power
Tired of fighting with Javascript to build an AJAX-enabled application? Sick of developing UIs that are not easily integrated into your JUnit test harness?
ICEfaces is a fully Ajax enabled implementation of the JSF (Java Server Faces) specification. Build all your components in (testable) Java, write your pages with ICEfaces/JSF tags, and ICEfaces magically generates the cross-browser Ajax interface elements with dynamic updates. You can leverage the full enterprise power of the JEE stack with ease. It’s open source too!
This session will present the fundamentals of ICEfaces, it’s benefits and drawbacks, as well as how you can start using it in your application.
November 13th, 2008 @ 9:41 am by Nayan Hajratwala | Posted in Conference, Maven | No Comments
Well, not really, but iterations are not as important some of the Agile community makes them out to be, in the way that they are typically thought of.
Short iterations. Long iterations. Who gives a rip? The important thing is that you are regularly tracking your team’s velocity. Take this Big Visible Velocity Chart from my current project:

Ouch! That Velocity Hurts!
We track velocity weekly (using Ideal Days), only counting up the velocity for stories that are completed before Monday morning. As you can see, we seem to have developed a fairly regular cadence of slow week/fast week/slow week/fast week… So what’s going on here? Do we bring a keg into the team room every other week? Are we really bad at estimating?
Actually, the cause of this sawtooth motion is simply that we tend to not be *quite* done with things in a given week, so a lot of the stories get counted in the following week’s tally. For example, in Week 7, we had two 4 iDay stories and one 2 iDay story allocated. The 2 iDay story was completed by the end of the week, but the the 4 iDay stories didn’t get finished until the following Monday afternoon. Therefore, we counted 2 iDays for week 7, and the remaining 8 were lumped into the week 8 metric.
Now, we could get into a big discussion about how our stories are too big, or that our iterations are too short, but in reality it doesn’t really matter. What matters is that from the data we’ve collected, we can come up with a fairly accurate measure of our teams velocity. (We had a string pulled across the chart that we adjusted each week to indicate the trend line, but the tape wasn’t strong enough to hold it up). We can use that velocity to estimate our team’s capacity and deliverable dates, and have done just that on this project.
By the way, in case you hadn’t noticed, this chart is *proof* that our team’s velocity is “off the charts”
What do you think? Are iterations overrated?
October 28th, 2008 @ 3:15 pm by Nayan Hajratwala | Posted in Agile | 5 Comments
Hello everyone –
I’m running for the chair of the Michigan Agile Enthusiasts Group — If you get a chance, join up and vote for me!
Thanks!
October 2nd, 2008 @ 10:16 am by Nayan Hajratwala | Posted in Agile | No Comments
The CodeMash 2009 Conference in beautiful Sandusky, Ohio was just announced.
Last year was a blast. In addition to the copious amounts of Rock Band that was played, and waterslides that were slid on, I presented a session on Continuous Integration. This year, I plan to propose a session around deployment and artifact management. Sounds exciting, right?
See you there!
July 15th, 2008 @ 9:06 pm by Nayan Hajratwala | Posted in Conference | 1 Comment