# Unit Tests for a Fraction Class

Posted on

Problem

As my first Java homework, I wrote a class to handle fractions. This `Fraction` class implements basic operations for the fractions (addition, subtraction, multiplication and division) and follows this interface*:

``````interface FractionInterface {
public int getNumerator();
public int getDenominator();

public Fraction sub(Fraction f);
public Fraction mult(Fraction f);
public Fraction div(Fraction f);
public int comparesTo(Fraction f);
}
``````

This interface doesn’t actually exist, it’s just a way to illustrate how the class works so I don’t have to add the actual implementation.

Even though the code is incredibly easy and straightforward, I decided to, as an exercise, write a few unit tests using JUnit. The tests should verify that:

• All operations work correctly.
• All fractions should be simplified. (E.g: `5/10 -> 1/2`)
• An `ArithmeticException` is thrown when the denominator is set to 0.
• Only the numerator can be negative, if the fraction is negative.

Even though it works, I wasn’t very pleased with the final result. It doesn’t feel very clean, specially the way I stores the predefined values, and I don’t really know what else could be improved. That’s how it looks:

``````public class FractionTest {

@Test (expected = ArithmeticException.class)
public void divisionByZeroShouldThrow() {
@SuppressWarnings("unused")
Fraction f = new Fraction(1, 0);
}

@Test
public void fractionsShouldBeSimplified() {
int tests[][] = {
{36, 90, 2, 5},
{83, 75, 83, 75},
{18, 86, 9, 43},
{72, 52, 18, 13},
{10, 37, 10, 37},
{99, 45, 11, 5},
{54, 58, 27, 29},
{61, 61, 1, 1},
{46, 36, 23, 18},
{96, 93, 32, 31}
};

for (int i = 0; i < tests.length; i++) {
Fraction f = new Fraction(tests[i], tests[i]);

assertEquals(tests[i], f.getNumerator());
assertEquals(tests[i], f.getDenominator());
}
}

@Test
public void negativeFractionsShouldHaveTheNominatorNegative() {
int tests[][] = {
{-35, 3, -35, 3},
{3, -5, -3, 5}
};

for (int i = 0; i < tests.length; i++) {
Fraction f = new Fraction(tests[i], tests[i]);

assertEquals(tests[i], f.getNumerator());
assertEquals(tests[i], f.getDenominator());
}
}

@Test
int tests[][] = {
{36, 90, 83, 75, 113, 75},
{18, 86, 72, 52, 891, 559},
{10, 37, 99, 45, 457, 185},
{54, 58, 61, 61, 56, 29},
{46, 36, 96, 93, 1289, 558}
};

for (int i = 0; i < tests.length; i++) {
Fraction f1 = new Fraction(tests[i], tests[i]);
Fraction f2 = new Fraction(tests[i], tests[i]);

assertEquals(tests[i], f.getNumerator());
assertEquals(tests[i], f.getDenominator());
}
}

@Test
public void subtractionsShouldWork() {
int tests[][] = {
{36, 90, 83, 75, -53, 75},
{18, 86, 72, 52, -657, 559},
{10, 37, 99, 45, -357, 185},
{54, 58, 61, 61, -2, 29},
{46, 36, 96, 93, 137, 558}
};

for (int i = 0; i < tests.length; i++) {
Fraction f1 = new Fraction(tests[i], tests[i]);
Fraction f2 = new Fraction(tests[i], tests[i]);

Fraction f = f1.sub(f2);

assertEquals(tests[i], f.getNumerator());
assertEquals(tests[i], f.getDenominator());
}
}

@Test
public void multiplicationsShouldWork() {
int tests[][] = {
{36, 90, 83, 75, 166, 375},
{18, 86, 72, 52, 162, 559},
{10, 37, 99, 45, 22, 37},
{54, 58, 61, 61, 27, 29},
{46, 36, 96, 93, 368, 279}
};

for (int i = 0; i < tests.length; i++) {
Fraction f1 = new Fraction(tests[i], tests[i]);
Fraction f2 = new Fraction(tests[i], tests[i]);

Fraction f = f1.mult(f2);

assertEquals(tests[i], f.getNumerator());
assertEquals(tests[i], f.getDenominator());
}
}

@Test
public void divisionsShouldWork() {
int tests[][] = {
{36, 90, 83, 75, 30, 83},
{18, 86, 72, 52, 13, 86},
{10, 37, 99, 45, 50, 407},
{54, 58, 61, 61, 27, 29},
{46, 36, 96, 93, 713, 576}
};

for (int i = 0; i < tests.length; i++) {
Fraction f1 = new Fraction(tests[i], tests[i]);
Fraction f2 = new Fraction(tests[i], tests[i]);

Fraction f = f1.div(f2);

assertEquals(tests[i], f.getNumerator());
assertEquals(tests[i], f.getDenominator());
}
}

@Test
public void comparisonsShouldWork() {
int tests[][] = {
{36, 90, 83, 75, -1},
{18, 86, 72, 52, -1},
{10, 37, 99, 45, -1},
{54, 58, 61, 61, -1},
{46, 36, 96, 93, 1},
{36, 6, 6, 1, 0}
};

for (int i = 0; i < tests.length; i++) {
Fraction f1 = new Fraction(tests[i], tests[i]);
Fraction f2 = new Fraction(tests[i], tests[i]);

assertEquals(tests[i], f1.comparesTo(f2));
}
}
}
``````

Solution

Instead of suppressing the warning here for the unused variable `f`:

``````@Test (expected = ArithmeticException.class)
public void divisionByZeroShouldThrow() {
@SuppressWarnings("unused")
Fraction f = new Fraction(1, 0);
}
``````

You could just omit the local variable completely:

``````@Test (expected = ArithmeticException.class)
public void divisionByZeroShouldThrow() {
new Fraction(1, 0);
}
``````

Instead of comparing the values of the getters like this:

``````Fraction f = new Fraction(tests[i], tests[i]);

``````

It would be simpler and more intuitive to compare `Fraction` objects directly (assuming the class implements the `equals` method properly):

``````Fraction f = new Fraction(tests[i], tests[i]);
Fraction expected = new Fraction(tests[i], tests[i]);

assertEquals(expected, f);
``````

Except, in the case when the behavior of `.equals` itself would be called into question, for example when verifying that `6/8` gets simplified properly to `3/4`. To test that `new Fraction(6, 8)` becomes `3/4`, you cannot use `.equals`,
you need the explicit assertions on the numerator and the denominator being 3 and 4, respectively.

You could create the fraction objects inside the test array:

``````        {new Fraction(2, 5), 36, 90},
{new Fraction(83, 75), 83, 75},

{new Fraction(36, 90), new Fraction(83, 75), 30, 83},
{new Fraction(18, 86), new Fraction(72, 52), 13, 86},
``````

Which still looks quite readable, and might be a bit clearer than what you have (because it’s more obvious which is the input to be tested and which is the expected result).

``````        // the following represents f1 + f2 = result (each with two entries for numerator/denominator)
``````        {36, 90, 83, 75, 113, 75},  // (36 / 90) * (83 / 75) = (113 / 75)