Feb 06 2010

Milano XpUg January Coding Dojo

Category: java,presentationgiordano scalzo @ 3:04 pm

Lately, I’m more and more involved in Milan XpUg meetings; last week I had the pleasure to attend my first Coding Dojo.
A Coding Dojo is a meeting where some people practice Tdd and try to learn new things, without schedule and deadline pressure.
As introduction I prepared a little presentation, mainly with the aim to clarify the “Ocp Way” to do katas, as conceived by Matteo Vaccari in his blog:

We had a lot of fun, and we are committed to arrange another Dojo, at the end of February.
If someone is interested to practice more, here you can find the text of the kata we practiced and here the code we produced.

Technorati Tags: , ,

Tags: , ,


Jan 19 2010

Objective-C for busy Java Developers 1: Calling methods

Category: java,objective-c,tutorialgiordano scalzo @ 2:34 pm

At last I got a wonderful MacBookPro, so I started to study Objective-C to develop some cool Iphone applications.

Objective-C is a language derived from C, to which it adds some modern features as ObjectOriented or Smalltalk-style messaging.

As far I’m a complete newbie, I’m trying to learn it recalling some well know patterns and scenarios as made in Java , following this good tutorial.

Objective-C has a little strange way to call method, that could be disorienting at first glance:

Java:

object.method;
object.methodWithInput(input);

output = object.methodWithOutput();
output = object.methodWithInputAndOutput(Object input);

Objective-C:

[object method];
[object methodWithInput:input];

output = [object methodWithOutput];
output = [object methodWithInputAndOutput:input];

Obviously, it’s possible to call methods of class, instead of instance:

Java:

Object oString = new String();

Objective-C:

id oString = [NSString string];

The

id

refers any kind of object, so it’s little different from Java counterpart.
Better code is:

Java:

String sString = new String();

Objective-C:

NSString* sString = [NSString string];

With this style, it’s a little cumbersome write nested calls:

Java:

calculator.add(numbers.split());

Objective-C:

[calculator add:[numbers split]];

This syntax disencourage the nesting of more than one method.

Some methods take multiple input arguments, Objective-C deals with that allowing split method names:

Java:

boolean writeToFile(String path, boolean useAuxiliaryFile)

boolean result = myData.writeToFile("/tmp/log.txt", false);

Objective-C:

-(BOOL)writeToFile:(NSString *)path withAuxFile:(BOOL)useAuxiliaryFile;

BOOL result = [myData writeToFile:@"/tmp/log.txt" withAuxFile:NO];

Objective-C has properties built in, in Java you need to implement getters and setters:

Java:

photo.setCaption("Day at the Beach");
output = photo.getCaption();

Objective-C:

photo.caption = @"Day at the Beach";
output = photo.caption;

A property should be marked

@property

in declaration and

@synthesize

in implementation.

To create an object, the function

alloc

should be called and then an init method should be called:

Java:

object = new ComplexObject(1.0f);

Objective-C:

object = [[ComplexObject alloc] initWithFloat:1.0f];

When working in an environment without garbage collector, any object created with alloc should be released:

Objective-C:

[object release];

To complete this introductory post, take a look at this ObjectiveC CheatSheet: it contains all the most used constructs needed to start to code for Mac.

Technorati Tags: , ,

Tags: , ,


Nov 07 2009

No more excuses 2: junit testing System time

Category: java,tutorialgiordano scalzo @ 2:59 pm

Another common exemple of static dependency, it’s the Time System dependency.
In greenfield project it could be possible inject time into the objects they’ll use it, but in legacy code it’s more difficult, so oftet we gave up and don’t unit test some behaviour dependent from time.

In a recent project, I had the problem to check the correct format of a filename that it had to contain the creation timestamp; I easily overcame it with a nice test pattern made by Paolo “Nusco” Perrotta, well known Ruby Metaprogramming guru, in a version wrote by Bruno Bossola in a nice Open Source project.

In a nutshell, the trick is to adapt System Time with another object.

Let see a simple example.
This is the class to test:

package biz.scalzo.prod;

import java.text.SimpleDateFormat;
import java.util.Date;

public class TimeFormatter {
	public String now() {
		SimpleDateFormat sdf = new SimpleDateFormat(
				"yyyy/MM/dd HH:mm");
		return sdf.format(new Date(System.currentTimeMillis()));
	}
}

I know it mixes two responsibilities, it has a silly static dependecy and so on, but forgive my oversemplification used to show the pattern.

package biz.scalzo.test;

import junit.framework.Assert;
import org.junit.Test;

public class ATimeFormatter {
	@Test
	public void shouldFormatNowInFancyWay() {
		Assert.assertEquals("2009/10/13 15:29", new TimeFormatter().now());
	}

}

The behaviour to check is how well the Formatter formats current time in string; we have to find a way to set a well know time point so we can check te result of format.

To implement the VirtualClock pattern, we declare a simple Clock interface:

package biz.scalzo.prod;

public interface Clock {
	public long now();
}

and a repository where we can insert our fake clock

package biz.scalzo.prod;

import java.util.Date;

public class SystemTime {
	private static Clock clock;

	private static final Clock defaultClock = new Clock() {
		public long now() {
			return System.currentTimeMillis();
		}
	};

	public static long asMillis() {
		return getClock().now();
	}

	public static Date asDate() {
		return new Date(getClock().now());
	}

	public static void reset() {
		clock = null;
	}

	public static void setClock(Clock aClock) {
		clock = aClock;
	}

	static Clock getClock() {
		return (clock != null ? clock : defaultClock);
	}
}

Now we can change our class using SystemTime instead of System.currentTimeMillis():

package biz.scalzo.prod;

import java.text.SimpleDateFormat;
import java.util.Date;

public class TimeFormatter {
	public String now() {
		SimpleDateFormat sdf = new SimpleDateFormat(
				"yyyy/MM/dd HH:mm");
		return sdf.format(SystemTime.asDate());
	}
}

In test harness we can inject a fake clock

package biz.scalzo.test;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import biz.scalzo.prod.Clock;
import biz.scalzo.prod.SystemTime;
import biz.scalzo.prod.TimeFormatter;

public class ATimeFormatter {
	private static final long FAKED_TIME = 1255440571354L;

	private void fakeClock() {
		SystemTime.setClock(new Clock() {
			public long now() {
				return FAKED_TIME;
			}
		});
	}

	@Before
	public void setUp(){
		fakeClock();
	}

	@Test
	public void shouldFormatNowInFancyWay() {
		Assert.assertEquals("2009/10/13 15:29", new TimeFormatter().now());
	}

}

and we have green bar! Neat, isn’t it?

I know it’s a lot of code, but in legacy code it’s better than leave a feature without a test.

Technorati Tags: , ,

Tags: , ,


Oct 21 2009

No more excuses: junit testing log messages

Category: java,tutorialgiordano scalzo @ 7:46 pm

Althought I’m a straight adept of Tdd, sometime I can’t resist the temptation to write some production code without a test, above all if I have to implement some cross cutting behaviours, as could be logging .

In project I worked on lately, a request was to manage some bad situations logging something at error level and go process next item; the temptation to implement it and check running the program was very appeliling, but my green wrist band and RailsConf 09 keynote by Uncle Bob I watched recentely, helped me resist.
So I started searching, tried somenthing, and, finally, I came up with a neat solution.

Given this simple object

package biz.scalzo.prod;

import org.apache.log4j.Logger;

public class LoggingObject {
	private static Logger log = Logger.getLogger(LoggingObject.class);

	public void starts() {
		log.info("I'm starting");
	}
}

we want to test if it writes log.
To achieve this, we can use a simple custom appender, that records all messages in a list:

package biz.scalzo.test;

import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;

public class RecordingAppender extends AppenderSkeleton {
	private static List<String> messages = new ArrayList<String>();
	private static RecordingAppender appender = new RecordingAppender();

	private RecordingAppender() {
		super();
	}

	public static RecordingAppender appender(PatternLayout patternLayout) {
		appender.setLayout(patternLayout);
		appender.clear();
		return appender;
	}

	protected void append(LoggingEvent event) {
		messages.add(layout.format(event));
	}

	public void close() {
	}

	public boolean requiresLayout() {
		return true;
	}

	public static String[] messages() {
		return (String[]) messages.toArray(new String[messages.size()]);
	}

	private void clear() {
		messages.clear();
	}
}

With that, writing our test is a piece of cake:

package biz.scalzo.test;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;

import biz.scalzo.prod.LoggingObject;

public class ALoggingObject {

	private LoggingObject loggingObj;

	@Before
	public void setUp() {
		loggingObj = new LoggingObject();
		configureLog();
	}

	private boolean logContains(String expected) {
		String actual[] = RecordingAppender.messages();
		for (String log : actual) {
			if (log.contains(expected))
				return true;
		}
		return false;
	}

	private void configureLog() {
		Logger rootLogger = Logger.getRootLogger();
		rootLogger.removeAllAppenders();
		rootLogger.setLevel(Level.INFO);
		rootLogger.addAppender(new ConsoleAppender(new PatternLayout(
				"%d [%t] %-5p %c{1} - %m%n")));
		rootLogger.addAppender(RecordingAppender.appender(new PatternLayout(
				"%-5p - %m%n")));
	}

	@Test
	public void shouldLogWhenStarts() {
		loggingObj.starts();
		assertTrue(logContains("I'm starting"));
	}

}

Neat, simple and clear: no more excuses to not test logging!

Technorati Tags: , ,

Tags: , ,


Sep 18 2009

Extreme Refactoring or Is Guard clause Considered harmful?

Category: agile,javagiordano scalzo @ 4:56 pm

During the JDave try, the focus was on Bdd side of the exercise, but, nonetheless, the StringTemplater’s code was yelling “Refactor me! Refactor me!” at me :-) .

Actually, that I like least, it’s the Guard Clause, I used to split a marker in key-value form:

private String name(String[] pair) {
		if (pair.length != 2)
			return "";
		return "$" + pair[0].trim();
	}

Usually I like that pattern, it’s a well know way to avoid nested conditional, but Anti-If Campaign, promoted by Francesco Cirillo made me think.

The first try didn’t satisfied me:

private String name(String[] pair) {
		return  (pair.length != 2) ? "" : "$" + pair[0].trim();
	}

Indeed, I believe it’s more cryptic and ugly than the original one.

Looking the code more carefully, I saw another thing: I was violating the principle “Ask, don’t tell“, handling some data that could be tied together.

Creating the new class, I thought another thing:
Why am I using the ‘IF?”
I did for avoid a runtime exception… but is an exception evil?
It isn’t if we can handle it!

So at the end this is my final product:

package biz.scalzo.kata.stringtemplater.jdave;

import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class StringTemplater {

	public String replace(String stringToReplace) {
		return replace(stringToReplace, "");
	}

	public String replace(String stringToReplace, String markers) {
		return replaceEmptyMarkers(replace(stringToReplace, initialIterator(markers)));
	}

	private String replaceEmptyMarkers(String stringToReplace) {
		return stringToReplace.replaceAll("\\$\\w+", "");
	}

	private Iterator initialIterator(String markers) {
		return Arrays.asList(markers.split(",")).iterator();
	}

	private String replace(String stringToReplace, Iterator markers) {
		try {
			return replaceMarker(stringToReplace, markers);
		} catch (NoSuchElementException e) {
			return stringToReplace;
		}
	}

	private String replaceMarker(String stringToReplace,
			Iterator markers) {
		Pair pair = new Pair(markers.next());
		String newString = stringToReplace.replace(pair.name, pair.value);
		return replace(newString, markers);
	}

	private class Pair {
		private String name;
		private String value;

		private Pair(String nameAndValue) {
			init(nameAndValue.split(":"));
		}

		private void init(String[] nameAndValue) {
			try {
				name = "$" + nameAndValue[0].trim();
				value = nameAndValue[1].trim();
			} catch (IndexOutOfBoundsException e) {
				name = "";
				value = "";
			}
		}
	}
}

I think a I could refactor more, but I was enough satisfied: I reached my goal to avoid IF and I’ve start to think the exception in different way.

Technorati Tags: , ,

Tags: , ,


Sep 17 2009

Using JDave: A quick introduction to specs framework

Category: bdd,java,tutorialgiordano scalzo @ 5:13 pm

As second Bdd engine to try, I choose JDave, a specification oriented engine.
JBehave is, instead, user-stories-oriented: the difference is very subtle and I’m not sure I caught it completely ;-) .
Anyway, JDaveis inspired by RSpec, at the moment the most used bdd engine, so I thought it deserved a try.
In order to compare JDave with JBehave, I implemented the StringTemplater kata, as in my previous post.

Installing JDave

After creating a java project, I simply downloaded the last version of JDave and extracted all jar in lib directory of my project:

JDave Jars

They are a lot of jars, and I’m sure I won’t use all of them, but it’s just a try so it doesn’t deserve the time to filter only the used ones.

JBehave is a story runner, so each scenario must be written as:

Given something
When something happens
Then this happens

Instead, JDave is a specification engine and each scenario show a behavior of a class:

AThingIWantToWrite
  - ShouldDoThis
  - ShouldDoThat
  - ShouldntDoThat

In other words, JBehave is similar to Cucumber, JDave is similar to RSpec.

Writing a specification is really straightforward:
first of all, we create a Specification object, passing the object we want to write; then we create a serie of inner classes:

@RunWith(JDaveRunner.class)
public class StringTemplaterSpec extends Specification<ThingIWantToWrite> {
	public class AThingIWantToWrite {
		public void ShouldDoThis() {
		}
		public void ShouldDoThat() {
		}
        }
   ...
}

As JBehave, JDave is a wrapper built over JUnit, so we can use our Ide integration to run the specifications.
That’s it!

The code

As in JBehave try, I implemented the same scenarios as in Corey Haines Video:

package biz.scalzo.kata.stringtemplater.jdave;

import org.junit.runner.RunWith;

import jdave.Specification;
import jdave.junit4.JDaveRunner;

@RunWith(JDaveRunner.class)
public class StringTemplaterSpec extends Specification<StringTemplater> {
	public class AStringTemplater {
		private StringTemplater stringTemplater;

		public void create() {
			stringTemplater = new StringTemplater();
		}

		public void shouldReturnEmptyWhenAnEmptyStringIsPassed() {
			specify(stringTemplater.replace(""), must.equal(""));
		}

		public void shouldReturnTheOriginalStringWhenNoMarkersArePassed() {
			specify(stringTemplater.replace("original string"), must.equal("original string"));
		}

		public void shouldReplaceAToken() {
			specify(stringTemplater.replace("Hello, $name","name: giordano"),
					must.equal("Hello, giordano"));
		}

		public void shouldReplaceTwoTokens() {
			specify(stringTemplater.replace("Hello, $name, how a $attitude day","name: giordano, attitude:  wonderful"),
					must.equal("Hello, giordano, how a wonderful day"));
		}

		public void shouldRemoveNotProvidedMarkers() {
			specify(stringTemplater.replace("Hello, $name, how a $attitude day","name: giordano"),
					must.equal("Hello, giordano, how a  day"));
		}
	}

}

The Junit view of Eclipse is very explicative of the behaviors of StringTemplater:
JUnit View

For sake of completeness, this is the final implementation of StringTemplater:

package biz.scalzo.kata.stringtemplater.jdave;

import java.util.Arrays;
import java.util.Iterator;

public class StringTemplater {

	public String replace(String stringToReplace) {
		return replace(stringToReplace, "");
	}

	public String replace(String stringToReplace, String markers) {
		return replace(stringToReplace, initialIterator(markers));
	}

	private String[] tupla(String pair) {
		return pair.split(":");
	}

	private Iterator<String> initialIterator(String markers) {
		return Arrays.asList(markers.split(",")).iterator();
	}

	private String replace(String stringToReplace, Iterator<String> markers) {
		if (!markers.hasNext())
			return stringToReplace;
		String[] pair = tupla(markers.next());
		String newString = stringToReplace.replace(name(pair), value(pair));
		return replaceEmptyMarkers(replace(newString, markers));
	}

	private String replaceEmptyMarkers(String replace) {
		return replace.replaceAll("\\$\\w+", "");
	}

	private String value(String[] pair) {
		return (pair.length != 2) ? "" : pair[1].trim();
	}

	private String name(String[] pair) {
		if (pair.length != 2)
			return "";
		return "$" + pair[0].trim();
	}
}

Conclusions

JDave is very easy to learn and the specifications written throught it are very complete and expressive.
If I have to make a choice, I liked slightly more JDave, but I think are just two tools: BDD is a way to think, not a framework or an engine to use.

In conclusions, I believe JBehave and JDave could be used together, the former to describe the user stories, at user level, the latter to describe the behaviors of the classes, at developer level.

Technorati Tags: , , ,

Tags: , , ,


Sep 09 2009

Infinitest: an autotest for Eclipse

Category: agile,bdd,javagiordano scalzo @ 7:00 pm

In my experimental trips in Ruby world, other than the elegance of the language, the Bdd as default and the lot of new exciting things created by the community, a thing I liked a lot was autotest , a little gem that launches our testsuite when we change a source file.
It could seem a silly utility, but I can assure it’s a really time saver and can take us in a high productive mental flow: I really missed it in Java world.

Of course, I’ve heard about Junit Max, the Kent Beck’s attempt to create a product, but my laziness delayed me to try it, until Kent got bored and dismiss the project :-( .

Today while reading distractedly the Twitterverse, I bumped into Infinitest, that seems exactly what I was looking for.
Infinitest isn’t open source, but for personal use it should be possible get a free of charge individual license.

The installation is straightforward as usual, just add http://update.improvingworks.com to Eclipse’s software updates, and we are ready to start!

Infinitest stay in the right bottom of Eclipse, waiting far some changes:

waiting for changes

When we save some file Infinitest starts and show the results of all test it founds in the project:

red test

A nice feature is the yellow bar when there is some error in the workspace and tests can’t run:

yellow bar

That’s all!
I have to try it more, but it seems very promising and useful.

Technorati Tags: , , , ,

Tags: , , , ,


Sep 04 2009

Bdd with JBehave

Category: bdd,java,tutorialgiordano scalzo @ 1:50 pm

Somebody defined Behaviour-Driven Development “TDD done right”; maybe is a bit too provocative as definition, but I think it’s the time to get my hands wet and give Bdd a chance.

JBehave is the first BDD’s framework, developed by the BDD’s inventor himself, Dan North, and still one of the more supported in Java community.

I choose a simple kata to develop in Bdd-way, the StringTemplater kata, as saw in a Corey Hainesvideo and following this excellent post.

JBehave on Eclipse: half an hour tutorial

First of all, we should create a project under Eclipse and add JBehave jars.

Then we should write the basic infrastructure: a textual file with the scenarios and two classes connecting our stories to JBehave.

By default the scenarios file should be without extension and in the same directory of classes, but, aiming to separate specs code and production code, I created a new source directory called scenario.

The scenarios file should have a meaningful name and the words should separated by underscores; in this example I called it replace_tokens_in_string.

At the beginning of the file, we can write the story we should implement: it isn’t mandatory, but it’s useful if we use specs to comunicate with the customers.
Following we can write a first basic scenario:

Story: replace tokens in String
As a user
I would like replace token in a string with values
So that I can create templates for my configuration files

Scenario: replace empty string
Given I have a StringTemplater
When I ask to replace an emptystring
Then I should get an emptystring

The story is just descriptive, but the scenario must be of the form of
Given something
When action
Then check

Now we need create two java classes.
The first one is JBehave wrapper to JUnit TestCase and its name should match the one of textual file converted in CamelCase: in our example should be ReplaceTokensInString.

package biz.scalzo.kata.stringtemplater.jbehave;

import org.jbehave.scenario.Scenario;

public class ReplaceTokensInString extends Scenario{
	  public ReplaceTokensInString() {
	        super(new ReplaceTokensInStringSteps());
	    }
}

The second class, ReplaceTokensInStringSteps, implementing the steps of the scenario:

package biz.scalzo.kata.stringtemplater.jbehave;

import org.jbehave.scenario.steps.Steps;

public class ReplaceTokensInStringSteps extends Steps {
}

That’s it!
As said before, JBehave is built over JUnit so we can run ReplaceTokensInString as Junit test obtaining a message from the engine:

Story: replace tokens in String
As a user
I would like replace token in a string with values
So that I can create templates for my configuration files

Scenario: replace empty string

Given I have a StringTemplater (PENDING)
When I ask to replace an emptystring (PENDING)
Then I should get an emptystring (PENDING)

PENDING means we have to build that step; so we do it with an empty implementation:

package biz.scalzo.kata.stringtemplater.jbehave;

import org.jbehave.scenario.annotations.Given;
import org.jbehave.scenario.annotations.Then;
import org.jbehave.scenario.annotations.When;
import org.jbehave.scenario.steps.Steps;

public class ReplaceTokensInStringSteps extends Steps {
	@Given("I have a StringTemplater")
	public void createStringTemplater() {
	}
	@When("I ask to replace an emptystring")
	public void replaceAnEmptystring() {
	}
	@Then("I should get an emptystring")
	public void shouldGetEmptyString() {
	}
}

and when we run again the test, the PENDING messages should disappear.

This is the basic infrastructure, but, in my tiny experience was the most difficult part: once the empty scenario worked, implement the complete kata was quite straightforward.

This is my final scenarios file:

Story: replace tokens in String
As a user
I would like replace token in a string with values
So that I can create templates for my configuration files

Scenario: replace empty string
Given I have a StringTemplater
When I ask to replace an emptystring
Then I should get an emptystring

Scenario: replace string without tokens
Given I have a StringTemplater
When I ask to replace 'this string'
Then I should get 'this string'

Scenario: replace string with a token
Given I have a StringTemplater
When I ask to replace 'Hello, $name' with [name : pippo]
Then I should get 'Hello, pippo'

Scenario: replace string with two tokens
Given I have a StringTemplater
When I ask to replace 'Hello, $name, how a $attitude day' with [name : pippo, attitude: wonderful]
Then I should get 'Hello, pippo, how a wonderful day'

Scenario: replace string with two adjacent tokens
Given I have a StringTemplater
When I ask to replace 'Hello, $adj$name' with [name : friend, adj: good]
Then I should get 'Hello, goodfriend'

Scenario: replace string with two tokens and only one value
Given I have a StringTemplater
When I ask to replace 'Hello, $name, how a $attitude day' with [name : pippo]
Then I should get 'Hello, pippo, how a  day'

This my steps:

package biz.scalzo.kata.stringtemplater.jbehave;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.jbehave.Ensure.ensureThat;

import org.jbehave.scenario.annotations.Given;
import org.jbehave.scenario.annotations.Then;
import org.jbehave.scenario.annotations.When;
import org.jbehave.scenario.steps.Steps;

public class ReplaceTokensInStringSteps extends Steps {
	private StringTemplater templater;
	private String result;

	@Given("I have a StringTemplater")
	public void createStringTemplater() {
		templater = new StringTemplater();
	}

	@When("I ask to replace an emptystring")
	public void replaceAnEmptystring() {
		result = templater.replace("");
	}

	@Then("I should get an emptystring")
	public void shouldGetEmptyString() {
		ensureThat(result, is(equalTo("")));
	}

	@When("I ask to replace '$stringToReplace'")
	public void replaceStringWithoutTokens(String stringToReplace) {
		result = templater.replace(stringToReplace);
	}

	@Then("I should get '$expected'")
	public void checkStringResult(String expected) {
		ensureThat(result, is(equalTo(expected)));
	}

	@When("I ask to replace '$stringToReplace' with [$tokens]")
	public void replaceStringWithTokens(String stringToReplace, String tokens) {
		result = templater. replace(stringToReplace,tokens);
	}

}

and, last but not least, StringTemplater class:

package biz.scalzo.kata.stringtemplater.jbehave;

import java.util.HashMap;
import java.util.Map.Entry;

public class StringTemplater {

	public String replace(String originaleString) {
		return replace(originaleString, "");
	}

	public String replace(String stringToReplace, String tokensAsString) {
		HashMap tokensMap = splitTokens(tokensAsString);
		return removeKeywordWithoutValue(replaceKeywords(stringToReplace,
				tokensMap));
	}

	private String removeKeywordWithoutValue(String replaceKeywords) {
		return replaceKeywords.replaceAll("\\$\\w+", "");
	}

	private String replaceKeywords(String initialValue,
			HashMap tokensMap) {
		String result = initialValue;
		for (Entry entry : tokensMap.entrySet()) {
			result = result
					.replaceAll("\\$" + entry.getKey(), entry.getValue());
		}
		return result;
	}

	private HashMap splitTokens(String tokensAsString) {
		String[] pairs = splitPairs(tokensAsString);

		HashMap result = new HashMap();
		for (String pair : pairs) {
			String[] tokens = pair.split(":");
			if (tokens.length > 1) {
				result.put(tokens[0].trim(), tokens[1].trim());
			}
		}
		return result;
	}

	private String[] splitPairs(String tokensAsString) {
		return tokensAsString.split(",");
	}
}

Conclusions

This is my first impact with Bdd in Java, I liked and I think it’s very promising.
Neverthless, I still don’t know if it is something I can do in day by day work or just a proof of concept: Jbehave is quite verbose and the stories are high level specifications, so we need to write a lot of boilerplate code to specify a class.

In my trip in Bdd-land, next steps will be give other Bdd engines a try, starting with ones written in high level languages as easyb or scalatest.

Technorati Tags: , , , , ,

Tags: , , , , ,