Multiple classes for one testclass - java

I have a testclass with #Parameters that looks like this:
#Parameterized.Parameters
public static Collection<Object[]> data() {
log.info("Starting test class for laan documents");
controller = new Controller();
List<Laan> calculations = controller
.getXMLValues(Controller.Type.LAAN)
.stream()
.map(object -> (Laan)object)
.collect(Collectors.toList());
ArrayList<Path> xmlFiles = new ArrayList<>();
calculations.forEach(s -> xmlFiles.add(s.getXmlPath()));
log.info("Getting log for " + xmlFiles.size() + " laan files");
logvalues = controller.getLogvalues(xmlFiles);
Collection<Object[]> params = new ArrayList<>();
for(Laan laan : calculations) {
if(laan.getDocumentType().equalsIgnoreCase("laan")) {
for(Logfile logfile : logvalues) {
if(logfile.getName().equalsIgnoreCase(laan.getName())) {
params.add(new Object[]{laan.getName(), laan, logfile});
}
}
}
}
log.info("");
return params;
}
Most of the objects contains the same variables with different values, but there are some cases where there is nothing to compare with in the logfile (which is no problem and in most cases normal). Those cases are handled with a test in the beginning of the test method assumeTrue(someCondition);
Now the test class is getting very big and hard to maintain. At the moment there is about 30 test methods in the class and there will be added about 100 new test methods in the upcoming days. I've read that it's bad practise to create a new class and use pointers to other test classes.. So how should I go ahead to and organize my very long testclass?

You need to define your architecture of your test framework. Try to seperate methods by another directories and classes. For example:
If you need to test some functionality like: LoginPage, Dashboard, Email - it doesn't mean that you need to keep all methods in one test class. Create basic api like:
com.myproject.steps
LoginPageSteps.java
DashBoardSteps.java
com.myproject.suite
TestSuite.java
com.myproject.scenarious
LoginPageScenario.java
DashboardScenario.java
After, if you have methods for working only with Dashboard, move them into DashBoardSteps, and for login methods into LoginPageSteps. After, call them from LoginPageScenario or DashboardScenario, this approach will provide you more comfortable conditions for easy support on future.

Related

How do I write a Mockito test case?

Hi I was writing a test case for
#Override
public SnapDocument updateFlights(SnapDocument snapDocument, FlightListingResponse flightsResponse) {
HashMap<String, FaresInfo> outboundFlights = new HashMap<>();
HashMap<String, FaresInfo> inboundFlights = new HashMap<>();
Objects.requireNonNull(flightsResponse.getOutboundFlights()).getFlights().forEach(faresInfo -> outboundFlights.put(faresInfo.getJourneySellKey(), faresInfo));
Objects.requireNonNull(flightsResponse.getReturnFlights()).getFlights().forEach(faresInfo -> inboundFlights.put(faresInfo.getJourneySellKey(), faresInfo));
snapDocument.setOutboundFlights(outboundFlights);
snapDocument.setInboundFlights(inboundFlights);
return snapDocument;
}
This is the test case I have written
public void updateFilghtsSuccess(){
when(snapService.getSnapDocument(any())).thenReturn(snapDocument);
when(snapService.updateFlights(snapDocument, flightListingResponse)).thenReturn(snapDocument);
verify(snapService).updateFlights(snapDocument, flightListingResponse);
}
The build is failing, How to write the test cases for this so that I can improve the coverage of my code?
when, given and verify should only be used when dealing with mocks.
As your code works with plain old java objects and no other external components are called, you do not need them.
Just construct the pojos to pass to the method and assert that the pojo that comes back out contains the correct values. You don't need mockito for that, as the test does not require mocks.
#Test
void testUpdateFlights() {
// Arrange
SnapService snapService = new SnapServiceImpl();
SnapDocument sd = new SnapDocument();
FlightListingResponse response = new FlightListingResponse();
response.setOutboundFlights(...);
response.setReturnFlights(...);
// Act
SnapDocument result = snapService.updateFlights(sd, response);
// Assert
assertThat(result.getOutboundFlights()).contains(...);
}
You do not need them now, but when would you need a mock? If your code calls a component that is not under test and you don't want that the actual implementation of it is executed. Unit tests are to test 1 unit of work. All other external components should be mocked out.

Is it possible to reinitialize static mutable fields in a class?

I'm trying to automate the testing process for customly written programs designed to solve competitive programming challenges. Below is a dummy sample implementation of Solution:
public class Solution {
private static String dummyField = "initial";
public static int initialize(InputStream in) {
//competitive programmer custom code
System.out.println(dummyField);
dummyField = "changed";
return subCaseCount;
}
public void processSingleSubCase(InputStream in) {
//competitive programmer custom code
}
}
Prewritten test code for solution regardless of its implementation:
public void testSolution() throws FileNotFoundException {
for(File testResource : testResources) {
InputStream in = new FileInputStream(testResource);
int subCaseCount = Foo.initialize(in);
for (int subCase = 0; subCase < subCaseCount; subCase++) {
new Foo().processSingleSubCase(in);
}
//magic call to re-init all static fields without knowing their number/names in advance goes here
}
//console current output:
//initial
//changed
//changed
//...
//desired:
//initial
//initial
//initial
//....
}
The static fields can be mutable, so caching the initial values and mapping them to field names using reflection as a first setup, then reassigning them in between iterations won't do.
I did manage to come up with a working solution which basically reloads the class using a different class loader in between iterations, it did work but was slow: it took about 50 seconds just to reload classes 300 times (test resources are auto generated and I'd like to have the flexibility to auto generate as many as tolerable).
Is there a faster alternative?
My two thoughts for how to do this are:
Use instances rather than statics, since that way the new instance for each test is fresh.
If you need (or want) to stick with statics: Prior to the first test, cache the static values, then reassign them from the cache between tests. If the static values are object references referring to mutable objects, you'll need to make deep copies.

Reading information to a map

I'm learning about Sets and Maps in the Introduction to Java Programming book by Daniel Liang. My professor has assigned a problem in the back of the chapter that asks me to create a program that:
Queries the user for input on name
Queries the user for gender
Using these two criteria, and this/these website(s): http://cs.armstrong.edu/liang/data/babynamesranking2001.txt
... http://cs.armstrong.edu/liang/data/babynamesranking2010.txt
I have to be able to get the ranking.
I'm supposed to get this information into an array of 10 maps.
Each map corresponds with a .txt file/year. This is where I'm having problems with. How do I do this?
The (Int) rank of the student is the value of the map, and the key is the name (String) of the baby.
The way I was thinking was to create an array of maps or maybe a list of them. So like:
List<Map<Int, String>> or <Map<Int, String>[] myArray;
Yet even after that the issue of how I get all of this information from the .txt file to my maps is a hard one for me.
This is what I've come up so far. I can't say I'm happy with it. It doesn't even work when I try to start reading information is because I haven't specified the size of my array.
public class BabyNamesAndPopularity
{
public static void main (String[] args) throws IOException
{
Map<Integer, String>[] arrayOfMaps;
String myURL = "cs.armstrong.edu/liang/data/babynamesranking2001.txt";
java.net.URL url = new java.net.URL(myURL);
Scanner urlInput = new Scanner (url.openStream());
while(urlInput.hasNext())
{
...
}
}
}
Would it be viable to make a set OF MAPS? I was kind of thinking it would be better to make a set OF maps because of the fact that sets expand as needed (according to the load factor). I just need some general guidance. Unfortunately the CS program at my university (Francis Marion University in Florence, SC) is VERY small and we don't have any tutors for this stuff.
This answer rather vague, because of broad nature of question, and it may be more suitable for
programmers SE site. Still, you may find these two points worth something.
Instead of thinking in terms of 'raw' compound collections, such as lists of maps of sets or such, try to invent set of domain types, which would reflect your problem domain, and, as the next step, implement these types using suitable Java collections or arrays.
Unit-testing and incremental refinement. Instead of immediately starting with access to remote data (via java.net.URL), start with static source of data. Idea here is to have 'reliable' and easily accessible input data hand, which would allow you to write unit tests easily and w/o access to network or even to file system, using set of domain types from 1st point, above. As you write unit tests you can invent necessary domain types/methods names in unit tests at first, then implement these types/methods, then make unit tests pass.
For example, you may start by writing following unit test (I assume you know how to organize your Java project in your IDE, so unit test(s) can be run properly):
public class SingleFileProcessingTest {
private static String[] fileRawData;
#BeforeClass
public static void fillRawData() {
fileRawData = new String[2];
// values are from my head, resembling format from links you've posted
fileRawData[0] = "Jacob\t20000\tEmily\t19999";
fileRawData[1] = "Michael\t18000\tMadison\t17000";
}
#Test
public void test() {
Rankings rankings = new Rankings();
rankings.process(fileRawData);
assertEquals("Jacob", rankings.getTop().getName());
assertEquals("Madison", rankings.getScorerOfPosition(4).getName());
assertEquals(18000, rankings.getScoreOf("Michael"));
assertEquals(4, rankings.getSize());
}
}
Of course, this won't even compile -- you need to type in code of Rankings class, code of class returned by getTop() or getScorerOfPosition(int) and so on. After you made this compile, you'll need to make test pass. But you get main idea here -- domain types and incremental refinement. And easily verifiable code w/o dependencies on file system or network. Just plain old java objects (POJOs). Code for working with external data sources can be added later on, after you get your POJOs right and make tests, which cover most parts of your use cases, pass.
UPDATE Actually, I've mixed up levels of abstraction in code above: proper Rankings class should not process raw data, this is better to be done in separate class, say, RankingsDataParser. With that, unit test, renamed to RankingsProcessingTest, will be:
public class RankingsProcessingTest {
#Test
public void test() {
Rankings rankings = new Rankings();
rankings.addScorer(new Scorer("Jacob", 20000));
rankings.addScorer(new Scorer("Emily", 19999));
rankings.addScorer(new Scorer("Michael", 18000));
rankings.addScorer(new Scorer("Madison", 17000));
assertEquals("Jacob", rankings.getTop().getName());
// assertEquals("Madison", rankings.getScorerOfPosition(4).getName());
// implementation of getScorerOfPosition(int) left as exercise :)
assertEquals(18000, rankings.getScoreOf("Michael"));
assertEquals(4, rankings.getSize());
}
}
With following initial implementation of Rankings and Scorer, this is actually compiles and passes:
class Scorer {
private final String name;
private final int rank;
Scorer(String name, int rank) {
this.name = name;
this.rank = rank;
}
public String getName() {
return name;
}
public int getRank() {
return rank;
}
}
class Rankings {
private final HashMap<String, Scorer> scorerByName = new HashMap<>();
private Scorer topScorer;
public Scorer getTop() {
return topScorer;
}
public void addScorer(Scorer scorer) {
if (scorerByName.get(scorer.getName()) != null)
throw new IllegalArgumentException("This version does not support duplicate names of scorers!");
if (topScorer == null || scorer.getRank() > topScorer.getRank()) {
topScorer = scorer;
}
scorerByName.put(scorer.getName(), scorer);
}
public int getSize() {
return scorerByName.size();
}
public int getScoreOf(String scorerName) {
return scorerByName.get(scorerName).getRank();
}
}
And unit test for parsing of raw data will start with following (how to download raw data should be responsibility of yet another class, to be developed and tested separately):
public class SingleFileProcessingTest {
private static String[] fileRawData;
#BeforeClass
public static void fillRawData() {
fileRawData = new String[2];
// values are from my head
fileRawData[0] = "Jacob\t20000\tEmily\t19999";
fileRawData[1] = "Michael\t18000\tMadison\t17000";
}
#Test
public void test() {
// uncomment, make compile, make pass
/*
RankingsDataParser parser = new RankingsDataParser();
parser.parse(fileRawData);
Rankings rankings = parser.getParsedRankings();
assertNotNull(rankings);
*/
}
}

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

How do I write a unit test to verify that a function sorts its result? [duplicate]

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.

Categories