Showing posts with label unit testing. Show all posts
Showing posts with label unit testing. Show all posts

Monday, 6 July 2015

Dynamic thread pool

Sometimes we're facing the problem, that we need to solve using dynamic thread pool.

By 'dynamic' I mean, that the pool is shrinking and growing automatically but it does have upper bound (so it can't grow indefinitely).

The API of the pool would be quite simple:

We should be able to submit the task to be executed asynchronously and monitor number of threads in the pool.
Having control over maximum number of threads and their longevity would be another feature.

Let's try to document functional requirements in the form of unit tests.
That would be our test setup:
Initial number of threads should be zero:
The execution of the tasks should be done concurrently:
Number of threads should grow automatically:
The size of thread pool should shrink when there is no active tasks and keep alive time was exceeded:
If the number of submitted task is greater than maximum threads number, we should block:
Actual implementation is quite simple, we need to use ThreadPoolExecutor:
There are two important things here.
First, we are required to create our own RejectedExecutionHandler to support blocking when the maximum number is exceed.
Secondly, we need to use the blocking queue of size zero (in our case I chose SynchronousQueue) - the queue needs to be filled up before we can create more than initial number of threads (in our case zero).
The whole project can be found at github.

Saturday, 29 June 2013

Handling command line arguments with args4j

From time to time, we need to write a tool that is using command line arguments as input.
Having an interface similar to unix command line tools is not a trivial task but with args4j it becomes quite easy.

We're going to write a fake tool called FileCompressor which process of invocation would look like:

where -i is input file name, -o output file name and -p the priority of the process.

Let's start with defining the dependencies of our project:

We'll need args4j, the rest is for testing.

Our fake FileCompressor requires a configuration that will be populated by args4j.

The configuration object has fields that will be mapped to command line arguments with args4j annotations.

And here is the class that will be invoked:

First of all, the arguments are parsed and configuration object is populated with them.
If there is a parsing problem, the exception is printed along with the usage (args4j can automatically print the usage of our application based on used annotations).

Testing our application requires some effort.
To begin with, we would like to mock completely the FileCompressor. There is no setter for it so we'll use Spring's ReflectionTestUtils together with Mockito.

We've also prepared some test data.

Let's check if the configuration object is populated properly and if the collabolator was invoked:

We would also like to know if the usage was printed when invalid arguments were passed.
To do that we need to use a spy, as we want to have the original behavior of populating argument, but we want to verify if printUsage method was invoked.

The last thing to check is if the exception was printed to the output stream when invalid arguments were passed.
Similarly we need to use a spy.

The whole project can be found at github.

Sunday, 19 May 2013

Testing JavaScript with Jasmine

When developing a web application, sooner or later we need to deal with JavaScript. To keep high code quality we must write unit tests.
Jasmine is a nice testing framework that allows us to write tests in a BDD manner.
Let's see how to use it in our project.

First of all, we need to incorporate it into our build. There is a maven plugin that will let us execute JavaScript tests within test build phase. We will add it to our pom.xml :
 
Apart from executing tests within build, we can run them during development phase.
The maven goal jasmine:bdd starts the Jetty server and under http://localhost:8234 URL we can see the results of executing test fixtures.
Reloading the page will execute the latest version of our code.

Let's see it in action. We have a simple JavaScript function residing in src/main/javascript/simple.js that increments the number passed as an argument.

The test (in Jasmine called spec) is located in src/test/javascript/simple_spec.js:

A test begins with a call to the global Jasmine function describe. 
Then the specific test cases are defined by calling function it.
We're testing the sunny day scenario and border case that throws the exception.
At the beginning as a sanity check we can test if the function is defined.
Jasmine has a lot of advanced features, we can even use mocks, expectations and argument matchers.

Nothing stops us from writing tests first and going through red-green-refactor cycle.
Let's write a function that will count the number of specific elements on our page.

The behaviour of our component is defined by following spec:

Before testing the case with one element, we're adding it to the document. In more complex case we could load the HTML content.

To implement, it we'll use jquery (we need to add it to src/main/javascript):

After executing mvn test we'll see a nice output:

Whole project can be found at github.

Wednesday, 3 October 2012

JUnit - hamcrest incompatibility

When we're using the latest version of JUnit (4.10) and hamcrest (1.3) together we might come across an unexpected behaviour.

Let's take a look at a simple test:

We might think that this test will fail because of the assertion, but the result is:

java.lang.NoSuchMethodError: org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Description;)V

That's because the default JUnit has a dependency to hamcrest 1.1 and also the artifact org.junit:junit has some hamcrest classes inside its jar. The hasSize matcher is not present in 1.1.

To avoid this problem we need to declare following dependencies in our project:

We need to use JUnit distribution that doesn't have any hamcrest internals and we need to exclude hamcrest dependency as well. What's interesting, we will not bump into this behaviour unless our assertion throws an error. 

Monday, 4 June 2012

Testing legacy code with Mockito spies

When we're working with legacy code, before making any changes we should write unit tests that will prevent us from breaking existing functionality. However most of the time, writing tests for legacy code is not easy.

Let's take a look at a simple example, that will try to show the challenges that we may face:

We have a class that calculates a discount for a customer based on his name and the amount of product that he's buying.

The problem hides in a static method call CustomerService.isImportantCustomer(). In the old code we can see a lot of static methods. Let's say that the one in our example is calling the database.
We need to mock it in order to write a proper unit test.

First of all, we will extract the static call to a separate method:

Refactoring using IDE (extracting methods, renaming etc.) is considered to be safe. Once we did that we can use a nice feature of Mockito - spies. 
If we declare our tested class as a spy, we can mock its method the same way as with standard mocks. The test for our class could look like:

The Mockito API for spies is similar to the one for mocks (the syntax is different for overriding void methods).

Sunday, 13 May 2012

Testing getters and setters with openpojo

Testing getters and setters is a little bit controversial topic. However, if we decide to do it or if we are forced to, we can ease the task with openpojo library.

Generally standard getters and setters can be generated by your IDE but testing them is a manual work - it takes some time and seems to be boring. So if the code was generated, why can't we automate the testing?
openpojo doesn't generate the unit test but it allows to test your POJO with a very small effort.

Let's take a look at an example. We have a Person class which is a POJO with generated getters and setters.


To test it we need to create just one class:

Our class defines which rules openpojo will apply and what tests it will execute. We also specify which package will be tested - if we have a lot of classes we can test them all in one go. In our case we're only testing if  getters and setters exist and if they behaving in a conventional way.
Running the class with any coverage tool will show us that the get and set methods are executed.
There are more rules that we can apply (like checking if there are no public fields, no primitive values etc.). We can write our own rules as well.

Sunday, 12 February 2012

Concurrent map with timed out elements using Guava library

Sometimes we have a need to use a map, in which elements live only for a specified amount of time.
We could implement such map ourselves (by overriding removeEldestEntry() from LinkedHashMap or using thread that will be removing elements periodically) but the better idea is to use already existing implementation. Google's guava library (http://code.google.com/p/guava-libraries) is the solution for us.
Let's write some simple unit tests to check the API and verify behaviour:
Map is created using the builder pattern. Apart from specifying the time of elements expiration, it allows among others, setting the maximum map's size or the listener that will be notified each time an entry is removed. As the built object is an instance of Cache, we need to create ConcurrentMap from it using asMap() method.
Two tests verify that added element is removed only when the timeout expires.