Wednesday, October 29, 2014

Getting deeper into functional programming




I've been so busy that I cannot find time to write a blog post anymore. But since 2012,  I've been playing with the Scala programming language and built projects using Play framework. I find Scala very concise and elegant as a programming language. The only issue I have with it is the syntax. When it gets too much into functional programming it gets harder to understand.

To fully submerge my thought into functional programming, I decided to take an online course "Introduction to Functional Programming" in edx. (https://www.edx.org/course/delftx/delftx-fp101x-introduction-functional-2126#.VFEX416nS5E). The course uses Haskell as a language, and it is taught by Erik Meijer.  I hope to finish this course soon, and hopefully widen my knowledge about functional programming.

Friday, August 09, 2013

Integration testing with Spring framework and Cucumber-jvm in maven web application


I was faced with a challenged to do software development without a QA engineer in my team.  In the company that I work with, developers do the unit testing, and QA engineers do the integration testing and end-to-end testing. Unfortunately, our QA engineer has moved on to a different company.

I started looking for a solution to implement some sort of an automatic integration testing for our projects. I came across some integration testing practice with maven while searching  the web. I asked some of my friends about their practices, and one my friends told me that they've been using cucumber (cukes.info). He told me that with cucumber, product managers can write the features (since it is just in plain english) and developers can build that feature. As it turned out, cucumber is more than just an integration-testing framework. it is a behavioral driven development framework.

So I decided to give it a try. I downloaded the cucumber-jvm project, read their examples and play with it. When I encountered some roadblocks, I go to stackoverflow to find the answers and if still I cannot find what I am looking for, I would ask my friends for some advice to see if they have encountered this problem.

At the end, I was able to make it work. Here are the steps that I did for my maven project.

First step is to add the dependencies in your pom.xml

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.java.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>${cucumber.java.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
              <groupId>info.cukes</groupId>
              <artifactId>cucumber-spring</artifactId>
              <version>${cucumber.java.version}</version>
              <scope>test</scope>
          </dependency>

I am using version 1.1.3. That's the latest version at this time. You can always check the maven repository for newer version.

The next step would be to make sure that you have the tomcat plugin in your project. This will allow your project to run tomcat before your integration test, and stop tomcat after your integration step.

           <plugin>
              <groupId>org.apache.tomcat.maven</groupId>
              <artifactId>tomcat7-maven-plugin</artifactId>
              <version>2.0</version>
              <configuration>
                <path>/keychest-extapi</path>
             </configuration>
              <executions>
                <execution>
                  <id>start-tomcat</id>
                  <phase>pre-integration-test</phase>
                  <goals>
                    <goal>run</goal>
                  </goals>
                  <configuration>
                    <fork>true</fork>
                    <port>9999</port>
                  </configuration>
                </execution>
                <execution>
                  <id>stop-tomcat</id>
                  <phase>post-integration-test</phase>
                  <goals>
                    <goal>shutdown</goal>
                  </goals>
                </execution>
              </executions>
            </plugin>
            <plugin>



Again, the tomcat7-maven-plugin version can vary. Always check for the latest version in the maven repository.
 In the example above, I changed the port to 9999, to avoid port conflict during start up (it uses 8080 by default ).

Next step is to add/modify your maven-surefire-plugin. We need to separate the integration testing from regular unit testing.

  <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.12.2</version>
                <configuration>
                    <argLine>-Duser.language=en</argLine>
                    <argLine>-Xmx1024m</argLine>
                    <argLine>-XX:MaxPermSize=256m</argLine>
                    <argLine>-Dfile.encoding=UTF-8</argLine>
                    <useFile>false</useFile>
                    <excludes>
                        <exclude>**/*IntegrationTest.java</exclude>
                    </excludes>
                </configuration>
                <executions>
                    <execution>
                        <id>default-test</id>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <phase>test</phase>
                        <configuration>
                            <excludes>
                                <exclude>**/*IntegrationTest.java</exclude>
                            </excludes>
                            <includes>
                                <include>**/*Test.java</include>
                            </includes>
                        </configuration>
                    </execution>
                    <execution>
                        <id>integration-tests</id>
                        <phase>integration-test</phase>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <configuration>
                             <excludes>
                               <exclude>**/*Test.java</exclude>
                             </excludes>
                             <includes>
                               <include>**/*IntegrationTest.java</include>
                             </includes>
                           </configuration>
                    </execution>
                </executions>
            </plugin>


Take note that all of your integration classes should be appended with "IntegrationTest" otherwise, it will not be executed.

Then you should define you maven-failsafe-plugin. The failsafe plugin is designed to run integration tests while the surefire plugins is designed to run unit tests.

                <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-failsafe-plugin</artifactId>
              <version>2.12.4</version>
              <configuration>
                <includes>
                  <include>**/*IntegrationTest*</include>
                </includes>
              </configuration>
              <executions>
                <execution>
                  <goals>
                    <goal>integration-test</goal>
                    <goal>verify</goal>
                  </goals>
                </execution>
              </executions>
            </plugin>



At this point, you can do "mvn clean install" and see if you are getting a successful build. The next step is to define your cucumber entry point class. The entry point is commonly named RunCukes, but since we are running cucumber during integration testing, we need to name the class as RunCukesIntegrationTest.

@RunWith(Cucumber.class)
@Cucumber.Options( glue = {"com.sample.project"} )
public class RunCukesIntegrationTest {
}


In all the examples that I have seen, this class does nothing but implement 2 annotations. The Cucumber.Options can have other parameters, but the important parameter is to define the glue. The glue value tells the package name where you put all your integration testing.

In your test/resources add a text file named student.feature.  This is where you put your cucumber features. You should place the student.feature file inside a package you define in your glue.

student-webapp/src/test/resources/com/sample/project/student.feature

Feature: When you query a student

  Scenario: Find student of a given student id
    Given A studentID 

    When the user of your rest api queries student
    Then returns student resource



The indentation is important. You can learn more about the format of .feature file in this link https://github.com/cucumber/cucumber/wiki/Feature-Introduction

Next is to define your inegration class. By convention with cucumber-jvm, they normally name the class as Stepdefs (e.g. StudentStepdefs) , but you can name it whatever you want.  First, I defined a base class for all my integration test to avoid code duplicity.

@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:cucumber.xml"})
public class BaseIntegration {
    public static final String SERVER_PORT = "9999";
    public static String SERVER_URL = "http://localhost:" + SERVER_PORT + "/student-webapp";

    @Autowired
    protected RestTemplate restTemplate;

}




Since I will be hitting a webapp, I have autowired spring RestTemplate. You also need to define the ContextConfiguration. Cucumber-jvm does not work if you wire you applicationContext directly. You have to define a file called cucumber.xml in your  maven src/test/resources/cucumber.xml, and the content of that file would simply be:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <import resource="classpath:applicationContext.xml"/>
</beans>


The next and final step is to define your integrationTest class that is wired to your .feature file.



public class StudentEndpointIntegrationTest  extends BaseIntegration {


    public static String STUDENT_URL = SERVER_URL + "/student/{studentID}";
    private String studentID;


    @Given("^A studentID$")
    public void givenAStudentId() {
        studentID = "14344";
    }



    @When("^the user of your rest api queries student$")
    public void getStudent() throws Exception {

        Map<String, String> params = new HashMap<String, String>();
        params.put("studentID",  studentID);

        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
        headers.add("userAuth" , "abc123" );

        HttpEntity<Object> httpEntity = new HttpEntity<Object>( headers );

        ResponseEntity<StudentResponse> responseEntity =  restTemplate.exchange(STUDENT_URL, HttpMethod.GET,httpEntity,StudentResponse.class,params);
        response = responseEntity.getBody();
    }



    @Then("^returns student resource$")
    public void itShouldHaveStudent() {
        assertThat(response.getStudents().size(),is(1));
    }



There are 3 annotations that should be used to match the .feature file. The parameter of these annotations (@Given, @When and @Then) is a string and can take regular expression.

Once your integration test class is defined, you can do "mvn clean install" and see that tomcat is started and your integration test is executed.

Hope this helps!

Tuesday, August 14, 2012

immutable classes in java

I've learned about designing immutable objects since Joshua Bloch published "Effective Java" book, but I never really practice it. I was very used to a traditional java beans with setters and getters, especially that my IDE can generate it for me.  Another reason is that we generate pojo from .xsd using jaxb, and jaxb does not generate immutable class yet.

But since I started using scala, I realized the value of having immutable objects in your code base.
Immutable objects greatly simplify your program, since they :
  • are simple to construct, test, and use
  • are automatically thread-safe and have no synchronization issues
  • do not need a copy constructor
  • do not need an implementation of clone
  • allow hashCode to use lazy initialization, and to cache its return value
  • do not need to be copied defensively when used as a field
  • make good Map keys and Set elements (these objects must not change state while in the collection)
  • have their class invariant established once upon construction, and it never needs to be checked again
  • always have "failure atomicity" (a term used by Joshua Bloch) : if an immutable object throws an exception, it's never left in an undesirable or indeterminate state
Here's an example of an immutable object.

public final class User {
    private final String name;
    private final String username;
    private final String password;
    private final int permission;
    
    private int hashCode;

    public User(String name, String username, String password, int permission) {
        this.name = name;
        this.username = username;
        this.password = password;
        this.permission = permission;
    }

    public String getName() {
        return name;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public int getPermission() {
        return permission;
    }

    @Override
    public int hashCode() {
         //This is Lazily loading. 
         if (hashCode == 0) {
            int result = name.hashCode();
            result = 31 * result + username.hashCode();
            result = 31 * result + password.hashCode();
            result = 31 * result + permission;
            hashCode = result;
        }
        return hashCode;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (permission != user.permission) return false;
        if (!name.equals(user.name)) return false;
        if (!password.equals(user.password)) return false;
        if (!username.equals(user.username)) return false;

        return true;
    }
}


But what if you have more than 4 fields? It is not going to be pretty having a constructor with more than 4 parameters.

In that case, you can add a Builder.


public final class User {
    private final String name;
    private final String username;
    private final String password;
    private final int permission;
    private final Date createDate;
    private final Date updateDate;

    private int hashCode;

    private User(Builder builder) {
        this.name = builder.name;
        this.username = builder.username;
        this.password = builder.password;
        this.permission = builder.permission;
        this.createDate = builder.createDate;
        this.updateDate = builder.updateDate;
    }

    public String getName() {  return name; }

    public String getUsername() { return username; }

    public String getPassword() { return password; }

    public int getPermission() { return permission; }

    public Date getCreateDate() { return createDate; }

    public Date getUpdateDate() { return updateDate; }

     //equals and hashCode are ommitted.


    //User Builder
    public static class Builder {
        private String name;
        private String username;
        private String password;
        private int permission;
        private Date createDate;
        private Date updateDate;

        public Builder(String username, String password) {
            this.username = username;
            this.password = password;
        }

        public Builder(User user) {
            this.name = user.getName();
            this.username = user.getUsername();
            this.password   = user.getPassword();
            this.permission = user.getPermission();
            this.createDate = user.getCreateDate();
            this.updateDate = user.getUpdateDate();
        }

        public Builder setName(String name) {
            this.name = name;
            return this;
        }
        
        public Builder setUsername(String username) {
            this.username = username;
            return this;
        }

        public Builder setPassword(String password) {
            this.password = password;
            return this;
        }
        
        public Builder setPermission(int permission) {
            this.permission = permission;
            return this;
        }        

        public Builder setCreateDate(Date createDate) {
            this.createDate = createDate;
            return this;
        }
        public Builder setUpdateDate(Date updateDate) {
            this.updateDate = updateDate;
            return this;
        }

        public User build() { return new User(this); }

    }

}
 
This is how you use it:
 
 
User user = new User.Builder("username","pasword").setCreateDate(new Date()).setName("Allan").setPermission(1).build();
        
//to change the name
user  = new User.Builder(user).setName("Homer").build();
        
//change password
user = new User.Builder(user).setPassword("secret").build(); 


Now what happened, if you wanna use immutable Pojo in Hibernate?  You can do so, by

  1. Add @Access annotation in the class level
  2. Make hashCode transient

Example:

@Entity
@Table(name = "system_monitor")
@SequenceGenerator(name="PK",sequenceName="system_monitor_id_SEQ")
@Access(AccessType.FIELD)
public class SystemMonitor {
    
    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PK")
    private Long id;  
 
    ...
 
 
 
     

This looks cool, but it requires a lot of coding. I agree with you. This is why I created this ImmutablePojoGenerator, to help you generate the code. You download the app here - immutablePojoGenerator
 



Sunday, August 07, 2011

Reactor Design Pattern - using java nio

While working on nginx, I got so interested with the architecture on how it can address the C10K problem. Unlike traditional servers, Nginx doesn't rely on threads to handle requests. Instead it uses a much more scalable event-driven (asynchronous) architecture.

But what is event-driven (asynchronous) architecture really? To simplify, let's talk about Asynchronous I/O. Asynchronous I/O is also known as Non-blocking I/O. It can be best describe by the reactor design pattern.

Wikipedia explains, the reactor design pattern is a concurrent programming pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers. (The Reactor pattern is closely related to the Observer/Observable pattern in this aspect: all dependents are informed when a single subject changes. The Observer pattern is associated with a single source of events, however, whereas the Reactor pattern is associated with multiple sources of events.)

Reactor design pattern is easier to understand by examples and diagrams. In this illustration, I will be using the java nio.

Until JDK 1.4, the Java platform did not support nonblocking I/O calls. With an almost one-to-one ratio of threads to clients, servers written in the Java language were susceptible to enormous thread overhead, which resulted in both performance problems and lack of scalability.


By this time, you have the basic idea of how the reactor pattern works! The key component are the Selector, Channels (and buffers) and the handler. Let's investigate them one by one.

Channels and Buffers
Channels are like streams in the original I/O package. All data that goes anywhere (or comes from anywhere) must pass through a Channel object. A Buffer is a container object. All data that is sent to a channel must first be placed in a buffer; likewise, any data that is read from a channel is read into a buffer.

A Buffer is an object, which holds some data, that is to be written to or that has just been read from. The addition of the Buffer object in NIO marks one of the most significant differences between the new library and original I/O. In stream-oriented I/O, you wrote data directly to, and read data directly from, Stream objects.

In the NIO library, all data is handled with buffers. When data is read, it is read directly into a buffer. When data is written, it is written into a buffer. Anytime you access data in NIO, you are pulling it out of the buffer.

The most commonly used kind of buffer is the ByteBuffer. A ByteBuffer allows get/set operations (that is, the getting and setting of bytes) on its underlying byte array. (There are other buffers as well. CharBuffer ShortBuffer, IntBuffer, LongBuffer, FloatBuffer, and DoubleBuffer). *NOTE: StringBuffer was added in Java 5 and it's not even part of nio package.

Basic Example on reading data from a Channel.

//getting the channel.
FileInputStream fin = new FileInputStream( "readandshow.txt" );
FileChannel fc = fin.getChannel();

//creating a buffer.
ByteBuffer buffer = ByteBuffer.allocate( 1024 );
fc.read( buffer );

You'll notice that we didn't need to tell the channel how much to read into the buffer. Each buffer has a sophisticated internal accounting system that keeps track of how much data has been read and how much room there is for more data.

Writing to a file.
FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" );
FileChannel fc = fout.getChannel();

//create a buffer, and put some data in it.
ByteBuffer buffer = ByteBuffer.allocate( 1024 );
for (int i=0; i<100; ++i) {
    buffer.put( i );
}

//The flip() method 
//prepares the buffer to have the 
//newly-read data written to another channel
buffer.flip();

//write data of the buffer.
fc.write( buffer );
Selector The central object in asynchronous I/O is called the Selector. A Selector is where you register your interest in various I/O events, and it is the object that tells you when those events occur. Example:
Selector selector = Selector.open();

//another way of getting selector instance.
Selector selector = SelectorProvider.provider().openSelector();
Handler The handler are your worker threads. They are responsible for the data that you read, and also for writing your data. You can pre-define a thread pool to handle all your request. There's nothing fancy about the handler. Check the link I provided below, for detailed example. Now that you are familiar with Selectors, Channels, buffers and Selector, we need to tie them together. But first, to accept connection from a client, you need a ServerSocketChannel. ServerSocketChannel is the nio version of ServerSocket that uses channeling and buffering methodology. Example:
// Create a new non-blocking server socket channel
serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);

// Bind the server socket to the specified address and port
// NOTE: HOST_ADDRESS is a type InetAddress and PORT is an int.
InetSocketAddress isa = new InetSocketAddress(HOST_ADDRESS, PORT);
serverChannel.socket().bind(isa);

//registering the ServerSocketChannel to the selector.
SelectionKey key = ssc.register( selector, SelectionKey.OP_ACCEPT );

The first argument to register() is always the Selector. The second argument, OP_ACCEPT, here specifies that we want to listen for accept events -- that is, the events that occur when a new connection is made. This is the only kind of event that is appropriate for a ServerSocketChannel.

Note the return value of the call to register(). A SelectionKey represents this registration of this channel with this Selector. When a Selector notifies you of an incoming event, it does this by supplying the SelectionKey that corresponds to that event. The SelectionKey can also be used to de-register the channel.

I'm sure by this time, you are ready to see a working sample code to implement this whole theory. I thought of writing an example, but this site did it very well. http://rox-xmlrpc.sourceforge.net/niotut/

Monday, June 06, 2011

Java Concurrency Utilities: using Semaphore

If you haven't done much of multi-threaded programming with Java 5, I am sure when you are ask of how prevent concurrent problems when 2 threads is accessing your data, you would think of synchronizing code, by making the method synchronized.

public class SyncCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }
}

Perhaps, you would probably also come up with an idea, instead of synchronizing a method, you would only synchronized a block of code.

    public void increment() {
        synchronized(c) {
            c++;
        }
    }

But with the concurrency API of java 5, they have added solutions for common threads requirements. In particular, the have added "Semaphore".

A Semaphore controls access to shared resource using a counter. If the counter has a value greater than zero, then access is allowed. If it is zero, then access is denied. What the counter is counting are permits that allow access to the shared resource. Ergo, to access the resource, a thread must be granded a permit from the semaphore.

Semaphore has two constructor:

Sempahore(int num)
Semaphore(int num, boolean how)

num specifies the initial permit count. The num parameter, specifies the number of threads that can access a shared resource at any one time. If the value of num is one, then only one thread can access the resource at any one time. By setting the how to true, you can ensure that waiting threads are granted a permit in the order in which they request access.

To acquire permit, call the acquire() method, which has these two forms:

void acquire() throws InterruptedException
void acquire(int num) throws InterruptedException

To release a permit, call release(), which has these two forms:

void release()
void release(int num)

The first form releases one permit. The second form releases the number of permits.

To use a semaphore to control access to a resource, each thread that wants to use that resource must first call acquire() before accessing the resource. When the thread is done with the resource, it must call release().

import java.util.concurrent.*;

class SemaphoreDemo {

    public static void main(String args[]) {
        //instantiate a Semaphore with value 1. Meaning, 1 thread can aquire permit at a time.
        Semaphore sem = new Semaphore(1);
      
        //instantiate 2 threads to access a shared resource at the same time.
        new IncThread(sem, "A");
        new DecThread(sem, "B");
    }

}

// A shared resource.
class Shared {
    static int count = 0;
}

class IncThread implements Runnable {
    String name;
    Semaphore sem;

    IncThread(Semaphore s, String n) {
        sem = s;
        name = n;
        new Thread(this).start();
    }

    public void run() {
        try {
        //acquiring the permit.
            sem.acquire();
            System.out.println(name + "gets a permit.");
            for( int i=0; i < 5; i++ ) {
                Shared.count++;
                System.out.println(name + ":" + Shared.count);
                Thread.sleep(10);
            }
            } catch (InterruptedException exc) {
               System.out.println(exc);
            }
        //releasing the permit.
        System.out.println(name + "releases the permit.");
        sem.release();
    }
}

class DecThread implements Runnable {
    String name;
    Semaphore sem;

    DecThread(Semaphore s, String n) {
        sem = s;
        name = n;
        new Thread(this).start();
    }

    public void run() {
        try {
            sem.acquire();
            System.out.println(name + "gets a permit.");
            for(int i=0; i < 5; i++ ) {
                Shared.count--;
               System.out.println(name + ":" + Shared.count);
            }
        } catch (InterruptedException exc) {
            System.out.println(exc);
        }
        System.out.println(name + "releases the permit.");
        sem.release();
    }
}


Notice that in the run methods, there are no synchronized keywords define. That is because, the semaphore actually implements it internally making it synchronized as you acquire for the lock.

Without the use of Semaphore, accesses to Shared.count by both threads would have occurred simultaneously, and the increments and decrements would be intermixed.

Monday, May 23, 2011

new try-catch in java

As we have experienced this, it is difficult to correctly close resources. For example, if you open a file or a socket, it is easy to forget to close it. Your code can easily ran out of file handles if not properly taken care of.
To make things easier, Java 7 introduced the new "try with resources" syntax. It automatically closes any AutoCloseable resources referenced in the try statement. For example, instead of manually closing streams ourselves, we can simply do this:

import java.io.*;

public class AutomaticResourceClosing {
  public static void main(String[] args) throws IOException {
    try (
      PrintStream out = new PrintStream (
          new BufferedOutputStream(
              new FileOutputStream("foo.txt")))
    ) {
      out.print("Unable to close resource");
    }
  }
}


Take note that there is never a semicolon at the end of the "try ()" declaration.

You can read more about other features by going to Java.net site ( http://jdk7.java.net/ ).

Thursday, November 11, 2010

TDD with javascript, JQuery, QUnit and Maven

I recently attended a Test Driven Development (TDD) training by Brett Schuchert of ObjectMentor.com and find it really useful! With TDD your code maintenance and evolution are easier and regression testing is less likely to have bugs because it prevents bugs from happening in the first place.

But what is TDD exactly? The instructor defined it as a "design practice". It uses tests as mechanism for discovery and feedback. He also added that TDD is not always the right thing to do. It depends on your application and requirements.

I was surprised to know that TDD idea has been around since late 50's. The original Mercury Rocket Project uses TDD.

The training inspired me and had me started looking on the how to apply TDD in javascript. The instructor advised some framework such as jsunit, which is good, but since our FEDs (Frontend developers) uses JQuery, I have to find a framework that has less learning curve and easy to use.

I searched and found out about Qunit (http://docs.jquery.com/Qunit). QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery project to test its code and plugins but is capable of testing any generic JavaScript code (and even capable of testing JavaScript code on the server-side).

Qunit is cool! But I have to integrate it with our maven project. I want our "maven build" to break if javascript unit test fails. (like how JUnit works ).

After further research, I found Rhino. Rhino is an open-source implementation of JavaScript written entirely in Java. It is typically embedded into Java applications to provide scripting to end users.

Given these 2 technologies, I configured maven to use qunit and Rhino to do javascript unit testing, and here's how I did it. ( If you have a better solution or comments, please let me know. )

One thing to keep in mind, when using this combo is that, you have to separate your javascript calculation logic from DOM-manipulation logic. You can extract them to a function or to an object, and unit test them separately. Use selenium to test the DOM-manipulation part. The reason being is that, you are executing javascript without the browser, and DOM-manipulation logic is easier to test using Selenium.

Here's an example on how to do it.

1) adder.js - This file is where you put the functions that you want to test.

//function that adds.
function adder(x,y) {
    return x + y;
}

2) adderTest.js - This file is your unitTest.
test("Adding numbers works", function() {
        expect(2);
        ok(adder, "function exists");
        equals(4, adder(2, 2), "2 + 2 = 4");
            }
);

3) suite.js - This file is your suite. It can contain many test.js files.

load("src/main/webapp/WEB-INF/js/qunit/qunit.js");

QUnit.init();
QUnit.config.blocking = false;
QUnit.config.autorun = true;
QUnit.config.updateRate = 0;
QUnit.log = function(result, message) {
    if(result == false) {
        print("FAILED: " + message);
        java.lang.System.exit(0);
    }else {
       print("PASS: " + message) ;
   }

};

load("src/main/webapp/WEB-INF/js/adder.js");
load("src/main/webapp/WEB-INF/js/adderTest.js");


NOTE:
a) Make sure you have downloaded qunit, and put it in your js directory. It is being referenced by suite.js
b) since I am using Maven 2, the path should starts from your base directory. (In my setup, it's in src/main/webapp/WEB-INF/js)

4) Add a dependency on Rhino and a maven plugin in your pom.xml:

...
<dependency>
   <groupid>rhino</groupid>
    <artifactid>js</artifactid>
    <version>1.7R1</version>
</dependency></pre>

...

<plugin>
    <groupid>org.codehaus.mojo</groupid>
    <artifactid>exec-maven-plugin</artifactid>
    <version>1.1</version>
    <executions>
        <execution>
        <phase>test</phase>
        <goals>
            <goal>java</goal>
        </goals>
        </execution>
    </executions>
    <configuration>
        <mainclass>org.mozilla.javascript.tools.shell.Main</mainclass>
        <arguments>
            <argument>-opt</argument>
            <argument>-1</argument>
            <argument>${basedir}/src/main/webapp/WEB-INF/js/suite.js</argument>
        </arguments>
    </configuration>
</plugin>
 



Now, when you execute "mvn test", it will execute the test suite, and run your test cases. Try adding this line in your addTest.js, and make sure to update the expect() method call.

equals(10,newAddition(5,0), "5 + 0 = 5");


making it:
test("Adding numbers works", function() {
     expect(3); //  <-- change to 3.
     ok(adder, "function exists");
        equals(4, adder(2, 2), "2 + 2 = 4");
        equals(10,adder(5,0), "5 + 0 = 5");
            }
);
);
It will break your maven build and tell you:

PASS: function exists
PASS: <span class="test-message">2 + 2 = 4</span>
FAILED: <span class="test-message">5 + 0 = 5</span>