Scaling method fails to satisfy JUnit - java

I’m trying to make a position, length and circle classes based on given JUnit in order to eventually output them graphically. But I’m stuck in one of the methods for days now.
I tried to truncate precisions but then my equals method failed.
JUnit for Scale:
public void testScale(){
Length inch2 = Length.unit.scale(320.0);
assertTrue(inch2 != null);
assertEquals(Length.inch,inch2);
assertFalse(inch2.equals(Length.unit));
Length unit2 = Length.cm.scale(1.0/125.98425197);
assertTrue(unit2 != null);
assertEquals(Length.unit,unit2); // This is the line my scale method fails
// Here my unit2 has a length of 1.0001249999881234
// and my constant cm has a length of 1.0 but
// truncating those precisions caused my equals
// method to fails.
assertFalse(unit2.equals(Length.cm));
Length z = Length.meter.scale(0);
assertTrue(z != null);
assertEquals(Length.zero,z);
assertFalse(z.equals(Length.meter));
assertFalse(Length.zero.equals(null));
}
My scale method:
public Length scale(double d) {
if (d < 0)
throw new IllegalArgumentException();
else {
return new Length(d* this.length);
}
}
I suspect maybe the problem is coming from my equals method but in the given JUnit it is passing the tests.
JUnit for Equals:
public void testEquals(){
assertFalse(Length.unit.equals("Not a length"));
assertFalse(Length.inch.equals(null));
assertEquals(Length.zero,Length.unit.scale(0.0000001));
assertTrue(Length.unit.scale(0.0000001).compareTo(Length.zero) == 0);
assertTrue(Length.zero.compareTo(Length.unit.scale(0.0000001)) == 0);
assertFalse(Length.unit.scale(0.0000015).equals(Length.zero));
assertTrue(Length.unit.scale(0.0000015).compareTo(Length.zero) > 0);
assertTrue(Length.zero.compareTo(Length.unit.scale(0.0000015)) < 0);
}
My Equals Method:
#Override
public boolean equals(Object other) {
if (other == null || !(other instanceof Length)) {
return false;
}
Length o = (Length) other;
if (Math.abs(this.length - o.length) < 0.000001) {
return true;
} else {
return false;
}
}
Please help
Link for all my code:
https://www.dropbox.com/sh/bz400f8y0ufx381/59aUTilrBt

You are testing too many things at once.
A unit test should be one unit of code - one aspect of the code as opposed to everything at once.
I also notice that you don't have any of your test methods annotated with #Test; you should be doing this with JUnit4 tests.
So, for your first test, you have a relatively small scale method you want to exercise. Let's enumerate the cases:
d < 0. I should expect an IllegalArgumentException.
d >= 0. I should expect a new instance of Length with a size some multiple of d and whatever the set length of the instance is.
What this looks like is two discrete tests:
#Test(expected = IllegalArgumentException.class)
public void scaleShouldThrowExceptionWhenInvalidLength() {
}
#Test
public void scaleShouldBehaveNormally() {
}
I leave you to fill in the blanks, since I don't know what object scale is attached to.
Equals is the same way - you want to exercise each condition of the equivalence.
By the way, you can do return Math.abs(this.length - o.length) < 0.000001 for your conditions. return true and return false scream bad practice.
The object you're passing in is null.
The object you're passing in is not an instance of Length.
The object you're passing in fails Math.abs(this.length - o.length) < 0.000001.
The object you're passing in passes Math.abs(this.length - o.length) < 0.000001.
So the above are four discrete tests.
#Test
public void equalsShouldFailIfNull() {
}
#Test
public void equalsShouldFailIfNotInstanceOfLength() {
}
#Test
public void equalsDoesNotMeetCondition() {
}
#Test
public void equalsMeetsCondition() {
}
Filling in the blanks, I leave as an exercise to the reader.
Be very careful when dealing with floating-point numbers. You won't always get an exact representation back (that is, you may get an imprecise value when dealing with fractions). Be certain that your equals method is well-defined to respect what could happen when you don't have an exact decimal value to work with.
Alternatively, if you really need the decimal precision, use a BigDecimal instead.

Related

Unit testing a method that returns the smallest value of an array

I have kind of a theoretical question. Given a method:
public int findSmallestArrayValue(int[] values){
int smallest = values[0];
for (int count = 0; count < values.length; count++){
if(values[count] < smallest){
smallest = values[count];
}
}
return smallest;
}
What would you potentially unit test here ? So far I have come up with:
assertEquals(array.findSmallestArrayValue(new int[]{5,11,3,6,8}),3);
assertEquals(array.findSmallestArrayValue(new int[]{5,5,5,5,5}),5);
assertEquals(array.findSmallestArrayValue(new int[]{-1,2,3,4,5}),-1);
Now I ask myself, what else would be useful/possible ? For example I came up with:
values that are larger than int, but Java won't let me do that ?
empty array, how to do that ?
filling up the int array with more values than int can take ?
Especially what is actually useful and what is not ? What do you think ?
Your current test ideas are good so far. Here's the additional tests I would consider adding
#Test(expected = IllegalArgumentException.class)
public void emptyArrayIsNotAcceptedArgument() {
array.findSmallestArrayValue(new int[]{});
}
#Test(expected = IllegalArgumentException.class)
public void nullArrayIsNotAcceptedArgument() {
array.findSmallestArrayValue(null);
}
#Test
public void lastValueIsSmallest() {
assertEquals(array.findSmallestArrayValue(new int[]{0,-1}),-1);
}
As for your ideas:
values that are larger than int, but Java won't let me do that ?
Java's compiler will not allow you to pass in anything but an int[] to that method, so no test needed
filling up the int array with more values than int can take ?
Java arrays cannot have a size larger than the max int value. This wouldn't really add much benefit to your tests anyways.
Some cases that come to mind:
(Your suggestion) Check for empty array
values.length > 0
Check for null array
values != null
These would be cases you would handle within the method, and ensure that the method outputs the correct error message or Exception that you write in.
You always want to test boundary conditions. So you will want to test:
Null
Empty
One
Several
All negatives
Mix of positives and negatives
You had some of those and others have provided the others. Keep in mind that having a test like this:
assertEquals(array.findSmallestArrayValue(new int[]{5,11,3,6,8}),3);
makes having a test like this of very little value:
assertEquals(array.findSmallestArrayValue(new int[]{5,11,6,8}),5);
Now when you do encounter a defect in a method, you will want to write a test that exposes the conditions of that defect.
Awesome! Thank you for the answers, I appreciate it! I think a good mix is key here:
public class ArrayValuesTest {
ArrayValues array = new ArrayValues();
#Test
public void returnsSmallestValue() {
assertEquals(array.findSmallestArrayValue(new int[]{5,11,3,6,8}),3);
assertEquals(array.findSmallestArrayValue(new int[]{5}),5);
assertEquals(array.findSmallestArrayValue(new int[]{0}),0);
assertEquals(array.findSmallestArrayValue(new int[]{-5,-8,-3,-6,-11}),-11);
assertEquals(array.findSmallestArrayValue(new int[]{-20,11,-3,6,-8}),-20);
}
#Test(expected = ArrayIndexOutOfBoundsException.class)
public void emptyArrayIsNotAcceptedArgument() {
array.findSmallestArrayValue(new int[]{});
}
#Test(expected = NullPointerException.class)
public void nullArrayIsNotAcceptedArgument() {
array.findSmallestArrayValue(null);
}
}
Do you think it's bad practice to include several asserts in the first test method instead of having separate test methods ?

Junit assert OR condition in my test case

In my test case, I get an integer value:
int val = getXXX();
Then, I would like to check if val either equals to 3 or equals to 5 which is OK in either case. So, I did:
assertTrue(val == 3 || val==5);
I run my test, the log shows val is 5, but my above assertion code failed with AssertionFailedError. Seems I can not use assertTrue(...) in this way, then, how to check true for OR condition?
You can use Hamcrest matchers to get a clearer error message here:
int i = 2;
assertThat(i, Matchers.either(Matchers.is(3)).or(Matchers.is(5))
or
int i = 2;
assertThat(i, Matchers.anyOf(Matchers.is(3),Matchers.is(5)));
This will more clearly explain:
Expected: (is <3> or is <5>)
but: was <2>
showing exactly the expectation and the incorrect value that was provided.
ive tried to write quick test:
#Test
public void testName() {
int i = 5;
junit.framework.Assert.assertTrue(i == 3 || i == 5);
}
its passing always so i guess there is some inbetween code when your value is changed.
You can use
org.junit.Assert.assertEquals(5, i);
to check value - this assertion will print out nice info whats wrong, for example:
java.lang.AssertionError:
Expected :4
Actual :5
While Harmcrest matchers can do the job, these constants can be easily refactored to a more meaninful constant, like a list of valid values. Then you can use the contains method to check that the value is present in the list - IMO is also easier to read:
public class Foo {
public static final List<Integer> VALID_VALUES = Arrays.asList(3, 5);
}
#Test
public void testName() {
int i = 5;
Assert.assertTrue(Foo.VALID_VALUES.contains(i));
}
In my case I wanted to do some complex assertion logic, so I simply implemented a method that returns a boolean and it did the job, the way it would be implemented in this example is as follows:
private Boolean is3or5(Integer val) {
if(val == 3 || val == 5) {
return true;
}
return false;
}
Then do the assertion:
assertTrue(is3or5(val));
Of course the method can contain more complex logic if needed
with TestNG this is also possible
Assert.assertTrue(val == 3 || val==5)

compareTo and Strings using a Scanner

I am implementing a form of leftist min heap, which stores arbitrary words by length. So, I have written a wrapper class for Scanner, and changed the compareTo, like so
public class ScannerWrapper implements Comparable<String>
//a Scanner, sc and a String, current
public int compareTo(String str){
if(current.length() > str.length()) return -1;
if(current.length() > str.length()) return 1;
else return 0;
}
where current = sc.next() and is not the \n character.
in this case, if I have ScannerWrapper.next() > foo , where foo is an arbitrary string of length > ScannerWrapper.next();
will it use the compareTo(String) that I have written, returning false, or will it do some other random thing?
After reading your question several times I think I understand what you're asking now. If you're trying to compare two instances of class ScannerWrapper with the comparison operators, then no, it's not going to work.
You can't overload operators in Java (you can in C++), therefore in order to compare instances of ScannerWrapper with each other you're going to have to call the compareTo() method.
Also, both of your if statement conditions are the same, so you might want to fix that up.
It's difficult to understand your question - so you might consider rephrasing it. Here's a shot in the dark :
public class ScannerWrapper implements Comparable<ScannerWrapper>
//your wrapper has a handle to the scanned data. Presumably it's
//initialized on construction, which is omitted here
private final String scannedData;
public String getScannedData() {
return this.scannedData;
}
public int compareTo(ScannerWrapper other) {
//if this scannedData is longer than the other, return 1
if(this.str.length() > other.getStr().length()) {
return 1;
} else if(this.scannedData.length() < other.getScannedData().length()) {
//if the other scannedData is longer return -1
return -1;
}
//if they are equal return 0
return 0;
}
}

Java error: "Comparison method violates its general contract!"

I have this code:
package org.optimization.geneticAlgorithm;
import org.optimization.geneticAlgorithm.selection.Pair;
public abstract class Chromosome implements Comparable<Chromosome> {
public abstract double fitness();
public abstract Pair<Chromosome> crossover(Chromosome parent);
public abstract void mutation();
public int compareTo(Chromosome o) {
int rv = 0;
if (this.fitness() > o.fitness()) {
rv = -1;
} else if (this.fitness() < o.fitness()) {
rv = 1;
}
return rv;
}
}
And every time I run this code I get this error:
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:835)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:453)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:376)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:182)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at java.util.Collections.sort(Collections.java:155)
at org.optimization.geneticAlgorithm.GeneticAlgorithm.nextGeneration(GeneticAlgorithm.java:74)
at org.optimization.geneticAlgorithm.GeneticAlgorithm.execute(GeneticAlgorithm.java:40)
at test.newData.InferenceModel.main(InferenceModel.java:134)
I use OpenJDK7u3 and I return 0 when the objects are equal. Can someone explain this error to me?
You could get into that situation if you have any NaN values:
For example:
public class Test
{
public static void main(String[] args) {
double a = Double.NaN;
double b = Double.NaN;
double c = 5;
System.out.println(a < b);
System.out.println(a > b);
System.out.println(b < c);
System.out.println(c < b);
}
}
All of these print false. So you could end up in a situation where two non-NaN values were both deemed "equal" to NaN, but one was greater than the other. Basically, you should work out how you want to handle NaN values. Also check that that really is the problem, of course... do you really want NaN values for your fitness?
Most probably your fitness function is broken, in one of two ways:
It doesn't always return the same value when called on the same object.
It could return NaNs. Your compareTo() is not transitive in the presence of NaNs, as explained by Jon Skeet.
You could rewrite your comparison function using Double.compare():
public int compareTo(Chromosome o) {
return Double.compare(o.fitness(), this.fitness());
}
This requires less code and takes care of corner cases (NaNs, the negative zero etc). Of course, whether these corner cases should be arising in the first place is for you to decide and address.
You should try adding if (this == o) return 0;
Because the same object must be returned equal.

How to return a flag plus an optional message in Java?

I want to write a method in Java that verifies that some conditions hold on some data, and acknowledges that the data is valid or produces an appropriate error message otherwise.
The problem is that we cannot return more than one thing from a method, so I'm wondering what the best solution is (in terms of readability and maintainability).
First solution. Easy, but we cannot know what exactly made the check fail:
boolean verifyLimits1(Set<Integer> values, int maxValue) {
for (Integer value : values) {
if (value > maxValue) {
return false; // Out of limits
}
}
return true; // All values are OK
}
Second solution. We have the message, but we are using exceptions in a way that we shouldn't (besides, it should probably be a domain-specific checked exception, too much overhead IMO):
void verifyLimits2(Set<Integer> values, int maxValue) {
for (Integer value : values) {
if (value > maxValue) {
throw new IllegalArgumentException("The value " + value + " exceeds the maximum value");
}
}
}
Third solution. We have a detailed message, but the contract is not clean: we make the client check whether the String is empty (for which he needs to read the javadoc).
String verifyLimits3(Set<Integer> values, int maxValue) {
StringBuilder builder = new StringBuilder();
for (Integer value : values) {
if (value > maxValue) {
builder.append("The value " + value + " exceeds the maximum value/n");
}
}
return builder.toString();
}
Which solution would you recommend? Or is there a better one (hopefully!)?
(Note: I made up this little example, my real use case concerns complex conditions on heterogeneous data, so don't focus on this concrete example and propose Collections.max(values) > maxValue ? "Out of range." : "All fine." :-).)
If you need more than a single value you should return a simple class instance instead. Here is an example of what we use in some cases:
public class Validation {
private String text = null;
private ValidationType type = ValidationType.OK;
public Validation(String text, ValidationType type) {
super();
this.text = text;
this.type = type;
}
public String getText() {
return text;
}
public ValidationType getType() {
return type;
}
}
This uses a simple Enumeration for the type:
public enum ValidationType {
OK, HINT, ERROR;
}
A validator method could look like this:
public Validation validateSomething() {
if (condition) {
return new Validation("msg.key", ValidationType.ERROR);
}
return new Validation(null, ValidationType.OK);
}
That's it.
The solution is simple: create a custom VerificationResult class. It can have a boolean status flag and a String message field, among other things you may want to add. Instead of returning either a String or a boolean, return a VerificationResult.
Also, depending on context, throwing an exception may actually end up being the right thing to do. This has to be considered on a case-by-case basis based on concrete scenarios, though.
Alternative solution: a last error query
Another option you can use is to have the verification return a boolean, and have a separate method e.g. String whatWentWrongLastTime() that a user can query in case false is returned. You'd have to be very careful with any concurrency issues etc. that may overwrite the "last" verification error.
This is the approach taken by e.g. java.util.Scanner, which does NOT throw any IOException (except for the constructors). To query if something "went wrong", you can query its ioException() method, which returns the last IOException, or null if there wasn't any.
IllegalArgumentException is the way to go if it really means that: You make some demands to the caller of the method (the contract) but they are ignored. In this case an IAE is appropriate.
If that doesn't reflect your use case, I'd use one of the solutions of the others.
Another approach - use a Status object:
public class Status {
public final static Status OK = new Status("OK");
private String message;
public Status(String message) { this.message = message; }
public String getMessage() { return message; }
}
To Verify, either return Status.OK if the input is valid or create a new Status message.
public Status validate(Integer input, int maxValue){
if (input > maxValue) {
return new Status(
String.format("%s value out of limits (maxValue=%s)", input, maxValue);
}
return Status.OK;
}
Using the verifier is simple as that:
Status status = validate(i, 512);
if (status != Status.OK) {
// handle the error
}
I think the best solution is to create your own exception that holds as much error description information as you want. It should not be a RuntimeException subclass; you want callers to have to deal with a failure to validate, because too many programmers fail to put in error handling. By making failure a checked exception, you force them (you?) to put at least something in, and code review can relatively easily pick up if they're being stupid about it. I know it's bureaucratic, but it improves code quality in the long run.
Once you've done that, consider whether you need to return a value on successful validation or not. Only return a value if that value contains information other than “oh, I've got here now” (which is obvious from the program flow). If you do need to return a result, and it needs to be a complex result, by all means use a custom class instance to hold it! To not do that is just refusing to use the facilities that the language gives you.
In this case, the method returning 'false' looks like a business logic result rather than a real Exception. So verifyLimits should return a result anyway rather than throwing an Exception when 'false'.
class VerifyLimitsResult{
//Ignore get, set methods
Integer maxValue;
Integer value;
public VerifyLimitsResult(Integer maxValue, Integer value) {
this.maxValue = maxValue;
this.value = value;
}
public boolean isOK(){
return value==null;
}
public String getValidationInfo(){
if(isOK()){
return "Fine";
}else{
return "The value " + value + " exceeds the maximum value/n"
}
}
}
....
VerifyLimitsResult verifyLimits4(Set<Integer> values, int maxValue) {
for (Integer value : values) {
if (value > maxValue) {
return new VerifyLimitsResult(maxValue, value);
}
}
return new VerifyLimitsResult(maxValue, null);
}
If you check a reasonable amount of items and be concerned about the number of objects you create to return the result, there's an alternative with interface.
First you create an interfaceto be called whenever the limit is violated:
// A simple listener to be implemented by the calling method.
public interface OutOfLimitListener {
// Called whenever a limit is violated.
public void outOfLimit(int value, int maxValue);
// ... Add additional results as parameters
// ... Add additional states as methods
}
You can add parameters and/or methods. For example the actual position of the violating value could be a parameter. As antother example add a method that is called at the end of each test with parameters for the number of checks and the number of violates.
An implementation of this interface is passed as argument to your checking method. It calls the listener every time one of the limits is violated:
private boolean verifyLimits(Set<Integer> values, int maxValue, OutOfLimitListener listener) {
boolean result = true; // Assume all values are OK
for (Integer value : values) {
if (value > maxValue) {
listener.outOfLimit(value, maxValue);
result = false; // At least one was out of limits
}
}
return result;
}
And finally you use this method just by implementening the interface:
#Test
public final void test() throws IOException, InterruptedException {
// Make up a test set of random numbers
Set<Integer> testSet = new HashSet<Integer>();
for(int i=0; i<10; i++) testSet.add((int) (Math.random() * 100));
// Implement the interface once with appropriate reaction to an out-of-limit condition
OutOfLimitListener listener = new OutOfLimitListener() {
#Override
public void outOfLimit(int value, int maxValue) {
System.out.printf("The value %d exceeds the maximum value %d\n", value, maxValue);
}
};
// Call verification
verifyLimits(testSet, 50, listener);
}
Android and other GUI Interfaces use this pattern heavily. For me, it got the prefered method when the result contains more then one value.
Create your own custom unchecked exception that extends from RuntimeException.
You can use simple Key-Value, by using HashMap, of course with predefined keys.
Return the HashMap for further processing.
I would vote for the second solution (either using IllegalArgumentException or defining a specific one).
Generally good practice is ensuring that any return value from a method can safely be ignored (because some day somebody will forget to check it anyway) and, in cases when ignoring a return value is unsafe, it's always better to throw/catch an exception.
You could return the flag as a boolean and log the results of tests that don't verify, you'll want to log them anyhow...
presuming you'll be checking millions of values.

Categories

Resources