I got a method that read from a txt file and populate a list with words that are exists in the file.
the method is calculate and return Most Repeated Word.
If I want to write a jUnit for that. how should I test the corectess of that method given the fact the file is changing frequentaly.
As #jaibalaji wrote, JuintTests should not depend on resources outside of the JVMs memory.
So the first step must be to make your code under test (cut) independent of the actual file.
I got a method that read from a txt file and populate a list with words that are exists in the file. the method is calculate and return Most Repeated Word.
In this sentences you mention 3 responsibilities:
reading a file
populating a list
find Most Repeated Word
You should split this method so that you ed up with smaller classes with the one responsibility each only.
class TextAnalyser{
private final WordListBulder wordListBulder; // converts String into List of words
private final WordCountAnalyser wordCountAnalyser;
public TextAnalyser(WordListBulder wordListBulder, WordCountAnalyser wordCountAnalyser){
this.wordListBulder = wordListBulder;
this.wordCountAnalyser = wordCountAnalyser;
}
public String findMostRepeatedWordIn(MyFileReader myFileReader){
String fileContent = myFileReader.readContent();
List<String> wordList = wordListBulder.crerateWordListFrom(fileContent);
return wordCountAnalyser.findMostRepeatedWordIn(wordList);
}
This code is too simple to fail and don't need to be UnitTested. Module- and/or Acceptance-Tests will show that this works.
Now the behavior to test is in the class WordCountAnalyser. And it has a simple t "fake" input which leads to a deterministic testable output.
The file should be a parameter of the method or an instance field of the class of this method.
In this way, you can unit test the method by providing a file which you master the data and you know how assert them.
For example with the parameter way :
public String findMostRepeatedWork(File file){
...
}
And so you could unit it easily :
#Test
public void findMostRepeatedWork(){
// fixture
File myTestFile = ...;
// action
new MyClassToTest.findMostRepeatedWork(myTestFile);
// assertion
...
}
Junit is not intended for any test that is taking resources(file, dB or network)
Related
I have text file
Now I am trying to read this into a two dimension array .
anyone with an example code or question which was answered ?
Consider this file divided in middle present two record in same format, you need to design class that contains fields that you want to get from this file. After that you need to read
List<String> fileLines = Files.readAllLines(Path pathToYourFile, Charset cs);
and parse this file with help of regular expressions. To simplify this task you may read lines and after that specify regexp per line.
class UnstructuredFile {
private List<String> rawLines;
public UnstructuredFile (List<String> rawLines) {
this.rawLines = rawLines;
}
public List<FileRecord> readAllRecords() {
//determine where start and stop one record in list list.sublist(0,5) or split it to List<List<String>>
}
private FileRecord readOneRecord(List<String> record) {
//read one record from list
}
}
in this class we first detect start and end of every record and after that pass it to method that parse one FileRecord from List
Maybe you need to decouple you task even more, consider you have one record
------
data 1
data 2
data 3
------
we make to do classes RecordRowOne, RecordRowTwo etc. every class have regex that know how
to parse particular line of row of the record string and returns partucular results like
RecordRowOne {
//fields
public RecordRowOne(String regex, String dataToParse) {
//code
}
int getDataOne() {
//parse
}
}
another row class in example has methods like
getDataTwo();
after you create all this row classes pass them to FileRecord class
that get data from all Row classes and it will be present one record of you file;
class FileRecord {
//fields
public FileRecord(RecordRowOne one, RecordRowTwo two) {
//get all data from rows and set it to fields
}
//all getters for fields
}
it is basic idea for you
I have a Rest Service that I want to respond to requests with the following paths
1) /v1/config/type/service
2) /v1/config/type/service, service2
What I'd like is to be able to store the path param serviceName as a List where each element is delimited by a comma. For example, if someone types v1/config/foo/bar1,bar2,bar3 I'd like serviceName to be a List with 3 elements (bar1, bar2, bar3). Right now it just returns a list with 1 element that contains all three service strings. Is that even possible? Or is that something I'll simply have to parse. The code I have is shown below, it's pretty rough as I'm in the beginning stages of the project:
#ApplicationPath("/")
#Path("/v1/config")
public class ServiceRetriever extends Application {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getHelloWorld() {
return "Hello World";
}
#GET
#Path("{type}/{serviceName}")
#Produces("application/zip")
public Response getServices(#PathParam("type") String type, #PathParam("serviceName")List<String> serviceNames,
#QueryParam("with_config") boolean withConfig, #QueryParam("with_drive") boolean withDriver) throws IOException
{
//some random file i made to test that we can return a zip
File file = new File(System.getProperty("user.home")+"/dummy.zip");
System.out.println(serviceNames.size()); //returns 1
//we can change the zip file name to be whatever
return Response.ok(file).header("Content-Type","application/zip").
header("Content-Disposition", "attachment; filename="+file.getName()).build();
}
The problems is that you have to alter the deserialization process of that variable. Typically only query parameters are lists so this might not be compatible with some libraries.
You could:
Capture the parameter as a string and parse it internally via helper method (obvious)
Create your own annotation like #PathParamMutli and return Arrays.asList(parameter.split(","));. Ideally you should have access to the framework source code and branching privileges.
Use a query parameter instead
Situation: I'm working on legacy code and trying to improve readability. The following example should visualize the intent:
private static final String CONSTANT_1 = "anyValue";
private static final String CONSTANT_2 = "anyValue";
private static final String CONSTANT_3 = "anyValue";
private static final String CONSTANT_4 = "anyValue";
private static final String CONSTANT_5 = "anyValue";
private final SomeType someField = new SomeType();
private void contentOfSomeMethods(){
someMethod(someField, CONSTANT_1, true);
someMethod(someField, CONSTANT_2, true);
someMethod(someField, CONSTANT_3, true);
someMethod(someField, CONSTANT_4, false);
someMethod(someField, CONSTANT_5, false);
}
private void someMethod(SomeType type, String value, boolean someFlag) { }
Imagine, there are about 50 calls of someMethod using about 50 constants. I want to do safe automatical refactorings on that code so that the contentOfSomeMethods method changes to
private void contentOfSomeMethods(){
doItWith(CONSTANT_1);
doItWith(CONSTANT_2);
doItWith(CONSTANT_3);
doItNotWith(CONSTANT_4);
doItNotWith(CONSTANT_5);
}
and two additional methods are generated:
private void doItWith(String value) {
someMethod(someField, value, true);
}
private void doItNotWith(String value) {
someMethod(someField, value, false);
}
The naive way is to extract all constants in contentOfSomeMethods inside local variables and use then the extract method refactoring to create the desired methods. And afterwards to inline back the local variables. But this solution doesn't scale up.
Another way is to use search and replace with regular expressions, but this is not a safe refactoring, so I could break the code without noticing it.
Do you have any better suggestions? Do you know some plugins for Eclipse that allow that?
I don't know of any utility that would do this directly.
I think using a regular expression is the only to go. First, you will need to create the two target methods doItWith and doItNotWith. Then, you can highlight the contents of the method contentOfSomeMethods, hit Ctrl+F, and use the following regular expressions:
Find: someMethod\(someField, (\w*), true\);
Replace with: doItWith(\1);
and then
Find: someMethod\(someField, (\w*), false\);
Replace with: doItNotWith(\1);
Be sure to check "Regular Expressions" and "Selected lines". Here's a picture of it:
The regular expressions match the constant that is used inside the function call with (\w*) and then it is used during the replacement with \1. Using this regular expression only on the selected lines minimizes the chance of breaking unrelated code.
Do it with a regular expression and verify it.
I'm assuming that each call to someMethod spans only one line. If not this method is still useful but slower.
Copy the original file.
Use ctrl+alt+h to show the Callers of someMethod and get a count of them.
Do regex search and replaces restricted to the proper area :
Find : someMethod(someField,([ ]*CONSTANT_[0-9]+)[ ]*,[ ]*true[ ]*)[ ]*;
Replace : doItWith("$1");
Find : someMethod(someField,([ ]*CONSTANT_[0-9]+)[ ]*,[ ]*false[ ]*)[ ]*;
Replace : doItNotWith("$1");
Make a diff of the original file and the new file showing only the lines of the original file which have changed.
diff --changed-group-format='%<' --unchanged-group-format='' original.java refactored.java | wc
You should get the same number of lines as you got in the callers of someMethod.
If the calls to someMethod are multiline, or if you want greater verification, just drop | wc to see the lines which were modified in the original file to ensure that only the correct lines have been modified.
Alas I know nothing in Eclipse that allows to do this today.
This is something I would like to achieve one day in AutoRefactor: https://github.com/JnRouvignac/AutoRefactor/issues/8
However the road to get there is quite long.
The only ways I know today are to extract local variables then extract method (as you suggested) or use regexes (as somebody else suggested).
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
I have two files:
Grader.getFileInfo("data\\studentSubmissionA.txt");
Grader.teacherFiles("data\\TeacherListA.txt");
Both contain a list of math problems, but the TeacherList is unsolved in order to check that the StudentSubmission was not altered from the original version.
studentSubmission is sent to the Grader class and the method currently looks like this:
public static void getFileInfo(String fileName)
throws FileNotFoundException {
Scanner in = new Scanner(new File(fileName))
while (in.hasNext()) {
String fileContent = in.nextLine();
}
and the TeacherFiles method looks like
public static void teacherFiles(String teacherFiles)
throws FileNotFoundException{
Scanner in = new Scanner(new File(teacherFiles));
while (in.hasNext()){
String teacherContent = in.nextLine();
String line = teacherContent.substring(0, teacherContent.indexOf('='));
}
I don't know how to get these methods to another method in order to compare them since they're coming from a file and I have to put something in the method signature to pass them and it doesn't work.
I tried putting them in one method, but that was a bust as well.
I don't know where to go from here.
And unfortunately, I can't use try/catches or arrays.
Is it possible to send the .substring(0 , .indexof('=')) through the methods?
Like line = teacherFiles(teacherContent.substring(0 , .indexof('='))); Is it possible to do this?
Think in more general terms. Observe that your methods called getFileInfo and teacherFiles, respectively are the very same except a few nuances. So why do not we think about finding the optimal way of merging the two functionalities and handling the nuances outside of them?
It is logical that you cannot use arrays as you need to know the number of elements of your array before you initialize it and your array would have already been initialized when you read the file. So using an array for this task is either an overkill (for example you allocate 1000 elements in your memory and you use only 10 elements) or insufficient (if you create an array of 10 elements, but you would need 1000). So, due to the fact that you do not know the number of rows in advance you need to use another data structure for your task.
So create the following method:
public static AbstractList<String> readFile(String filePath) throws FileNotFoundException, IOException {
Scanner s = new Scanner(new File(filePath));
AbstractList<String> list = new ArrayList<String>();
while (s.hasNext()){
list.add(s.next());
}
s.close();
return list;
}
Then use the method to read the student file and to read the teacher file. Store the results into two separate AbstractList<String> variables, then iterate through them and compare them as you like. Again, think in more general terms.