I wrote NUnit tests for class CharGrid from this homework assignment.
My goal here is DRY: I want to keep the testing code as short and simple as possible. In addition, want to run every test independently, as opposed to having a single method with a lot of asserts that either succeeds or fails as a whole.
I went through the NUnit documentation and found this "Parameterized TestFixture" annotation, which seemed to help fulfill my goal.
I would like to ask if there are any improvements to the testing code regarding what I just stated my goals were.
In addition, I would like to know if it is a good idea to have a separate CharGridTestFixture
class or if it is preferable to directly annotate class CharGrid
with a TestFixture
and it's methods with TestCaseSource
annotations and test them sort of in-place. This way there would be one less class.
Moreover, I used NUnit 2 without looking at any of the alternatives. Is it still a decent Unit testing framework or should I switch to NUnit 3 or something else?
using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
namespace CS108
{
This is a skeleton of the code to be tested:
// HW1 2-d array Problems
// CharGrid encapsulates a 2-d grid of chars and supports
// a few operations on the grid.
public class CharGrid {
private char[][] grid;
/**
* Constructs a new CharGrid with the given grid.
* Does not make a copy.
* @param grid
*/
public CharGrid(char[][] grid) {
this.grid = grid;
}
/**
* Returns the area for the given char in the grid. (see handout).
* @param ch char to look for
* @return area for given char
*/
public int charArea(char ch) {
return 0; // TODO ADD YOUR CODE HERE
}
/**
* Returns the count of '+' figures in the grid (see handout).
* @return number of + in grid
*/
public int countPlus() {
return 0; // TODO ADD YOUR CODE HERE
}
}
This is specification of the tests:
public class CharGridTestCase {
internal char [][] grid;
internal Dictionary<char, int> charArea;
internal int countPlus;
}
class CharGridTestCase1 : CharGridTestCase {
public CharGridTestCase1 () {
grid = new char[][] {
new [] { 'c', 'a', 'x' },
new [] { 'b', ' ', 'b' },
new [] { ' ', ' ', 'a' }
};
charArea = new Dictionary<char, int> {
{'a', 6},
{'b', 3},
{'c', 1},
{'x', 1},
{'z', 0},
{' ', 4}
};
countPlus = 0;
}
}
class CharGridTestCase2 : CharGridTestCase {
public CharGridTestCase2 () {
grid = new char[][] {
new [] {'a', 'b', 'c', 'd'},
new [] {'a', ' ', 'c', 'b'},
new [] {'x', 'b', 'c', 'a'}
};
charArea = new Dictionary<char, int> {
{ 'a', 12 },
{ 'b', 9 },
{ 'c', 3 },
{ 'd', 9 },
{ 'x', 1 },
{ ' ', 1 }
};
countPlus = 0;
}
}
class CharGridTestCase3 : CharGridTestCase {
public CharGridTestCase3 () {
grid = new char[][] {
new [] { ' ', ' ', 'p', ' ', ' ', ' ', ' ', ' ', ' ' },
new [] { ' ', ' ', 'p', ' ', ' ', ' ', ' ', 'x', ' ' },
new [] { 'p', 'p', 'p', 'p', 'p', ' ', 'x', 'x', 'x' },
new [] { ' ', ' ', 'p', ' ', ' ', 'y', ' ', 'x', ' ' },
new [] { ' ', ' ', 'p', ' ', 'y', 'y', 'y', ' ', ' ' },
new [] { 'z', 'z', 'z', 'z', 'z', 'y', 'z', 'z', 'z' },
new [] { ' ', ' ', 'x', 'x', ' ', 'y', ' ', ' ', ' ' }
};
charArea = new Dictionary<char, int> {
{ 'p', 25 },
{ 'x', 48 },
{ 'y', 12 },
{ 'z', 9 },
{ ' ', 63 }
};
countPlus = 2;
}
}
This is the code running the tests:
[TestFixture(typeof(CharGridTestCase1))]
[TestFixture(typeof(CharGridTestCase2))]
[TestFixture(typeof(CharGridTestCase3))]
class CharGridTestFixture<T> where T : CharGridTestCase, new() {
T tc;
CharGrid that;
public CharGridTestFixture(/*Type testCaseType*/) {
//tc = (CharGridTestCase)Activator.CreateInstance (testCaseType);
tc = new T();
that = new CharGrid (tc.grid);
}
IEnumerable CharAreaSource {
get {
foreach (var e in tc.charArea) {
yield return new TestCaseData (e.Key).Returns (e.Value);
}
}
}
[TestCaseSource("CharAreaSource")]
public int charArea(char c) {
return that.charArea(c);
}
[Test]
public void countPlus() {
Assert.AreEqual(tc.countPlus, that.countPlus());
}
}
}