I am new to JUnit and looking for advice. To start myself off I picked a simple helper object, that is used to manage a Table of Strings. The tests have a progression that argues against the granularity encouraged in the guides I've read.
Trying to keep the granularity fine without duplicating tests, I have created some tests for related methods such AddAndSize or GetAndPut. However, having the code to setup the test in multiple tests seems odd, I'm really trying to get my feet on the ground with jUnit and find the balance of test granularity. Here is my Target and TestCase -
- Have I started any bad habits that I should avoid?
- Is this a "typical" use of jUnit?
- When testing abstract classes, should I place the "Stub" target in the Tests or Main source folder?
DataTable is a Class to be tested
public class DataTable {
private ArrayList<String> columnNames = new ArrayList<String>();
private ArrayList<ArrayList<String>> theData = new ArrayList<ArrayList<String>>();
public DataTable() {
}
public int size() {
return theData.size();
}
public int cols() {
return columnNames.size();
}
public void addCol(String name) {
this.columnNames.add(name);
}
public int getCol(String name) {
return columnNames.indexOf(name);
}
public String getCol(int index) {
if (index < 0 | index >= columnNames.size()) {return "";}
return columnNames.get(index);
}
public String getValue(int row, String name) {
return getValue(row,this.getCol(name));
}
public String getValue(int row, int col) {
if (row < 0 | row >= theData.size()) {return "";}
if (col < 0 | col >= theData.get(row).size()) {return "";}
return theData.get(row).get(col);
}
public ArrayList<String> getNewRow() {
ArrayList<String> newRow = new ArrayList<String>();
this.theData.add(newRow);
return newRow;
}
}
And here is the Test Case I've written.
public class DataTableTest {
/**
* Test Constructor
*/
@Test
public void testDataTableConstruction() {
DataTable table = new DataTable();
assertNotNull(table);
}
/**
* Test GetNewRow and Size
*/
@Test
public void testGetNewRowAndSize() {
DataTable table = new DataTable();
assertEquals(0, table.size());
ArrayList<String> row = table.getNewRow();
assertNotNull(row);
assertEquals(1, table.size());
}
/**
*
*/
@Test
public void testColsAndAddCol() {
DataTable table = new DataTable();
assertEquals(0, table.cols());
table.addCol("One");
table.addCol("Two");
table.addCol("Three");
assertEquals(3, table.cols());
}
/**
*
*/
@Test
public void testGetColInt() {
DataTable table = new DataTable();
table.addCol("One");
table.addCol("Two");
table.addCol("Three");
assertEquals("One", table.getCol(0));
assertEquals("Two", table.getCol(1));
assertEquals("Three", table.getCol(2));
}
/**
*
*/
@Test
public void testGetColString() {
DataTable table = new DataTable();
table.addCol("One");
table.addCol("Two");
table.addCol("Three");
assertEquals(0, table.getCol("One"));
assertEquals(1, table.getCol("Two"));
assertEquals(2, table.getCol("Three"));
assertEquals(-1, table.getCol("Four"));
}
/**
*
*/
@Test
public void testGetValueIntString() {
DataTable table = new DataTable();
table.addCol("One");
table.addCol("Two");
table.addCol("Three");
ArrayList<String> row = table.getNewRow();
row.add("R1C1");
row.add("R1C2");
row.add("R1C3");
row = table.getNewRow();
row.add("R2C1");
row.add("R2C2");
row.add("R2C3");
assertEquals("R1C1", table.getValue(0, "One"));
assertEquals("R1C3", table.getValue(0, "Three"));
assertEquals("R2C2", table.getValue(1, "Two"));
assertEquals("", table.getValue(2, "One"));
assertEquals("", table.getValue(0, "Four"));
}
/**
*
*/
@Test
public void testGetValueIntInt() {
DataTable table = new DataTable();
table.addCol("One");
table.addCol("Two");
table.addCol("Three");
ArrayList<String> row = table.getNewRow();
row.add("R1C1");
row.add("R1C2");
row.add("R1C3");
row = table.getNewRow();
row.add("R2C1");
row.add("R2C2");
row.add("R2C3");
assertEquals("R1C1", table.getValue(0, 0));
assertEquals("R1C3", table.getValue(0, 2));
assertEquals("R2C2", table.getValue(1, 1));
assertEquals("", table.getValue(2, 0));
assertEquals("", table.getValue(0, 3));
}
}
> of data. I was thinking to @test "TestEmptyColumns", TestAddGetColumn and TestColumnBounds methods, followed by similar test for the Row methods and finally for the get/put data methods. If I create each of these as individual test methods that have to stand alone, the test get/put data methods will have to duplicate the code from the add/getColumn and add/getRow tests. I don't like duplicate code....