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)
Related
I want to annotated 2 different methods and related them together in order to match the global variable and method which uses it
#FirstAnn(funcName = "foo")
def foo = {
val value = boo()
val checkValue = value > 2
return checkValue
}
#SecondAnn(funcName = "foo", paramName = "value")
def boo : Double = {
return B.getValue
}
#Pointcut("execution(* *(..)) && #annotation(firstAnn) && if()")
public static boolean execute(FirstAnn firstAnn){
return true;
}
#Pointcut("execution(* *(..)) && #annotation(secAnn) && if()")
public static boolean execute2(SecondAnn secAnn){
return true;
}
#Before("execute(firstAnn) && execute2(secAnn)")
public void before(FirstAnn firstAnn, SecondAnn secAnn, JoinPoint.StaticPart jps,JoinPoint jp){
if (firstAnn.funcName == secAnn.funcName){
print("value X is used in funcname Y" ) //here I will retrieve the value from signature like: value 3 is used in function foo
}
}
But the code doesn't get to this place...Any suggestion to make it work please?
thanks
Your usage of && implies you expect both methods to be executed at the same time. But of course they are not. Either the first or the second one is matched, they are two different joinpoints, thus combining the pointcuts with && will never make your advice method fire. You need to use || instead to match either one.
Looking at your source code, what you probably want is to trigger the advice when boo is called from within foo and possibly also the other way around. You are also trying to bleed context from the calling method into the called method. This is called a wormhole pattern, see also my answers here:
https://stackoverflow.com/a/12130175/1082681
https://stackoverflow.com/a/50577287/1082681
https://stackoverflow.com/a/25075051/1082681
So probably you want to use a pointcut like
execute2(secAnn) && cflow(execute(firstAnn))
for your example or the other way around if you have cases where the second method calls the first one:
cflow(execute2(secAnn)) && execute(firstAnn)
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 ?
Assignment: Write a JUnit test assuming you have an array of int values and you only want the JUnit test to fail if any of the values are less than 20.
I know it only asks for the JUnit assuming the other methods are already created. But I want to create them anyway. However I do not know how to go about it. This is my code so far:
package ArrayJU;
public class ArrayJUTest {
public static void main(String[] args){
ArrayJUTest array = new ArrayJUTest();
int arr[] = {23,25,50,68,3};
System.out.println(array.arrayLessThan(arr));
}
public boolean arrayLessThan(int array[]){
for (int element : array) {
if(element>20){
return true;
}
else{
return false;
}
}
}
}
For the arrayLessThan Eclipse is telling me that I need to return a boolean, however I wouldn't know how to iterate through the array without a for loop. And if I return a true or a false outside the for loop it will defeat the purpose of what I'm trying to do with the if/else statements. How do I go about this? Your help will be greatly appreciated.
JUnit Test:
package ArrayJU;
import static org.junit.Assert.*;
import org.junit.Test;
public class JUnitArrayTest {
#Test
public void JUnitArTest(){
int[] arr = {32,52,89,12};
ArrayJUTest arra = new ArrayJUTest();
boolean poop = arra.arrayLessThan(arr);
assertEquals(false, poop);
}
}
Eclipse (really the java compiler) is complaining because after your for loop, your method doesn't return a boolean. The compiler doesn't figure out that the method never gets that far because it will always return during its very first iteration. Which is a problem anyway, since your method will never look beyond the first array element.
The typical way to code a loop like this is something along these lines:
public boolean arrayLessThan(int[] array) {
for (int element: array) {
if (element < 20) {
return false;
}
}
return true;
}
But beyond this, you're missing the point of JUnit. It's a framework, and you need to write your tests as methods of test classes that are written in a very specific manner required by that framework. You don't write your own main function - the framework provides one that looks through your code to find all your test classes and the tests implemented in each class, and then runs those tests for you.
You should google for documents / tutorials / examples of JUnit and then try again.
This question seems to be more about "why does this not compile and what the method return for an empty set" than "how do I write a JUnit test". I would recommend reading up on some JUnit tutorials (like this tutorial from mkyong) to get an understanding of them. I'll try to answer what I think is the first question.
The first thing is to note about the correctness of your loop based on your description. The loop will currently always return a value based on the first value of the array:
public boolean arrayLessThan(int array[]){
for (int element : array) {
if(element>20){
return true;
}
else{
return false;
}
}
}
Based on your description, it should only return false if any item matches your predicate (an item is less than 20). You are also getting a compiler error because it does not return anything for an empty array (0 elements). This would be one way to change it:
public boolean arrayLessThan(int array[]){
for (int element : array) {
if(element < 20){
return false;
}
}
return true;
}
And if I return a true or a false outside the for loop it will defeat
the purpose of what I'm trying to do with the if/else statements
Well, not really. It depends on how you want to model the 0-element array case. The best way to model it would be to return true because you cannot point to an element that does not satisfy your condition. This is known as vacuous truth.
You can read a good explanation for Java 8 streams with anyMatch and allMatch and vacuous truth in this question/answer.
I'm confused, there are two issues...
The first is that this isn't a junit test.
They look like this:
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
class HypotheticalClassTest {
private HypotheticalClass hypClass;
#Before
public void setup() {
hypClass = new HypotheticalClass();
}
#Test
public void ensureNoNumsLessThanTwenty() {
int[] result = hypClass.hypotheticalMethod();
// Some assertions. Check out the org.junit.Assert class.
}
}
Second, is you method arrayLessThan
Let's go through it step by step:
public boolean arrayLessThan(int array[]){
for (int element : array) { // For each int in array...
if(element>20){ // If element is greater than 20
return true; // Return true (returning stops the loop,
// do you want to stop on the
// first element greater than
// 20?)
} //
else{ // otherwise
return false; // Return false
}
} // Assuming there are no elements in the
// array (length 0) then this is where it
// comes. There's no return here, there
// needs to be, then it will stop
// complaining.
}
Looking at it now we see it doesn't compile because there is no return statement for the case of an empty array. Also we see it only checks the first element! Look up what continue does, it will fix the issue of only checking the first element, or write your condition differently.
This question already has answers here:
Best way to format multiple 'or' conditions in an if statement
(8 answers)
Closed 1 year ago.
Basically, what I want to do is check two integers against a given value, therefore, classically what you would do is something like this:
//just to get some values to check
int a, b;
a = (int)(Math.random()*5);
b = (int)(Math.random()*5);
//the actual thing in question
if(a == 0 || b == 0)
{
//Then do something
}
But is there a more concise format to do this? Possibly similar to this (which returns a bad operand type):
//just to get some values to check
int a, b;
a = (int)(Math.random()*5);
b = (int)(Math.random()*5);
//the actual thing in question
if((a||b) == 0)
{
//Then do something
}
You can do the following in plain java
Arrays.asList(a, b, c, d).contains(x);
Unfortunately there is no such construct in Java.
It this kind of comparison is frequent in your code, you can implement a small function that will perform the check for you:
public boolean oneOfEquals(int a, int b, int expected) {
return (a == expected) || (b == expected);
}
Then you could use it like this:
if(oneOfEquals(a, b, 0)) {
// ...
}
If you don't want to restrict yourselft to integers, you can make the above function generic:
public <T> boolean oneOfEquals(T a, T b, T expected) {
return a.equals(expected) || b.equals(expected);
}
Note that in this case Java runtime will perform automatic boxing and unboxing for primitive types (like int), which is a performance loss.
As referenced from this answer:
In Java 8+, you might use a Stream and anyMatch. Something like
if (Stream.of(b, c, d).anyMatch(x -> x.equals(a))) {
// ... do something ...
}
Note that this has the chance of running slower than the other if checks, due to the overhead of wrapping these elements into a stream to begin with.
I think that a bit-wise OR:
if ((a | b) == 0) . . .
would work if you want to check specifically for 0. I'm not sure if this saves any execution time. More to the point, it makes for cryptic code, which will make the future maintainer of this code curse you (even if its yourself). I recommend sticking with the more-typing option.
Bah. I misread OP's original logic.
Another go...
If you want to test whether any one of many variables is equal to an expected value, a generic function might work:
public <T> boolean exists(T target, T... values) {
for (T value : values) {
if (target == null) {
if (value == null) {
return true;
}
} else if (target.equals(value)) {
return true;
}
}
return false;
}
This will work for any number of objects of one type. Primitives will be autoboxed so it will work with them as well. Your original code will be something like:
if (test(0, a, b)) {
// do something
}
(A better method name would be desperately needed to even consider whether this an improvement over what you have now. Even if the test expands to 3 or 4 variables, I question the need for this kind of thing.) Note that this also works with arrays:
int[] values = { . . . };
if (test(0, values)) { . . .
and it can be used to test whether an array (or any of a collection of variables) is null.
if(a == 0 || b == 0)
{
//Then do something
}
Why not keep it readable? What is not concise about this? On the other hand,
a = (int)(Math.random()*5);
involves an unnecessary cast. Why not just use Random and invoke nextInt()?
For this example, you can do
if (a * b == 0)
or for more variables
if (a * b * c * d == 0)
while more concise it may not be as clear. For larger values, you need to cast to a long to avoid an overflow.
You could put the integers in a set and see if it contains the given value. Using Guava:
if(newHashSet(a, b).contains(0)){
// do something
}
But two simple int comparisons are probably easier to understand in this case.
Here's a modification of #buc's answer that can take any number of any arguments:
public <T> boolean oneOfEquals(T expected, T... os) {
for (T o : os) {
if (expected.equals(o)) return true;
}
return false;
}
Even if you have used the bit-wise operation as Ted suggested, the expressions are not equal, since one requires at least one of the variables to be zero and the second requires both of them to be zero.
Regarding your question, there is no such shortcut in Java.
You can try this code:
public static boolean match (Object ref, Object... objects)
{
if (ref == null)
return false;
//
for (Object obj : objects)
if (obj.equals (ref))
return true;
//
return false;
} // match
So if you can check this way:
if (match (reference, "123", "124", "125"))
; // do something
In Java 8 we can achieve the same by using the below method:
private boolean methodName(int variant,int... args){
if(args.length > 0){ return Arrays.stream(args).anyMatch( x -> x == variant); }
return false;
}
The given method will return true if the variant will match any possible input(s). This is used for or condition.
In the same way, if you want to do &&(and) condition then you just need to used other Java 8 methods:
Note: These methods take Predicate as an argument.
anyMatch: return true the moment the first predicate returns true otherwise false.
allMatch: return true if all the predicates return true otherwise false.
noneMatch: return true if none of the predicates return true otherwise false.
Performance Note: This is good when you have enough amount of data to
check as it has some overhead but it works really well when you use
this for enough amount of data. normal way is good for just two
conditions.
There is no special syntax for that. You could make a function for that. Assuming at least Java 1.5:
public <T> boolean eitherOneEquals(T o1, T o2, T expectedValue) {
return o1.equals(expectedValue) || o2.equals(expectedValue);
}
if(eitherOneEquals(o1, o2, expectedValue)) {
// do something...
}
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.