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()!
Related
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() : ""));
}
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
This question already has answers here:
How to test the ordering of elements in a Collection in JUnit test?
(4 answers)
Closed 6 years ago.
I have a data source from which I can request a list of people that live in a (any) country, and a method which retrieves the people from that data source and sorts them by their name alphabetically. How should I write my unit test to make sure that the sorting part of my method works properly?
This is what my SUT looks like:
class PeopleStuff {
public IData data;
public List<Person> getSortedPeopleForCountry(String countryName) {
List<Person> people = data.getPeopleForCountry(countryName);
Comparator nameComparator = new PersonNameComparator();
Collections.sort(people, nameComparator);
return people;
}
}
And this is what my unit test looks like:
#Test public void testGetPeopleSortsByPeopleName() {
String COUNTRY = "Whatistan";
// set up test (the 3 lines below are actually in a #Before setup method)
PeopleStuff peopleStuff = new PeopleStuff();
IData mockData = createNiceMock(IData.class);
peopleStuff.data = mockData;
// set up data
List<PersonName> mockPeopleList = new ArrayList<PersonName>();
mockPeopleList.add(new Person(COUNTRY, "A"));
mockPeopleList.add(new Person(COUNTRY, "D"));
mockPeopleList.add(new Person(COUNTRY, "B"));
mockPeopleList.add(new Person(COUNTRY, "C"));
when(mockData.getPeopleForCountry(COUNTRY)).thenReturn(mockPeopleList);
// exercise
List<String> result = peopleStuff.getSortedPeopleForCountry(COUNTRY);
// assert
assertEquals("A", result.get(0).name);
assertEquals("B", result.get(1).name);
assertEquals("C", result.get(2).name);
assertEquals("D", result.get(3).name);
}
What I need to know is if the way I am stubbing the data, running the test and making the assertions is correct, or if there are better ways of doing this.
My application has a lot of methods to test and a lot of custom sorting algorithms; I implemented all tests to use some 4 values that I stub like that, in a "random" order which I choose when I write the test.
Should I just test if the comparators are called? That doesn't seem right to me, because I don't know if they're called for the right data or at the right time in the algorithm that's inside getSortedPeopleForCountry(). I want to detect situations like this:
public List<Person> getSortedPeopleForCountry(String countryName) {
List<Person> people = data.getPeopleForCountry(countryName);
Comparator nameComparator = new PersonNameComparator();
List<Person> sortedPeople = new ArrayList<Person>(people)
Collections.sort(sortedPeople, nameComparator);
return people; // oops!
}
Should I leave it like this and add mock comparators which use the real comparators but also verify that they're being called?
Am I doing it right?
I think your current test is very good - the tests are realistic, exercising all of the code, and you are mocking out the data source & using dependency injection to supply a mock data source. There is a lot of best practice going on in this test.
On the issue of whether you should look to mock the comparators (and therefore make the test on testGetPeopleSortsByPeopleName a pure unit test), you will definitely get two different opinions here:
A purist would argue that your test is technically an integration test, and that to have proper unit tests you need to adjust your test to use a mock comparator, and then test the comparator separately.
A pragmatist would argue that your test is already high quality, and that it doesn't matter that it isn't a unit test in the strictest sense. Furthermore, to split this into two separate unit tests may make the test less readable - which I imagine would be the case with the test above if you were to involve mock comparators.
My personal opinion is that you should leave it as it is, the fact that you have a high quality, readable test that exercises all the code and effectively asserts your requirements is far more important than worrying about having strictly pure unit tests.
The only way in which the test looks in need of improvement is the length of the test method - I think a little method extraction could help improve readability and make the test method more expressive. I would aim for something like this:
#Test public void testGetPeopleSortsByPeopleName() {
peopleStuff.data = buildMockDataSource(COUNTRY, "A", "D", "B", "C")
List<String> result = peopleStuff.getSortedPeopleForCountry(COUNTRY);
assertPersonList(result, "A", "B", "C", "D")
}
private IData buildMockDataSource(String country, String ... names) {
...
}
private void assertPersonList(List<Person> people, String ... names) {
...
}
ObjectA[] arr = objectAList.toArray(new ObjectA[objectAList.size()]);
for (int i = 0; i < objectAList.size() - 1; i++) {
int j = i + 1;
assertTrue(arr[i].getDate().compareTo(arr[j].getDate()) >= 0);
}
This code represents an example where ArrayList contaning ObjectA objects is sorted by field date in descending order. We are checking if the member of the list has smaller or equal date from his predecessor.
Separate the sorting logic from returning the list. So I'd have getPeopleForCountry(String countryName) only return a list whereas a sorted list would be returned from getSortedPeopleForCountry(List ). That way you can test how it works before and after sorting. Also, you might want to override the Equals() method to compare names if that is what you want to go with, but then you'd later want to compare with some other property. That's your call.
Currently, I'm getting stuck with what it seems to be an unexpected error.
I'm programming with the java language, using eclipse as IDE.
The List in question is declared as follows :
private final List<Integer> resList;
Using the "Watchpoint" feature of eclipse while debugging the program, I've seen the following process :
After returning the resList List two times, and before returning it for the third time, the List became suddenly empty.
If anyone have a suggestion to give me in order to fix that problem, I would be very pleased ?
Concerning the code, I posted all the methods that access the resList list and are invoked in the program :
Here is the first One :
public CloudInformationService(String name) throws Exception {
super(name);
resList = new LinkedList<Integer>();
arList = new LinkedList<Integer>();
gisList = new LinkedList<Integer>();
}
And the second one :
public void processEvent(SimEvent ev) {
int id = -1; // requester id
switch (ev.getTag()) {
...
// A resource is requesting to register.
case CloudSimTags.REGISTER_RESOURCE:
resList.add((Integer) ev.getData());
break;
...
}
}
And finally, The third one :
private static CloudInformationService cis;
public static List<Integer> getCloudResourceList() {
if (cis == null) {
return null;
}
return cis.getList();// The implementation of this method is listed below
}
public List<Integer> getList() {
return resList;
}
Thank you in advance.
Step 1: use ctrl+alt+H to look up references to resList and look for methods calling remove, clear, removeAll. If there are too many methods using resList move on to Step 2.
Step 2: Set breakpoints in the CloudInformationServices constructor, when hit, set up breakpoints in LinkedList/AbstractList (in the JDK) in all remove, clear, removeAll methods. In the breakpoints view, right click on resList and choose instance breakpoints. Pick all your remove, clear, removeAll breakpoints and continue execution. Now you'll get a breakpoint hit and can observe from where the list is being emptied.
Without any more code there isn't much help you can get I'm afraid.
I am not entirely sure what title to put on this problem to get the right minds. This seems like a Java slight of hand but it's only occuring using the Guava Collections2.transform. The transformer is providing a completely different instance of my object during iteration on 'results' then what is contained when 'results' is finally return. And thus, the 'setDateStamp()' doesn't actually appear to work because it's being set on instances that seem to just appear and vanish like a ghost.
When I implement what the logical equivalent of the Collections2.transform() method is doing (commented out code) I get the results I expect. I have stepped through the google code, breakpoints and all, and no where is a new instance being created through any method other than my underlying Function.
I get what their implementation is doing: transform-as-needed. Not complicated. So why the hell doesn't this work?
Here is the code in question along with some debug
#Component
public class SurveyResultToQuestionResults implements Function<SurveyResult, Collection<QuestionResult>> {
#Autowired
private QuestionResultDtoToDomain dtoToDomain;
#Override
public Collection<QuestionResult> apply(#Nullable SurveyResult input) {
Collection<QuestionResult> results = new HashSet<QuestionResult>();
if (input != null) {
// substitute this
// for (QuestionResultDto dto : input.getResults()) {
// QuestionResult result = dtoToDomain.apply(dto);
// results.add(result);
// }
// for this
results = Collections2.transform(input.getResults(), dtoToDomain);
for (QuestionResult result : results) {
long time = input.getSurveyTime().getTime();
Timestamp dateStamp = new Timestamp(time);
result.setDateStamp(dateStamp);
}
}
return results;
}
}
next class
#Component
public class QuestionResultDtoToDomain implements Function<QuestionResultDto, QuestionResult> {
#Override
public QuestionResult apply(#Nullable QuestionResultDto input) {
QuestionResult result = null;
if (input != null)
result = new QuestionResult(input.getAnswerOriginId(),input.getAnswer(),input.getQuestionId());
return result;
}
}
And a test
#RunWith(MockitoJUnitRunner.class)
public class SurveyTransformerTest {
#Spy
private QuestionResultDtoToDomain dtoToDomain = new QuestionResultDtoToDomain();
#InjectMocks
private SurveyResultToQuestionResults surveyResultToQuestionResults = new SurveyResultToQuestionResults();
#Test
public void testSurveyToQuestionResults() throws Exception {
Set<QuestionResultDto> answers = new HashSet<QuestionResultDto>();
answers.add(new QuestionResultDto(17L,"question 2 answer"));
answers.add(new QuestionResultDto(18L,"question 3 answer"));
answers.add(new QuestionResultDto(19L,"question 4 answer"));
SurveyResult result = new SurveyResult(10L,16L,new Date(),answers);
Collection<QuestionResult> qresults = surveyResultToQuestionResults.apply (result);
System.out.println(qresults);
for (QuestionResult qresult : qresults) {
assertNotNull(qresult.getDateStamp());
}
}
}
Debug:
Bad implementation
[QuestionResult{questionResultId=null, answer='question 4 answer', dateStamp=null}, QuestionResult{questionResultId=null, answer='question 2 answer', dateStamp=null}, QuestionResult{questionResultId=null, answer='question 3 answer', dateStamp=null}]
Good implementation:
[QuestionResult{questionResultId=null, answer='question 4 answer', dateStamp=2012-05-17 00:02:18.615}, QuestionResult{questionResultId=null, answer='question 3 answer', dateStamp=2012-05-17 00:02:18.615}, QuestionResult{questionResultId=null, answer='question 2 answer', dateStamp=2012-05-17 00:02:18.615}]
You're surprised that the writes on the new objects aren't writing through to the backing collection?
Collections.transform doesn't just do the transform "as needed" -- it doesn't store anything at all. That's what "view" means in its documentation. Any time you walk through a Collections2.transformed collection, it applies the function again, freshly. Once that for loop in the apply method is done with result, that object is gone; never seen again.
If you want to do what you're doing, make an explicit copy of the transformed collection in e.g. an ArrayList.
The answer is in the javadoc but the quick answer is that the transform is lazy. What is returned is a view of the old collection and the function is called each time you access an element; which is useful if you you'll only be accessing a few of them. If you know you're going to iterate several times it's best to copy the view into a brand new Collection.