Sunday, March 21, 2010

How do I know if an open source software product is right for my organization?

More and more organizations are relying on open source software to build, test, deploy, and run mission critical IT applications. From small start-ups to Fortune 500 companies, organizations worldwide are continuing to find open source as a cost effective means to deliver quality business applications. With a wealth of commercial and open source software options widely available, how does an organization know if an open source product is right for them?

Here are several critical factors to consider when selecting open source software.

Community
Understand the community around the software. Perform a job search for postings referencing the technology. The results will give excellent insight into the usage of the software. In addition, ask yourself the following questions. How many times has the software been downloaded? When was the last release? How often are changes made? Are the forums alive and well? Are there frequent tweets (via twitter) regarding the software? Is the wiki alive and well? How often is the wiki updated? Are there books written on the topic? These are all great questions to ask yourself to get a better understanding of the community that exists around the software.

Expertise
Make sure you can find expert talent to work with the software. Determine if that talent exist within your own staff. If not, then consider training programs. Also, talk to local consulting companies with the proper expertise.

Quality
Research and experiment with the quality of the software. Talk to expert users in your area. Take a look at bug reports. Perform a proof-of-concept. Take a look at the source code and associated test cases. And, don’t forget to take a good look at the documentation. Without good documentation, it can be very hard to get started.

Usage
Consider the usage of the software. Open source solutions exists for a wide-range of applications including small code libraries, frameworks, development tools, application servers, enterprise grade databases, operating systems and more. When looking at open source, the planned usage of the software will probably dictate how closely you evaluate it. For example, you may take more time evaluating an enterprise database than you would a build tool.

Ownership
Learn more about who owns the software, and understand the owner’s motivation. Is it owned by an individual working part-time with the hope of sharing their code with the world? Is it owned by a non-profit organization with significant funding and a solid base of volunteers? Or, is it owned by a business or individual entrepreneur using the open source model to increase product adoption? The answer to these questions may help you better understand the long-term viability of the open source software.

Limitations (if any)
Make sure you understand the limitations associated with the open source version of the solution. Several open source companies offer open source and commercial versions of their product. The commercial versions generally offer enhancements that may or may not be critical to your application. If you feel the commercial version is important, then keep in mind that you may be able to upgrade to the commercial version at a later time.

Support
Understand the support options available. It used to be the case that many organizations feared open source because the software lacked commercial support options. Today, this is not always the case. Most widely adopted open source solutions have medium-to-large sized companies offering support contracts as well as indemnification. In fact, it’s not unusual for open source support companies to offer more responsive support than the alternative commercial software.

Licensing
Always consider the open source license associated with the software. Most products will have a link to a description of the license on their website. Certain licenses may limit your ability to use the open source version of the software.

Open source software can be an excellent option when trying to lower IT costs. But, it’s not always an obvious choice. Considering some or all of the factors outlined above can help your organization make the right choice.

Monday, November 30, 2009

Write Readable Tests with Mockito

A good mocking framework is a must have in any Java developers toolset. Mocking frameworks greatly reduce the amount of code needed to effectively mock dependent interfaces and/or classes. Over the past several years EasyMock has been my mocking framework of choice. But, the framework has a couple of issues that could be improved upon. First, tests using EasyMock tend to be less readable than desired, and second, when tests fail, it's often extremely difficult to decipher the exact problem.

A couple months ago I came across mockito. The docs promised me the ability to "write beautiful tests" that are "more readable" and "produce clean verification errors." Perfect, I thought I'd give Mockito a try. Now, after several months of using mockito on a large project, I can say that I have a new favorite mocking framework.

Let's take a simple example to illustrate the benefits of mockito. In this example, we have a PersonService with the method updateName(Integer personId, String name). In order to update the name, the PersonService will retrieve the existing Person via a call to PersonDao.fetchPerson(Integer personId), create a new instance of the immutable Person with the new name value set, and finally call PersonDao.update(Person) to save the changes. I realize this is not the most performant means of updating the name in the database, but it provides a nice simple example for illustration purposes.

First, take a look at the Person class. Nothing special, just a simple bean.

public class Person {

private final Integer id;
private final String name;

public Person(Integer id, String name) {
this.id = id;
this.name = name;
}

public Integer getId() {
return id;
}

public String getName() {
return name;
}

}



And, here's the PersonDao interface. I've left out the implementation to simplify the example. Although, do note that mockito will mock classes as well as interfaces.

public interface PersonDao {

public Person fetchPerson(Integer id);

public void update(Person person);

}



Finally, here's the PersonService. The class we'll be testing.

public class PersonService {

private final PersonDao personDao;

public PersonService(PersonDao personDao) {
this.personDao = personDao;
}

public boolean update(Integer personId, String name) {

Person person = personDao.fetchPerson(personId);
if (person != null) {
Person updatedPerson = new Person(person.getId(), name);
personDao.update(updatedPerson);
return true;
} else {
return false;
}

}

}



Now, for our tests. The first snippet shows the static imports defined in the test class. The static imports improve the readability of tests by allowing the code to read like a DSL. I just wish eclipse would default to allow .* when organizing static imports. There is a setting, but you must change it with each new workspace.

import static org.mockito.Mockito.*;
import static junit.framework.Assert.*;


Below, you'll see the first sign of mockito. In this case, the before() method creates a mock of the personDao by calling mock(PersonDao.class). Nice and easy.

public class PersonServiceTest {

private PersonService personService;
private PersonDao personDao;

@Before
public void before() {
this.personDao = mock(PersonDao.class);
this.personService = new PersonService(personDao);
}
...
}


Below is our first test. A happy path scenario in which the PersonService finds the existing Person and calls the PersonDao to update the Person's name. Let's take a closer look at what's happening in the test.

  • The personDao.fetchPerson() method is stubbed simply by calling when(personDao.fetchPerson(1)).thenReturn(person). This statement informs the mock PersonDao to return person when the fetchPerson method is called with a value of 1.
  • The statement verify(personDao).fetchPerson(1) verifies that personDao.fetchPerson is called with a value of 1. If it is not, the test will fail.
  • The ArgumentCaptor provides a really slick way to capture the variable passed to the update method of the PersonDao. And, easily allows me to assert that the name has changed to the new value.
  • The verifyNoMoreInteractions(personDao) statement asserts that during the test, there are no other calls to the mock object.


    @Test
public void shouldUpdatePersonName() {

Person person = new Person(1, "john");
when(personDao.fetchPerson(1)).thenReturn(person);

boolean updated = personService.update(1, "joe");
assertTrue(updated);

verify(personDao).fetchPerson(1);

ArgumentCaptor<Person> personCaptor = ArgumentCaptor
.forClass(Person.class);
verify(personDao).update(personCaptor.capture());
Person updatedPerson = personCaptor.getValue();
assertEquals("joe", updatedPerson.getName());

verifyNoMoreInteractions(personDao);

}


The second scenario we'll test is shown below. It proves that when PersonDao.fetchPerson(Integer) returns null, PersonDao.update(Person) is not called. Nothing really new here. Just notice that the stubbed call (when...thenReturn), is returning null, and the test is no longer verifying that personDao.update(Person) is called.

    @Test
public void shouldNotUpdateIfPersonNotFound() {

when(personDao.fetchPerson(1)).thenReturn(null);

boolean updated = personService.update(1, "joe");
assertFalse(updated);

verify(personDao).fetchPerson(1);
verifyNoMoreInteractions(personDao);

}



Now, for our final test, let's see what happens when an unexpected call happens. This is the same test as above, but the test is no longer calling verify(personDao).fetchPerson(1). So, the test fails...

    @Test
public void shouldFailWithNiceMockitoError() {

when(personDao.fetchPerson(1)).thenReturn(null);

boolean updated = personService.update(1, "joe");
assertFalse(updated);

// notice no longer calling verify(personDao).fetchPerson(1);
verifyNoMoreInteractions(personDao);

}


And, check out the readability of the test failure! In very simple terms, the message tells me exactly what happened and where it went wrong.

org.mockito.exceptions.verification.NoInteractionsWanted: 
No interactions wanted here:
-> at com.opi.mock.PersonServiceTest.shouldFailWithNiceMockitoError(PersonServiceTest.java:70)
But found this interaction:
-> at com.opi.mock.PersonService.update(PersonService.java:20)

at com.opi.mock.PersonServiceTest.shouldFailWithNiceMockitoError(PersonServiceTest.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)




As you can see from these examples, mockito tests are simple to write, easy to read, and fail with nice concise messages. All factors leading to happy, productive developers! Happy mocking!

Wednesday, January 14, 2009

Wednesday, December 3, 2008

Rod Johnson: "Can Ruby on Rails do that?"

Adrian Coyler presented tonight's keynote at SpringOne.  Once again Grails was a large part of the presentation.  During the demo, he created a grails app from scratch.  Nothing new, we've seen it all before.  Easily creating a web application with minimal code.  However, the more impressive piece of the presentation was when Adrian integrated the application with an existing Spring Integration application.  

It was done with great ease.  Adrian performed the following simple steps to successfully integrate the existing application:
  • Copied all the spring integration jars into the grails-app/lib directory.
  • Copied the existing application's spring config file into the grails-app/resources/spring directory.
  • Added a "cafe" property to his Grails service in order to inject the existing application's spring bean.
  • Invoked the Cafe interface from the Grails service method.
That was it.  To which Rod Johnson commented from the crowd "Can Ruby on Rails do that?"  

I'd like to hear from the JRuby and Rails communities.  I have to believe there's a way to call an existing spring application bean via a Ruby on Rails app using JRuby.  Even if it requires some custom code.

Is it possible?  If it isn't simple, are there plans to provide tighter integration to allow organizations to re-use existing spring beans in Rails projects?

Tuesday, December 2, 2008

Grails Shines at SpringOne

Last night Rod Johnson kicked-off the 2008 springOne conference with a keynote emphasizing the new SpringSource slogan "Weapons for the War on Java Complexity."  During the first day of the conference, no technology fit that billing more than Grails.

In the first session of the day, "Grails for Spring Developers", Graeme Rocher wowed the crowd by building Twitter in 40 minutes.  It was really impressive to see how quickly Graeme created a full-blown twitter application including all the functionality twitter users are familiary with.  Not to mention the necessary application infrastructure including authentication, authorization, database persistence, caching, JMS messaging, Quartz scheduling, and email.

Graeme added each feature using many of the popular Grails plugins available today including:
By demonstrating these features, Graeme really backed up his statements that "Grails is more than just a CRUD framework" and that it offers "all the benefits of rapid application development without sacraficing the underlying power of Spring."  It appears that we may see more Grails integration with other Spring technologies such as Spring Dynamic Modules for OSGi and Spring Integration in the future.  Only time will tell, but Grails was mentioned by presenters in each of the presentations I attended today.

In Rod Johnson's keynote last night, he mentioned that in the last year, the number of Grails downloads have increased from 7000 to 70,000/month.  It may be a bit early, but it's starting to appear as though Grails truly is the future of enterprise java development.

Monday, December 1, 2008

Unit Testing Grails in Eclipse

For the past several weeks, I've been working on a Grails app in my spare time, and I'm really excited about the future of Grails.  However, I've been a bit disappointed in the tooling currently available.  Myself and many of my clients use Eclipse, and at this point the Eclipse support for Grails is less than ideal.

Spring Source's recent acquistion of G2One will really help move the Eclipse support forward.  Here's a recent interview with Grails founder Graeme Rocher in which he discusses how Spring Source will help drive Grails tool support within Eclipse.


One of the largest frustrations I've had with the Eclipse plugin is the setup necessary to run a grails unit test.  After I first setup my grails project in Eclipse, I tried to create a simple groovy unit test and run it.  As with Java unit tests, I right clicked on the class and selected run as junit test.  Each time I ran the test I received the following error.

"Error running MyGroovyTest.groovy failed to find a class file, ensure the Groovy output folder is on the classpath"

After a lot of digging around I was finally able to work through these issues and figure out a way to execute grails unit tests within eclipse.  Here are the steps I used to get the tests working.  
  1. Right-click on the project and select Properties > Groovy Project Properties.
  2. Uncheck "Disable Groovy Compiler Generating Class Files"
  3. Modify the "Groovy compiler output location" to "bin-groovy"
  4. Select "Java Build Path"
  5. Modify the Default Output folder to "/bin" (I need to test this again to see if this step is required).
  6. From the same Java Build Path dialog select Libraries > Add Class Folder...
  7. Check bin-groovy.
  8. Now run the unit test by right clicking on the groovy file and it should work.
It's quite an involved process, but it works.  If anyone has a simpler solution, I'd be really glad to hear it.  I'm using Eclipse Ganymede, Grails 1.0.4, and Groovy Plugin 1.5.6.200807211457.  

Cleaning up these types of issues within Eclipse will be critical to the success of Grails, and I'm glad to hear that SpringSource and Grails will be focusing their efforts on tooling in the near future.