HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaModerate

Unit Tests for a Fraction Class

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
testsforfractionclassunit

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 add(Fraction f);
    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][0], tests[i][1]);

assertEqual

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][0], tests[i][1]);

assertEquals(tests[i][2], f.getNumerador());
assertEquals(tests[i][3], f.getDenominador());


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][0], tests[i][1]);
Fraction expected = new Fraction(tests[i][2], tests[i][3]);

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.

Code Snippets

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

assertEquals(tests[i][2], f.getNumerador());
assertEquals(tests[i][3], f.getDenominador());
Fraction f = new Fraction(tests[i][0], tests[i][1]);
Fraction expected = new Fraction(tests[i][2], tests[i][3]);

assertEquals(expected, f);

Context

StackExchange Code Review Q#83514, answer score: 10

Revisions (0)

No revisions yet.