Alexandre Martins’ Blog

On software & technology

Archive for the ‘Uncategorized’ Category

Hamcrest Out Of Test Code!

with 7 comments

It’s been a while since I read some interesting posts showing creative uses of Hamcrest library out of test code. Since then I’ve been proscrastinating to implement my own version, trying strongly typed java delegates.

Thankfully this week I came across a nice API called hamcrest-collections. It uses Hamcrest to implement features such as select, reject, map, reduce and zip familiar from languages like Ruby and Python.

Selectors

Selectors can be used to select or reject items that matches a given Matcher, from any iterable object. It reminds me the Specification Pattern from Domain-Driven Design, which is also used for querying objects that satisfies defined specifications.

public static final Person john = new Person("John", 28);
public static final Person nicole = new Person("Nicole", 12);
public static final Person ryan = new Person("Ryan", 23);
public static final Person nathan = new Person("Nathan", 18);

public static final List list() {
    return Arrays.asList(john, nicole, ryan, nathan);
}



The code below selects from the list of users defined above, the ones that are under twenty.

@Test
public void should_select_only_people_under_twenty_years_old() {
    List users = Person.list();
    Iterable underTwentyList = select(users, underAge(20));
    assertThat(underTwentyList, hasItems(nicole, nathan));
    assertThat(underTwentyList, not(hasItems(john, ryan)));
}



The code below rejects all the users that are under twenty.

@Test
public void should_reject_every_people_under_twenty_years_old() {
    List users = Person.list();
    Iterable aboveTwentyList = reject(users, underAge(20));
    assertThat(aboveTwentyList, hasItems(john, ryan));
    assertThat(aboveTwentyList, not(hasItems(nicole, nathan)));
}


Map and Reduce

Map is used to apply a function onto each item in any iterable object, whereas Reduce combines all these elements, applying a Reducer implementation. In our example, we map the timesTwo function, that doubles each element in the list, and then we reduce it by adding up all of them.

@Test
public void should_double_each_number_in_the_list_then_sum_all_of_them() {
    List numbers = Arrays.asList(1, 2, 3);
    MultiplyBy timesTwo = new MultiplyBy(2);

    Iterable result = map(numbers, timesTwo);
    assertThat(result, hasItems(2, 4, 6));

    Integer sum = reduce(result, new Sum());
    assertThat(sum, equalTo(12));
}


public class MultiplyBy implements Function {
    private Integer factor;

    public MultiplyBy(Integer factor) {
        this.factor = factor;
    }

    public Integer apply(Integer number) {
        return (int)number * factor;
    }
}


public class Sum implements Reducer {
    public Integer apply(Integer first, Integer second) {
        return first + second;
    }
}


Despite the bias created by some developers, that Hamcrest should not be used anywhere else but test code, specially after JUnit has defined it as its new matcher library, just ignore it and add these features to your runtime library, so that you can let your creativity drive you when developing. Get rid of “for” loops from your life! :)

Written by Alexandre Martins

February 19th, 2009 at 6:38 am

Martin Fowler: HumaneRegistry

without comments

Latest Martin Fowler’s post about HumaneRegistry mentions the first project I was involved working for ThoughtWorks. It was a SOA-Governance consulting with some development effort, and also some effort on harvesting information about services provided by different applications inside the organization, compiling and placing them on the wiki. The idea was to get both service builders and consumers to contribute, inputing information about the services they develop/consume aiming to build a solid service registry for all the services, with some highlighted features such as:

  • Service description and what the user needs to use it.
  • Who is the best person for the consumer to speak to, by looking the graph indicating who’s been contributing to the project.
  • Who’s using it, by looking the graph indicating which applications has been invoking EJBs and consuming messages.
  • And some other ones mentioned on Martin’s post.

This was such a rewarding experience to work with great professionals like Erik Dörnenburg and Halvard Skogsrud. And it was cool that Martin documented this on his bliki.

Written by Alexandre Martins

December 7th, 2008 at 4:53 pm

Acceptance Tests With JBehave, Selenium & Page Objects

with 5 comments

Since JBehave 2.0 was released in September, I’ve been using it on my current project to verify the acceptance criteria for the features we are implementing, ensuring that the web interface is following the right workflow, and is displaying the data as expected, as well as some other important elements.

What is JBehave?

JBehave is a framework for Behaviour-Driven Development, that allows customers and developers to work together more closely on features for the system. They get together to discuss and define a set of executable criteria (scenarios) for each of the features that will be used to determine if they are fully implemented or not. The cool thing is that the scenario execution produces an easy-to-read output, so that customers can keep track of the implementation status.

An Example

In this example, I’m not covering all the bits and pieces about writing and running acceptance tests with JBehave. If you want to see it in details, there’s a very good introduction article here. The intention is to show how we are doing it on my project, integrating with Selenium and using the Page Objects pattern.

New Feature

Suppose the customer wanted to provide exclusive content for the user of the website. For that, we would have to implement an authentication framework, so that we could guarantee that only registered users would access that content. So the story looks like this:

As an user
I want to login into the website
So that I can view the exclusive contents

Defining Scenarios

Scenario: Invalid Username
Given the user is on the login page
 When the user types username wrong!
  And the user types password 123456
  And clicks the login button
 Then the page should display Invalid Authentication message

Scenario: Successful Login
Given the user is on the login page
 When the user types username alexandre
  And the user types password 123456
  And clicks the login button
 Then the user should be redirected to home page
  And the page should display welcome message to alexandre

Each scenario needs its own implementation, providing the necessary steps to be verified, in our case the LoginSteps class. Another improvement on version 2.0 is that it allows you to define multiple scenarios in a single file.

public class LoginScenarios extends Scenario {
	public LoginScenarios() {
		super(new LoginSteps());
	}
}

Defining Steps (Integrating Selenium)

After defining the scenarios on the text file, it’s time to map each scenario step to its implementation. Once you start mapping them you will come across ones that are already mapped, and will realise that defining new scenarios is just a matter of combining existing steps.

Initially, for each step, we were extracting the code sniped from Selenium IDE record and placing into it. But it felt a bit clumsy, with code duplication in some spots. It quickly reminded me how hard it is to maintain a suite of tests when it starts evolve and there is not enough effort on refactoring. We wanted to avoid duplication and come up with a more elegant and reusable solution.

One day my friend Uday Rayala came up with the idea of using the Page Objects pattern for writing our acceptance tests, so that we could encapsulate the logic to interact and verify page state into these objects. The first time I heard about it was from Simon Stewart, when he was in Sydney for the JAOO conference. He said that they implemented WebDriver based on this pattern, and showed me some examples. Here is a definition, extracted from the WebDriver wikipage:


Within your web app’s UI there are areas that your tests interact with. A Page Object simply models these as objects within the test code. This reduces the amount of duplicated code and means that if the UI changes, the fix need only be applied in one place.

public class LoginSteps extends Steps {

	@Given("the user is on the login page")
	public void theUserIsOnTheLoginPage() {
		LoginPage loginPage = new LoginPage();
		loginPage.verifyPresenceOfUsernameAndPasswordFields();
		loginPage.verifyPresenceOfLoginButton();
	}

	@When("the user types username $username")
	public void theUserTypesUsername(String username) {
		loginPage().typeUsername(username);
	}

	@When("the user types password $password")
	public void theUserTypesPassword(String password) {
		loginPage().typePassword(password);
	}

	@When("clicks the login button")
	public void clicksTheLoginButton() {
		loginPage().login();
	}

	@Then("the page should display $errorMessage message")
	public void thePageShouldDisplayErrorMessage(String errorMessage) {
		loginPage().verifyPresenceOfErrorMessage(errorMessage);
	}

	@Then("the user should be redirected to home page")
	public void theUserShouldBeRedirectedToHomePage() {
		HomePage homePage = new HomePage();
		homePage.verifyPage();
	}

	@Then("the page should display welcome message to $user")
	public void thePageShouldDisplayWelcomeMessage(String user) {
		homePage().verifyPresenceOfWelcomeMessageTo(user);
	}

	private LoginPage loginPage() {
		return (LoginPage) Page.current();
	}

	private HomePage homePage() {
		return (HomePage) Page.current();
	}
}

Written by Alexandre Martins

November 14th, 2008 at 6:30 pm

Agile patient diagnostic!

with one comment


Last week, I went to a hospital in St Leonards, yes I was feeling sick, but now I’m fine. The thing is, while I was waiting to see the doctor my wife called my attention “Look, the doctors are having a stand-up meeting!!!!” (she’s been reading about agile…). It was awesome! There were about six doctors standing, forming a circle, each of them reporting its patients diagnostics and what was being done to treat them. After each report, all the other doctors were free to provide their own opinion about the case, and so they kept going, one by one. After about 20 minutes the meeting was done. Cool!! I couldn’t go home without asking the doctor about that. He said they started doing that about one year ago and since then, the stress level in the hospital has been decreasing more and more, just for the fact that now, decisions are made in group and all the doctors have a general knowledge of what’s going on around. The next day, speaking to a friend at ThoughtWorks, he said this hospital received loads of criticism on the way the staff was being overloaded. This is just another proof of how agile practices can enhance productivity and quality of your team.

Written by Alexandre Martins

May 22nd, 2008 at 1:38 pm

Posted in Uncategorized

Tagged with ,