tags:

views:

51

answers:

2

I am trying to wrap my head around Junit testing and have read examples and what not, but still finding it difficult to understand how and what to test. Below is the Class with methods that I am creating my test cases from (as well as my test case Class).

import java.util.Iterator;

/**
 * The Probability class understands the likelihood that something will happen.
 * <p>
 * (c) Copyright Fred George 2008. All right reserved. Adapted and used for
 * educational purposes with permission from Fred George.
 * </p>
 * 
 * @author Fred George
 */
public class Probability {
    /** Value of receiver. */
    private final double value;
    /** Cannot happen. */
    private static final double IMPOSSIBLE_VALUE = 0.0;
    /** Will happen. */
    private static final double CERTAIN_VALUE = 1.0;
    /** Instance that represents outcome that will happen. */
    public static final Probability CERTAIN = new Probability(CERTAIN_VALUE);

    /**
     * Answer a new instance of the receiver with the specified value as the
     * likelihood that it occurs.
     * 
     * @param valueAsFraction
     *            value between 0.0 and 1.0
     * @throws
     */
    public Probability(final double valueAsFraction) {
        if (valueAsFraction < IMPOSSIBLE_VALUE || valueAsFraction > CERTAIN_VALUE) {
            throw new IllegalArgumentException("Specified value of "
                    + valueAsFraction + " is not between 0.0 and 1.0");
        }
        value = valueAsFraction;
    }

    /**
     * Answer the liklihood that the receiver will occur and the specified other
     * Probability will occur.
     * 
     * @return "and" of receiver and other Probability
     * @param other
     *            Probability being and'ed to receiver
     */
    public final Probability and(final Probability other) {
        return new Probability(this.value * other.value);
    }

    /**
     * Answer the value of the receiver as a scaled double between 0.0
     * (impossible) to 1.0 (certain).
     * <p>
     * This method is modeled after those in Double, Integer, and the rest of
     * the wrapper classes.
     * 
     * @return value of receiver as double between 0.0 and 1.0
     */
    public final double doubleValue() {
        return value;
    }

    /**
     * Answer true if the receiver has the same value as the other (assuming
     * other is a Probability).
     * 
     * @return true if receiver's value equals other's value
     * @param other
     *            Object (assumed to be Probability) to compare
     */
    public final boolean equals(final Object other) {
        if (!(other instanceof Probability)) {
            return false;
        }
        return this.value == ((Probability) other).value;
    }

    /**
     * Answers with a hashcode for the receiver.
     * @return the hash
     */
    public final int hashCode() {
        return (new Double(this.value)).hashCode();
    }

    /**
     * Answer true if the combined likelihoods of the specified Collection of
     * Probabilities sums to certain (100%).
     * 
     * @return true if combined likelihoods is 100%
     * @param probabilities
     *            Collection of likelihoods to sum
     */
    public static final boolean isTotalCertain(final java.util.Collection probabilities) {
        double sum = 0;
        for (Iterator i = probabilities.iterator(); i.hasNext();) {
            sum += ((Probability) i.next()).value;
        }
        return sum == CERTAIN_VALUE;
    }

    /**
     * Answer the liklihood that the receiver will not occur.
     * 
     * @return "not" of receiver
     */
    public final Probability not() {
        return new Probability(CERTAIN_VALUE - value);
    }

    /**
     * Answer the liklihood that the receiver will occur or the specified other
     * Probability will occur, or both.
     * 
     * @return "or" of receiver and other Probability
     * @param other
     *            Probability being or'ed to receiver
     */
    public final Probability or(final Probability other) {
        return this.not().and(other.not()).not(); // DeMorgan's Law
    }

    /** Multiplier from double to percentage. */
    private static final int PERCENTAGE_MULTIPLIER = 100;

    /**
     * Answers a String representation of the receiver suitable for debugging.
     * 
     * @return String representation of the receiver
     */
    public final String toString() {
        int percentage = (int) (value * PERCENTAGE_MULTIPLIER);
        return percentage + "%";
    }
}

And here is what I've attempted for some of the test cases. I haven't tried them all, but am stuck on the "equals" method.

package edu.psu.ist.probability;

import edu.psu.ist.decision.Decision;
import junit.framework.TestCase;
import junit.framework.*;

public class ProbabilityTest extends TestCase {
    private Probability p1;
    private Probability p2;
    private Probability p3;
    private Decision d1;


    protected void setUp() {
        p1 = new Probability(.6);
        p2 = new Probability(.7);
        p3 = new Probability(.6);
        d1 = new Decision("No decision made");
    }

    public void testHashCode() {
        fail("Not yet implemented");
    }

    public void testProbability() {
        assertEquals(p1.doubleValue(), .6);
        try{
            p1 = p3;
            //get here, bad
            fail("Should raise an IllegalArgumentException");
        }catch (IllegalArgumentException e){
            //good!
        }

    }

    public void testAnd() {
        assertEquals((p1.and(p2)).doubleValue(), .42);
    }

    public void testDoubleValue() {
        assertEquals(p1.doubleValue(), .6);
    }

    public void testEqualsObject() {
        assertEquals(p1, p3);
        //assertEquals(p1, p2);
        assertTrue(!p1.equals(p2));
        assertTrue(p1.equals(p3));


        /*Probability p1 = new Probability (.7);
        Probability p2 = new Probability (.6);
        Decision d1 = new Decision();
        boolean TRUE = p1.equals(p2);
        boolean FALSE = p1.equals(d1);

        try {
            p1.equals(p2);
            p1.equals(d1);
            p1.equals(null);
        } catch (NullPointerException ex){
            // exception should be thrown
        }
//      assertEquals("Return true if theses values are the same",p1.doubleValue(), p2.doubleValue());
//      assertEquals("Return false if not equal", p1.doubleValue(), d1.equals(p1.doubleValue()));
//      assertNotSame("Objects are not the same", p1, d1);
        */
    }

    public void testIsTotalCertain() {
        fail("Not yet implemented");
    }

    public void testNot() {
        fail("Not yet implemented");
    }

    public void testOr() {
        fail("Not yet implemented");
    }

    public void testToString() {
        fail("Not yet implemented");
    }

}

Maybe someone can shed some light that will help me understand this process more clearly.

+3  A: 

You've chosen a somewhat hairy first step, comparing floating point numbers can be non-intuitive. You want to make sure you use the assertXXX methods with a delta:

double x = 1.3;
double y = 13.0 / 10.0;
double acceptable_difference = 0.05;
assertEquals(x,y, acceptable_difference);

That should return true as you're unlikely to make your value match.

In terms of writing your tests just think what you want to make sure of, being careful to test the boundary conditions, like if one Probability is 0.

Speaking of floating point I bet you could find uses of not that get you below 0.0, if ever so slightly. That's something to take a look at.

Paul Rubel
A: 

In your particular case, the code seems straight forward for the most part. Try to focus on testing the behavior of the code.

Here are some test scenarios for equals method.

Pass in a non-Probability object

String test = "foo";
assertTrue(!p1.equals(test));

Should the test pass? Should the test expect an exception?

Pass in null

assertTrue(!p1.equals(null));

Should the test pass? Should the test expect an exception?

Kin U.