android10

  • Increase font size
  • Default font size
  • Decrease font size

Unit Testing With JUnit & Eclipse From a .NET Perspective

E-mail Print
( 2 Votes )
Share

Introduction

Since I’ve been toying with Android development in the last few months, I’ve been focusing on the Android SDK side of things instead of fundamentals such as project set up, code cleanliness, and testing. This post starts rectifying that situation, and is an introduction to unit testing Java code using JUnit & Eclipse, with the context being that of Android development being done by a .NET guy. Should be fun, eh?
We’ll assume that we have everything that’s needed to develop for Android on a Windows machine. If not, you can refer to the Android SDK docs here to get that up and going.
We’ll also assume that you’ve installed the latest version of Eclipse, which comes with JUnit already available, meaning we don’t have to install it.
Since I’ve been toying with Android development in the last few months, I’ve been focusing on the Android SDK side of things instead of fundamentals such as project set up, code cleanliness, and testing. This post starts rectifying that situation, and is an introduction to unit testing Java code using JUnit & Eclipse, with the context being that of Android development being done by a .NET guy. Should be fun, eh?

We’ll assume that we have everything that’s needed to develop for Android on a Windows machine. If not, you can refer to the Android SDK docs here to get that up and going.
We’ll also assume that you’ve installed the latest version of Eclipse, which comes with JUnit already available, meaning we don’t have to install it.



Starting Up

Our first test is to create a new Java project. After that, we add two new interfaces to the src folder, IBoard and IPlayer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.personal.UnitTestingFun;
 
import java.util.List;
 
public interface IBoard {
 
int getRows();
int getColumns();
IPlayer getWinner();
List<IPlayer> getPlayers();
 
boolean MakeMove(int x, int y, IPlayer mover);
}
 
package com.personal.UnitTestingFun;
 
public interface IPlayer {
String getName();
}



Writing Tests

We will segregate our tests into a separate source folder called tests. To do this, right click on the root note in the package explorer and select New –> Source Folder.

unit_testing_from_net_01

Once we’ve done this our project should look like below.

unit_testing_from_net_02

Now to create our first JUnit test file, right click on the tests source folder and select New –> JUnit Test Case.

unit_testing_from_net_03

We go ahead and enter the options for our new test case, namely the package, the name of the test class, and the class under test.

unit_testing_from_net_04

You’ll notice that this dialog isn’t letting us continue onwards, namely because the class we want to test doesn’t exist yet. To get around this, we’ll go ahead and create an empty class called TicTacToeBoard in our src folder and indicate that implements the IBoard interface. Once we do this, Eclipse will yell at us because our new class doesn’t have the needed methods; we’ll let Eclipse create those for us as well, giving us a class definition as below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.personal.UnitTestingFun;
 
import java.util.List;
 
public class TicTacToeBoard implements IBoard {
 
@Override
public boolean MakeMove(int x, int y, IPlayer mover) {
// TODO Auto-generated method stub
return false;
}
 
@Override
public int getColumns() {
// TODO Auto-generated method stub
return 0;
}
 
@Override
public List<IPlayer> getPlayers() {
// TODO Auto-generated method stub
return null;
}
 
@Override
public int getRows() {
// TODO Auto-generated method stub
return 0;
}
 
@Override
public IPlayer getWinner() {
// TODO Auto-generated method stub
return null;
}
 
}

Now we can try to create our test case again, and sure enough, Eclipse lets us finish the job.

unit_testing_from_net_05

Clicking Next brings us to a new dialog where Eclipse asks us what methods on the class under test we actually want to write tests for.

unit_testing_from_net_06

Looks like a nifty feature, but since we want to just write enough code for a test and then for that test to pass, we’ll turn down Eclipse’s offer to help us and just click Finish. That gives us the beautiful test class below.

1
2
3
4
5
package com.personal.UnitTestingFun;
 
public class TicTacToeBoardTests {
 
}

So finally we can write our test. JUnit uses method attributes just like NUnit does to indicate that a given method is a test method. Our test looks like below.

1
2
3
4
5
@Test
public void BoardHasThreeRowsTest() {
TicTacToeBoard b = new TicTacToeBoard();
Assert.assertEquals(3, b.getRows());
}

To run the test, all we have to do is right click anywhere in the test body and select Run As –> JUnit Test.

unit_testing_from_net_07

This is actually pretty hot, given that the same functionality isn’t available integrated into Visual Studio without a relatively pricey tool (unless you’re using MSTest, which we determined wasn’t as good as NUnit in the above post). Our test results appear in the left-hand set of tabs as below.

unit_testing_from_net_08

Again, pretty hot.  We go ahead and make our tests pass by creating a backing store for the rows property and setting it to 3 when a TicTacToeBoard class is created; we also do the same thing for the columns property, since it’s exactly the same.

Our next test ensures that we have two players, and appears below.

1
2
3
4
5
@Test
public void BoardHasTwoPlayersTest() {
TicTacToeBoard b = new TicTacToeBoard();
Assert.assertEquals(2, b.getPlayers().size());
}

We fail with a NullPointerException because we haven’t written the code to handle players yet, which is exactly as expected. To get our test to pass, we modify our constructor to instantiate and populate our player list, which is held in a backing store for the Players property.

1
2
3
4
5
6
7
public TicTacToeBoard() {
_columns = 3;
_rows = 3;
_players = new ArrayList<IPlayer>();
_players.add(new Player());
_players.add(new Player());
}

1
2
3
4
5
private ArrayList<IPlayer> _players;
@Override
public List<IPlayer> getPlayers() {
return _players;
}

With this magic, our test passes.

unit_testing_from_net_09



Collection Test

Our next test is a test to ensure that our two players have the correct names, namely “Nought” and “Cross”. The tests to verify this appear below.

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void BoardHasOneCrossPlayerTest() {
TicTacToeBoard b = new TicTacToeBoard();
IPlayer crossPlayer = (IPlayer) CollectionUtils.find(b.getPlayers(),
new Predicate() {
@Override
public boolean evaluate(Object arg0) {
IPlayer p = (IPlayer) arg0;
return (p.getName() == "Cross");
}
});
Assert.assertNotNull(crossPlayer);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void BoardHasOneNoughtPlayerTest() {
TicTacToeBoard b = new TicTacToeBoard();
IPlayer crossPlayer = (IPlayer) CollectionUtils.find(b.getPlayers(),
new Predicate() {
@Override
public boolean evaluate(Object arg0) {
IPlayer p = (IPlayer) arg0;
return (p.getName() == "Nought");
}
});
Assert.assertNotNull(crossPlayer);
}

Note that the CollectionUtils functionality is provided by the Apache Commons-Collection library, and can be located here.

To make the above tests pass, we modify our Player class to accept a string representing the name of the player being created. The new class definition appears below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.personal.UnitTestingFun;
 
public class Player implements IPlayer {
 
public Player(String name) {
_name = name;
}
 
private String _name;
@Override
public String getName() {
return _name;
}
}

Then, we modify our tic tac toe board implementation to pass in the right player names when it’s constructed.

1
2
3
4
5
6
7
public TicTacToeBoard() {
_columns = 3;
_rows = 3;
_players = new ArrayList<IPlayer>();
_players.add(new Player("Nought"));
_players.add(new Player("Cross"));
}



Exception Test

Our final test will ensure that an out of bounds move will raise an exception. The test appears below.

1
2
3
4
5
@Test(expected=IndexOutOfBoundsException.class)
public void OutOfBoundsMoveThrowsExceptionTest() {
TicTacToeBoard b = new TicTacToeBoard();
b.MakeMove(4, 3, null);
}

Note that we augment the test attribute to indicate that we are expecting an exception. To get this test to pass, we implement the MakeMove method as below.

1
2
3
4
5
6
7
8
9
@Override
public boolean MakeMove(int x, int y, IPlayer mover) {
if (x <= 0 || x > _rows
|| y <= 0 || y > _columns) {
throw new IndexOutOfBoundsException();
} else {
return true;
}
}

And with that, our test passes, and we have 6 green lights.


unit_testing_from_net_10



Closing Thoughts

The integration of JUnit into Eclipse was pretty straightforward to work with, and wasn’t too much of a departure from working with NUnit in Visual Studio. I definitely missed the fluent interface; that said, there seems to be a way to get the same kind of functionality using custom matchers with JUnit 4.4+. I simply wasn’t able to get it to work in the time I gave myself for this post. With a working fluent interface, the unit testing picture in Java is better than the same picture in the .NET space from a cost perspective. MSTest equalizes things a bit, but you still need at least the Professional SKU for Visual Studio, and that is definitely not free.

Bottom line, if cost is an issue and everything else is the same, Java + Eclipse win from a unit testing perspective.


Thanks BareBones Coder for this article!!!


Comments (0)
Only registered users can write comments!
 

ANDROID10 --- TIP!!!

android10 tipIf you are writing an article and want to include your source code or a file...is pretty simple: first you save your article for first time to create it, then you edit it and at bottom of the editor, you have a button "Add Attachment"...just click it, upload your file...and that's all...too easy...
contact android10!!!