Runtime problems in TestNG asserts - java

I have a TestNG assertion which may occasionally fail due to the state of the object asserted (ArrayList element), and when it does, I would like to display this state.
I created an example which will fail in runtime, to illustrate the concept
import static org.testng.Assert.assertEquals;
#Test
public void sandbox() {
ArrayList<Integer> arr = new ArrayList<>();
assertEquals(arr.size(), 0, "The problem is: " + arr.get(0).toString());
}
I expected the assertion to pass and it will, when I remove the third argument (message). I see it's not a TestNG issue as execution is not stepping in the statement, but rather fails directly at this step with
at java.util.ArrayList.rangeCheck(ArrayList.java:657)
at java.util.ArrayList.get(ArrayList.java:433)
What's the best approach here? I am thinking of a method which will take care of the exception, but perhaps there are better known ways.
Thanks

Below should work:
import static org.testng.Assert.assertEquals;
#Test
public void sandbox() {
ArrayList<Integer> arr = new ArrayList<>();
assertEquals(arr.size(), 0, "The problem is: " + arr);
}
This is more practical as well, because if list is not empty it will print all values from the list instead of the first.

There is no other pretty way of doing it since all your arguments are passed at once to the callee, i.e. your method, so that the arr.get(0) must have been evaluated.
You may simply call for the next() element only if there is one using the Iterator over your collection:
#Test
public void sandbox() {
ArrayList<Integer> arr = new ArrayList<>();
Iterator<Integer> it = arr.iterator();
assertEquals(arr.size(), 0, "The problem is: " + (it.hasNext() ? iterator.next() : ""));
}

Related

SubList test cases

Im testing methods of SubList(Java.util.List) native implementation. Im using Java 8 api documentation. For toArray() method, I have only 3 tests. Can u help me to come up with more test cases? Thanks
#Test
public void toArrayBasicSub() {
fillList();
List<String> expectedList = Arrays.asList("1","2","3","4","5");
String[] expected = {"1","2","3","4","5"};
List<String> sub = list.subList(0, 5);
Object[] actual = sub.toArray();
assertEquals(expectedList,list);
assertArrayEquals(expected,actual);
}
#Test
public void toArrayEmpty() {
String[] expected = {};
List<String> sub = list.subList(0, 0);
Object[] actual = sub.toArray();
assertArrayEquals(expected,actual);
}
#Test
public void toArrayNull() {
fillList();
List<String> expected = null;
List<String> sub = list.subList(0, 5);
sub = null;
boolean thrownException = false;
try {
sub.toArray();
} catch (NullPointerException e) {
thrownException = true;
}
assertTrue(thrownException);
}
I assume you are targeting List.subList() for learning purposes only (as there are no other good reasons to test JDK methods!).
So, you are basically looking for feedback ... so lets help with that.
First thing: be clear about the scope you are testing. You say you want to test subList(). If so, then your tests should only be about sublist.
And then, the number of reasonable tests is really short:
Test the result for calling subList on an empty list
Test the result for calling subList on an non-empty list (simple case: with one element to show up in subList)
Test the result for calling subList on an non-empty list (complex case: with several elements to show up in subList)
You don't need much else. Specifically: when your job is to test the subList() call; then you don't need any test case for toArray.
subList() is called on a List, and returns a List. That is the only thing that matters here. What one does afterwards, to a list created by a call to subList() ... is not in the scope of testing subList()!

How do I run the same JUnit test multiple times with different test data each time?

I am just getting started with unit testing. I did the junit tutorial from a pdf from the tutorial points website. So my question is, I want to test my shunting yard algorithm and my RPNEvaluator.
The constructors (and any other variables to help you out with the context) look like this:
ShuntingYard.java:
private ArrayList<String> tokens = new ArrayList<String>();
public ShuntingYard(ArrayList<String> tokens) {
this.tokens = tokens;
}
RPNEvaluator.java:
private Queue<String> polishExpression;
public RPNEvaluator(Queue<String> exp) {
polishExpression = exp;
}
ShuntingYard.java has a method called toRpn() which will take an ArrayList and return a Queue after some processing.
RPNEvaluator has a method called evaluate which will take a Queue type and return a double after some processing.
With Junit I am trying to write some unit tests and I wanted to know if this start was the best way to go about it:
package testSuite;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import org.junit.Before;
import org.junit.Test;
public class ExpressionEvaluationTest {
/**
* Initialise the lists to be used
*/
#Before
public void beforeTest() {
ArrayList<String> exprOne = new ArrayList<String>();
exprOne.add("3");
exprOne.add("+");
exprOne.add("4");
exprOne.add("*");
exprOne.add("2");
exprOne.add("/");
exprOne.add("(");
exprOne.add("1");
exprOne.add("-");
exprOne.add("5");
exprOne.add(")");
exprOne.add("^");
exprOne.add("2");
exprOne.add("^");
exprOne.add("3");
ArrayList<String> exprTwo = new ArrayList<String>();
exprTwo.add("80");
exprTwo.add("+");
exprTwo.add("2");
ArrayList<String> exprThree = new ArrayList<String>();
exprThree.add("2");
exprThree.add("/");
exprThree.add("1");
exprThree.add("*");
exprThree.add("4");
ArrayList<String> exprFour = new ArrayList<String>();
exprFour.add("11");
exprFour.add("-");
exprFour.add("(");
exprFour.add("2");
exprFour.add("*");
exprFour.add("4");
exprFour.add(")");
ArrayList<String> exprFive = new ArrayList<String>();
exprFive.add("120");
exprFive.add("/");
exprFive.add("(");
exprFive.add("10");
exprFive.add("*");
exprFive.add("4");
exprFive.add(")");
ArrayList<String> exprSix = new ArrayList<String>();
exprSix.add("600");
exprSix.add("*");
exprSix.add("2");
exprSix.add("+");
exprSix.add("20");
exprSix.add("/");
exprSix.add("4");
exprSix.add("*");
exprSix.add("(");
exprSix.add("5");
exprSix.add("-");
exprSix.add("3");
exprSix.add(")");
}
#Test
public void test() {
}
}
I was going to put this in the before() method:
ShuntingYard sy = new ShuntingYard(/arraylist here/);
And then in the test, pass the lists to the algorithm. My question is that I think I am going the long way around it, would it be better to have a parameterised annotation and pass those lists as a list of parameters?
and a further question: if a test for any of the ArrayLists passes then I am sure I can execute a subsequent test to the RPNEvaluator evaluate method. I hope I haven't been ambiguous.
Help would be very much appreciated.
I would come at it a little differently. Instead of just creating several sets of test data and calling the same test each time break it up in to something meaningful. Instead of writing one test called test() write several separate tests for each aspect of ShuntingYard. For example:
#Test public void
itDoesntDivideByZero()
{
ArrayList<String> divideByZeroExpression = Arrays.asList("5", "0", "/");
// Add code to call your method with this data here
// Add code to verify your results here
}
#Test public void
itCanAdd()
{
ArrayList<String> simpleAdditionExpression = Arrays.asList("1", "2", "+");
// Add code to call your method with this data here
// Add code to verify your results here
}
and so on. This will make your JUnit output much easier to read. When there's a failure you know that it failed while trying to add, or it failed while trying to evaluate an expression that would cause a divide by zero, etc. Doing it the way you have it in the original you'd only know that it failed in the test() method.
Each of the tests here does 3 things:
Arranges the test data
Performs some action with that data
Asserts that the results of the action are as expected
This Arrange, Assert, Act idiom is very common in automated testing. You may also see it called Given, When, Then as in, "Given these conditions, when I call this method, then I should get this result".
Try to get out of the mindset of writing one test to test an entire class or method. Write a test to test one part of a method. Consider this class:
public class Adder {
public int addOneTo(int someNumber) {
return someNumber + 1;
}
}
You might end up with a test suite that looks like:
#Test public void
itAddsOne()
{
int numberToAddTo = 1;
int result = new Adder().addOneTo(numberToAddTo);
assertEquals("One plus one is two", 2, result);
}
#Test(expected="NullPointerException.class") public void
itChokesOnNulls()
{
new Adder().addOneTo((Integer)null);
}
#Test public void
itDoesntOverflow()
{
int result = new Adder().addOneTo(Integer.MAX_VALUE);
// do whatever here to make sure it worked correctly
}
And so on.
The advise from Mike B is very good, try to separate your test thinking in one test per behavior/functionality.
For make your test more readable i probably write a static constructor for the class ShuntingYard that receives a string, then you can write:
ShuntingYard addition = ShuntingYard.createFromExpresion("2+2");
assertThat(addition.getRpn().evaluate(), is(4));
you can refactor a little more and ends with something like that:
assertThat(evaluate("2+2"), is(4))
That is easy to understand an and easy to read, and in addition write more test with diferent scenarios its one-line of code.
Other option its to write parametrized test, one example: http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/, but in my opinion are really ugly. This test are normally called "data driven test" and are used when you want to test the same code with different input values.
For this data-driven test a much better option its to use something like spock, a groovy framework for testing that allows you to write incredible semantic test, and of course you can use for testing java code, check this out: http://docs.spockframework.org/en/latest/data_driven_testing.html

List Iterator - Not working

I've below code:
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class IteratorExample {
public static void main(String[] args) {
List<String> listnames = new ArrayList<String>();
listnames.add("Tom");
listnames.add("Finn");
listnames.add("Harry");
ListIterator<String> iteratorNames = listnames.listIterator();
while (iteratorNames.hasNext()) {
System.out.println(iteratorNames);
}
}
}
When I execute, I am getting strange output like below(which differs everytime when I run the program):
java.util.ArrayList$ListItr#a200d0c
java.util.ArrayList$ListItr#a200d0c
java.util.ArrayList$ListItr#a200d0c
java.util.ArrayList$ListItr#a200d0c
java.util.ArrayList$ListItr#a200d0c
Also the program is running infinitely.
Why it is not printing the list values?
You're looking at the iterator itself.
use
iteratorNames.next()
to get the next item.
Change the below line:
System.out.println(iteratorNames);
To:
System.out.println(iteratorNames.next());
I am getting strange output like below
It's just printing the memory adress of the object using the toString() default implementation of the object class.
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
Also the program is running infinitely.
As other answers stated, you have to use next()(i.e System.out.println(iteratorNames.next());) for two reasons :
It allows you to get the element in the list while iterating it
It advances the cursor position of the iterator
That's why your program runs indefinitely, because the cursor is still on the first position on your list, so hasNext() will always returns true.
Using next() the program looks like :
while (iteratorNames.hasNext()) {
String element = iteratorNames.next(); //now you can do what you want with this element
System.out.println(element);
}
Others have already mentioned how you use an Iterator--by querying it to see if it has a next value and then grabbing it via next() if it does.
However, you have the option of avoiding those low-level details altogether through a nice syntactic abstraction:
for (String name : listnames) {
System.out.println(name);
}
Give it a shot. In my opinion, it was one of the most helpful features of Java 5. Here is more information on it.
In your program System.out.println(iteratorNames); it will call toString() of Object class that will returns a string representation of the object (see implementation on toString())
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
That is why you are getting output like java.util.ArrayList$ListItr#a200d0c.
call next() It will returns the next element in the list. as follows:
System.out.println(iteratorNames.next());
use,
System.out.println((String)iteratorNames.next());

Should enhanced for loops include a function returning a list

I was just concerned about enhanced for loops calling a method directly.
Nested inside the code is my question in capital letters:
public class ExtendedForLoop {
public static List<Integer> returnList() {
System.out.println("Hurray ----> ");
List<Integer> abc = new ArrayList<Integer>();
abc.add(5);
abc.add(10);
abc.add(20);
return abc;
}
public static void main(String args[]) {
for (Integer i : returnList()) { // <----- OPTION 1. Include function call in extended loop.
System.out.println(i);
}
List<Integer> list = returnList()
for (Integer i : list) { // <----- OPTION 2. Provide list to function call.
System.out.println(i);
}
}
}
I prefer option 2, as some exception can be dealt with.
However if no exceptions are expected then option 1 can reduce unnecessary declaration of a new variable, hence reducing clutter.
But,
In general.
Which option is preferred ?
If it is option2 and the only reason for chosing option2 is handling exceptions, then should we use option1 if no exceptions are expected ?
I prefer using option 1 if I'm the owner of the code that returns the list and can guarantee that null will never be returned.
If I'm not the owner, I prefer to use a different construct though
for(Integer i : guaranteeCollection(resultList())
{
// dostuff
}
public static &ltT> Collection&ltT> guaranteeCollection(Collection&ltT> c)
{
return c != null ? c : Collections.EMPTY_LIST;
}
This avoids creating unnecessary variable declarations in your code and prevent NPEs.
I think second approach with null check is safer.
enhanced for loop will through NullPointerException if method returns null.
It depends on your system design:
Many project targets avoiding null objects.
If you are sure that returnList() will never return null (It should return an empty list instead (or Collections.emptyList), then go for solution 1, other wise for 2.
Well if you are dealing with NullpointerException in case then i prefer going with Option 1 as we are making an extra variable "list" on the stack which will occupy some memory also will reduce the performance by some bit.

values in queue Java

If I have a queue with strings as values How would I print all the values I was using:
System.out.println(queue.elements().toString().);
But it prints java objects...?
Do I have to use a loop to print values of queue?
Yes, you will need to use a loop however the loop can be simple like.
for(String s : queue) {
System.out.println(s.toString());
}
Actually, as long as it implements Iterable you should be able to do this type of foreach loop.
I don't understand your question. You say you want to print strings, and then after some code that doesn't compile, you say, "But it prints java objects...?" Strings are Java objects.
import java.util.*;
public class Foo {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<String>(); // create queue
for (String name : args) queue.add(name); // add strings to queue
System.out.println(queue); // print entire queue at once
for (String s : queue) System.out.println(s); // print each separately
}
}
Run with e.g., java Foo apple banana pear. The output is:
[apple, banana, pear]
apple
banana
pear
If the problem is that you are getting output like this:
[MyObject#498b5a73, MyObject#5bdf59bd, MyObject#247cb66a]
MyObject#498b5a73
MyObject#5bdf59bd
MyObject#247cb66a
Then your Queue does not actually hold Strings, and you have forgotten to override the toString() method in your class:
#Override public String toString() {
return firstName + " " + lastName + ", " + quest + ", " + favoriteColor;
}
There is no need to use a loop, unless you don't [like, this, output, format].
The answer depends on the type of queue.
If it is a Queue or Deque, then your code won't compile, because these interfaces don't define an elements() method. This applies to most of the classes that implement Collection.
If it is a Vector, then the elements() returns an Enumeration, and you have to use a loop to pull the values from it.
My advice would be:
Stop using Vector ... unless you have no choice. Vector is a legacy class. Use one of the implementations of Queue or Deque instead.
Whether or not you use Vector, use queue.toString() rather than queue.elements().toString() to render the queue contents as a String. The toString() method is defined as rendering the elements of the collection for all of the standard collection classes.
Try this:
Enumeration e = queue.elements();
while ( e.hasMoreElements() )
System.out.println( e.nextElement() );
Look at Joiner in guava.
System.out.println(Joiner.on("\n").join(queue.elememts()));
try this
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue myQueue = new LinkedList();
myQueue.add("A");
myQueue.add("B");
myQueue.add("C");
myQueue.add("D");
List<String> myList = new ArrayList<String>(myQueue);
for (Object theFruit : myList)
System.out.println(theFruit);
}
}
Java 1.8+ solution:
queue.forEach(System.out::println);

Categories