• Post Reply Bookmark Topic Watch Topic
  • New Topic

Running a test with a file  RSS feed

 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello Everybody!

I just wrote a java program with eclipse that has to read many-many inputs from the user. I want to test it, but I really don't want to type it everytime again and again...
Can I just write all inputs in a text file and let eclipse read this file so instead of typing it again and again, Eclipse reads every line whenever it waits for a user input?

Thanks :-)
 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is no way that I know of to fill input from a file instead of the keyboard in Eclipse, but there are other ways to test a program. The best way is to write JUnit tests. This works if you have distinct methods for validation and processing, apart from your user interface (UI). For a beginning programmer, this is a really good way to start writing better programs. What if you want to use a GUI or web interface? What if you wanted to create a web service and have other programs call your logic? Separating the UI, validation, and processing makes this possible.

Another thought is to make the program accept command line input (CLI). Then you can write a batch or shell file that calls the program with different CLI. You could make the CLI positional...

program_name first_answer second_answer ...

... or use flags for more control:

program_name --second-answer=data --fifth-answer=data ...
 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, a batch file IS the best option for me.
But I have a problem. My program includes 5 files, let's say A.java, B.java, C.java, D.java, E.java.

My batch file is "test.bat". Its content is:



What am I doing wrong?
 
E Armitage
Rancher
Posts: 989
9
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Matan Bar Lev wrote:
What am I doing wrong?

You haven't said what your expected output is we don't know if you are doing something wrong let alone what you are doing wrong.
I would also strongly suggest learning how to use junit to test code. It teaches you to write testable code. Testable code is reusable code.
 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
junit ? what is it?

Actually, the output should be a text file that the program creates that includes some information.

The input/output should be this:

Please choose shape type:
E - Ellipse
R - Rectangle
S - Square
X - Exit
R
Please enter X coordinate:
1
Please enter Y coordinate:
2
Please enter width:
10
Please enter height coordinate:
20
Shape added: [Rectangle: Rectangle: X=1, Y=2, Width=10, Height=20]
Please choose shape type:
E - Ellipse
R - Rectangle
S - Square
X - Exit
X
 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, almost everything. :-/

A batch file will take each line and execute it, so the first line...

javac ShapeDimensionCalculator.java

...will compile the code, not execute it. Then the line "R" will try to execute, but that's not a command. Neither is 1, 2, 10, 20, or X.

In Windows, the pause command is just "pause".

What you probably want is "java ShapeDimensionCalculator". Or, if you have written the program to accept CLI, "java ShapeDimensionCalculator R 1 2 10 20 X"
 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, I corrected the batch file to be:

java ShapeDimensionCalculator R 1 2 10 20 X

pause();

I got an error saying: "Error: Could not find or load main class ShapeDimensionCalculator"

 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would Google "JUnit" and read that.

There is no magic way to get a Java program to read keyboard input from a file that I know of. You have to write the program to look in a file or at command line arguments.

http://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html
 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I will read about it.
But, for now, I just want to know why windows cannot open this file.
Does anybody know the answer?

 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Learn how to compile and run a Java program from the command line.

http://docs.oracle.com/javase/tutorial/getStarted/cupojava/win32.html
 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
this link explains how to compile and run one-file-program.
I tried to type: "javac ShapeDimensionCalculator" and I got many errors saying that java doesn't recognize the classes I defined in the program.


 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Go to Google.

Type in "compiling multiple java files"

Read the links.

Please do some basic research before asking a question.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
JUnit is the right way to go here. But just so as to answer the question related to batch files, you can do what is called 'piping' a file into a process' input stream using the '<' character. Example, if I have the class: lev.bar.martan.ShapeDimensionCalculator, and I made a text file named Rectangle.txt with these contents:

Then I could create a batch file named Test.bat like this:

And I would get results like this:


In fact, I could pipe the output to a text file as well, so you could run many tests, see how each one ran without having a long command window buffer to sift through. The Test.bat would be:

And it would produce a results.txt file that looked like this:
 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, I did read about the JUnit, but still I didn't find out how to insert an input stream and let a JUnit test read it and pssing it to the code.
 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't think there is a way to insert input into a read, but congratulations on the JUnit test. Now you can create methods that test every aspect of input to your program and have them run automatically when you build the project (for instance, Maven does this). Or you can run them manually in Eclipse by choosing Run -> Run As -> JUnit test.

If you want, you can post some code here and I will try to answer your questions.
 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK...

I have a problem with Juint so I'm publishing my code.

ShapeDimensionCalculatorTest.java:







Shape is an interface, and Rectangle, Ellipse and Square implement it.


When I run ShapeDimensionCalculatorTest.java I get an error in the line:
ShapeDimensionCalculator.AddToArray(rect1); // Error

saying: "java.lang Null pointer Exception"

What am I doing wrong?

 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't think the error is where you say it is. I think that is just the line in the test class, while further reading of the stack trace should indicate the error is actually on line 95 of the ShapeDimensionCalculator (as posted in your code above): new_shapes_array[i]=shapes_array[i];. What value does shapes_array have when you first call the AddToArray() method?

I'll give you a hint - it would cause a 'pointer exception'.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, a hint on creating useful UnitTests. I think it is better to be more granular in your testing. Right now you have one test which tests putting something in an array and writing it to a file. That is at least two units (adding to the array (1) and writing to file (2)). You also don't have any tests to make sure things succeed, you would have to manually read the file and compare against the test inputs, which is missing the point or unit testing.

So here is a starter


Note that each test is for 1 method, and that each method might have multiple tests for it to test different aspects. Also each of the tests is broken into 3 parts:
1) Setting up the test (in which I make sure the target array is empty, create the rectangle and the expected output)
2) Exercising the code (in which I call the AddToArray() method)
3) Creating a pass/fail metric that is automated (in which I assert something is true or equal to expectations)

See how granular the tests are: If I insert 1 element in an empty array, do I get a single length array. If I insert an element into the array, do I get the list of values I expected?

Also note that I can't really do great testing here. Because everything is static, the shapes_array is shared as long as the class remains in memory - which it does for all the tests. That means, in order for the tests to work, I have to make sure it is empty so each test is an independent test and could be run in an order - I have to have a known starting point. So I get around that by assigning it an empty array. But notice by doing this, I hide the NullPointerException you would get in real code. If those methods were not static, and the shapes_array variable was not static, then this would not be an issue. This shows another aspect of unit testing: you can often identify design problems with your tests, not just code problems.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I should also note that, despite hiding the NullPointerException, both tests fail on the code you posted - because you don't do to shapes_array what you think you are doing. So although the tests look basic they identify an issue and by being this granular it should help you identify where the problem is.
 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for your answers.
I succeeded to find out what the problem was in my code.

At the very beginning of ShapeDimensionCalculator.java, I wrote the line:


I changed it to


and it works fine.


I have two more questions:
1. After getting to know JUnit, it seems that it is not so comfortable to use. I mean, you have some knowlegde about how your code is built/written in order to use it.
It's not like manual test that you don't have to know anything about your code, just inserting the input and wait for the correct output.
Is there any possibility to make tests without getting into the code with JUnit?
2. I saw that once I operate the JUnit test, and the program creates the object named "tester", the program doesn't commit println commands. My question is how the code knows that it doesn't have to commit "println"s?
What other commands are not supposed to be committed when using JUnit?
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Matan Bar Lev wrote:Thanks for your answers.
I succeeded to find out what the problem was in my code.

At the very beginning of ShapeDimensionCalculator.java, I wrote the line:


I changed it to


and it works fine.
Awesome, glad you got it worked out

I have two more questions:
1. After getting to know JUnit, it seems that it is not so comfortable to use. I mean, you have some knowlegde about how your code is built/written in order to use it.
It's not like manual test that you don't have to know anything about your code, just inserting the input and wait for the correct output.
Is there any possibility to make tests without getting into the code with JUnit?


Yes. In fact, I usually try to write my unit tests (in JUnit) before writing the code itself. I usually design the code so I know what class names and public interface there should be be. And I let the test code help define the parameters, expected output, and refine the interface (I consider the tests like a bunch of little use-cases where the 'user' knows what to put in and cares about one particular aspect of the results. Looking at it this way helps me define what the public interface for the class needs to be). The key isn't to know anything about the code, the key is to understand:
- What the normal use-cases are so you can test them
- What the corner cases are so you make sure they are handled
- What the possible failure modes are so you can make sure they are handled or avoided
- What the expected results are so you can be sure the changes you make are measured against expectations

You write a test against one case at a time, write the code to pass the test, then write the next test... Then at the end you go back and refactor the code so it is in good style, takes advantage of normal coding paradigms/design patterns and run the tests again to make sure nothing broke in the refactor. This gets you to 'Test Driven Development'

2. I saw that once I operate the JUnit test, and the program creates the object named "tester", the program doesn't commit println commands. My question is how the code knows that it doesn't have to commit "println"s?

As far as I can tell, that isn't true. If I put System.out.println()s (a.k.a. SOP) in the code that gets called, they are output properly. I suspect one of following things:
1) You think that the menu system should be displayed, because it always is when you run the main() method. But your tests don't call the getShapesFromUser() method, so the menu doesn't get displayed
2) You do have SOPs that should be called, and they are being called, but some configuration is feeding the output to someplace other than the console. This isn't impossible, there are many frameworks which will send SOPs to a log file. I don't know if JUnit has a configuration for that, but if it does, it isn't set up that way on my machine (or any machine I have run JUnit tests on that I am aware of).
3) You think because you aren't getting output to the file that the printlns there are not being executed. This isn't the case. The reason you get no output in the file would be for the same reason the tests I posted above fail.

What other commands are not supposed to be committed when using JUnit?

Generally, nothing. JUnit is just like running normal Java code. It just adds convenience methods and annotations to make running the tests easier, for reporting, and output that IDEs can use to make it easier to understand what failures happened where.
 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Steve,

Thanks for you answers. I really appreciate it!

However, I had a little misunderstanding with the following sentence:

As far as I can tell, that isn't true. If I put System.out.println()s (a.k.a. SOP) in the code that gets called, they are output properly. I suspect one of following things:
1) You think that the menu system should be displayed, because it always is when you run the main() method. But your tests don't call the getShapesFromUser() method, so the menu doesn't get displayed


I found out that once I remove the line:

from "ShapeDimensionCalculatorTest" class, the program runs properly, and SOPs are committed. In addition, the test method actually waits for a user stdio input and doesn't commit the line:


I can see the menu in the console window. I didn't change anything in the method of the test. This may say that maybe the fact that once I declare this method as a test (by writing "@test"), the mehods are read differently.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I suspect you are again no exactly understanding what is happening, or the code you posted is not the same as you are running. If I look at the code you posted there is not a single SOP that would get executed. If you change it to:

Then, at least on my machine, "Hello" gets printed to the console. If I move that SOP to AddToArray() or to writeShapesToFile() then it is also printed to my console.

So here is what I think might be happening:
1) As I said before, JUnit is redirecting SOP to someplace else. This isn't happening on my machine, but it possible. Research JUnit to see if it can be configured to do that
2) When you take out the @Test annotation, you aren't running the test code. You are actually running a main() method, and that main() method runs the menu like you expect, while the test code does not.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Matan Bar Lev wrote:I found out that once I remove the line:

from "ShapeDimensionCalculatorTest" class, the program runs properly, and SOPs are committed. In addition, the test method actually waits for a user stdio input and doesn't commit the line:
I can see the menu in the console window.

Yup, I am sure it is the second of the two possibilities in my last post. When you take out the @Test annotation you no longer have a JUnit test to run. That method doesn't get called. Instead your IDE must be running the ShapeDimensionCalculator's main() method.
 
E Armitage
Rancher
Posts: 989
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Likely the println statements are in the main method and the unit test doesn't call the main method (which it should not ofcourse). Another possiblity is that you are actually not checking the console at all. After the test runs it usually defaults to displaying the test results not the console. You would need to just select the console display pane to see the console results if that is the case.
 
Matan Bar Lev
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So the question is WHY when we run a JUnit test and create a new ShapeDimensionCalculator object, the main method is not committed?
When we just create a ShapeDimensionCalculator object as a part of a program (without @test), the program automatically go to the main method. Why doesn't it happen when we run a test?
 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The short answer is that you're (correctly) not testing the main method; you are testing the methods main() calls. main() isn't what gets called when an object is created; that's the class.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Matan Bar Lev wrote:So the question is WHY when we run a JUnit test and create a new ShapeDimensionCalculator object, the main method is not committed?

Because you never call it.
When we just create a ShapeDimensionCalculator object as a part of a program (without @test), the program automatically go to the main method. Why doesn't it happen when we run a test?

No, when you create a ShapeDimensionCalculator object, the main method is not called. When you run the application then the main method is called, because, by definition, that is what running an application does (when you do java ShapeDimensionCalculator it loads the ShapeDimensionCalculator class and calls the public static main(String[] args) method or provides an error if either of those steps fails).

When you run the Test, you are running JUnit which loads the TestCase class and executes those methods marked as tests. It does not call the main method unless you tell it to.

And as others said, you shouldn't tell the test method to call the main method.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!