I have pw_check.java and I need to run it with an argument first and then run it without argument in terminal.
java pw_check -g
java pw_check
But in second command, without argument, the system is throwing exception. How could I handle it to feed my requirement.
Check the code pw_check.java.
Probably there is something like
public static void main(String[] args) {
// Code accessing args[0]
}
This will cause an error if you don't have a parameter.
Modify with a code similar to the following:
public static void main(String[] args) {
String arg = DEFAULT_ARG;
if (args.length == 1) {
arg = args[0];
}
... // Code using arg DEFAULT or passed value
}
Related
I'm trying to test my main method (which should accept exactly one argument) for no arguments passed. Can't seem to understand what am I missing here to achieve that.The nature of my program is such that it reads input from a file, creates objects by passing parameters read from the file, and displays output.
Failure Message:
org.junit.ComparisonFailure: Expected :Please pass one argument
Actual :
Here's my Unit Test:
#Test
public void givenNoParameter_shouldAskForOne() throws IOException {
String[] args = {};
String output;
try (ByteArrayOutputStream bOutput = new ByteArrayOutputStream()) {
System.setOut(new PrintStream(bOutput));
Main.main(args);
bOutput.flush();
output = bOutput.toString();
}
String newLine = System.getProperty("line.separator");
String[] breakDownOutput = output.split(newLine);
assertEquals(1, breakDownOutput.length);
assertEquals("Please pass one argument", breakDownOutput[0]);
}
Main Method:
public static void main(String[] args) {
if(args.length == 1) {
DisplayOrder.setFilePath(args[0]);
DisplayOrder.display();
} else{
System.err.println("Please pass one argument");
}
}
I've realized I was using System.err.println() in my main. Changing that to System.out.println() fixed it.
Not showing your main method, my only guess is, that you do not write anything to "System.out" in your main, especially there is no System.out.println("Please pass one argument"); statement which is executed.
So, your unit test fails perfectly for a not expected value in "breakDownOutput[0]".
What you have to do is to make certain that the System.out.println("Please pass one argument"); is executed if no arguments were provided to your main.
Also check your class name Main.main(...) since there might be other Main classes imported which will never print out your expected values to System.out
I have written a CLIInterface in java that takes the necessary flags from the user as a String[].
Here is some sample code:
public static void call(String[] args)
{
try
{
Map<String, Object> cliOptions = new HashMap<>();
for (int i = 0; i < args.length; ++i) {
// override the db directory
if (args[i].equals("--help")) {
printHelp();
System.exit(1);
}
..........
}
I know that you can invoke the method in the command line using something like this:
java -Dexec.mainClass=org.bitcoinj.examples.ForwardingService -Dexec.args=""
but I want to be able to use it like a CLI and have something like this:
ethj --help whereby --help would be args[0] and then from there I could handle it in the call method.
How would one go about doing this?
the easiest way is to write a starter script ethj for your operation system passing the arguments to the java executable.
btw:
you don't need the -Dexec.args="" form, just list the parameters after the main class name...
My Java application consists of two parts:
core libraries (classes, interfaces, etc)
command line interface (CLI), which uses the core libraries
For 1. I use JUnit for unit testing, but what would you do for 2.?
How can I create automated tests for a command line interface?
I had the exact same problem, landed here and didn't find a good answer, so I thought I would post the solution I eventually came to as a starting point for anyone who lands here in the future.
I wrote my tests after the CLI (shame on me, I know), so first I made sure the CLI was written in a testable way. It looks something like this (I've omitted the exception handling and simplified a lot to make it more readable):
public class CLI {
public static void main(String... args) {
new CLI(args).startInterface();
}
CLI(String... args) {
System.out.println("Welcome to the CLI!");
// parse args, load resources, etc
}
void startInterface() {
BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String[] input = sanitiseInput(consoleReader.readLine());
if (input[0].equalsIgnoreCase("help") {
help();
} else if (input[0].equalsIgnoreCase("exit") {
break;
} else if (input[0].equalsIgnoreCase("save") {
save(input);
} else {
System.out.println("Unkown command.");
}
}
}
String[] sanitiseInput(String rawInput) {
// process the input and return each part of it in order in an array, something like:
return rawInput.trim().split("[ \t]+");
}
void help() {
// print help information
System.out.println("Helpful help.");
}
void save(String[] args) {
// save something based on the argument(s)
}
}
On to testing. CLI is not a part of the public libraries, so it should be protected from library users. As is mentioned here, you can use the default access modifier to make it package private. This gives your tests full access to the class (as long as they are in the same package) while still protecting it, so that's that taken care of.
Writing a method for each command accepted by the CLI allows JUnit tests to almost perfectly simulate user input. Since the object won't read from stdin until you call startInterface(), you can simply instantiate it and test the individual methods.
First, it's good to test that the raw input is being correctly sanitised, which you can do trivially by writing JUnit tests for sanitiseInput(). I wrote tests like this:
#Test
public void commandAndArgumentsSeparatedBySpaces() throws Exception {
String[] processedInput = uut.sanitiseInput("command argument1 argument2");
assertEquals("Wrong array length.", 3, processedInput.length);
assertEquals("command", processedInput[0]);
assertEquals("argument1", processedInput[1]);
assertEquals("argument2", processedInput[2]);
}
It's easy to cover some edge cases too:
#Test
public void leadingTrailingAndIntermediaryWhiteSpace() throws Exception {
String[] processedInput = uut.sanitiseInput(" \t this \twas \t \t a triumph \t\t ");
assertEquals("Wrong array length.", 4, processedInput.length);
assertEquals("this", processedInput[0]);
assertEquals("was", processedInput[1]);
assertEquals("a", processedInput[2]);
assertEquals("triumph", processedInput[3]);
}
Next we can test the invididual command methods by monitoring stdout. I did this (which I found here):
private CLI uut;
private ByteArrayOutputStream testOutput;
private PrintStream console = System.out;
private static final String EOL = System.getProperty("line.separator");
#Before
public void setUp() throws Exception {
uut = new CLI();
testOutput = new ByteArrayOutputStream();
}
#Test
public void helpIsPrintedToStdout() throws Exception {
try {
System.setOut(new PrintStream(testOutput));
uut.help();
} finally {
System.setOut(console);
}
assertEquals("Helpful help." + EOL, testOutput.toString());
}
In other words, substitute the JVM's out with something you can query just before the exercise, and then set the old console back in the test's teardown.
Of course, CLI applications often do more than just print to the console. Supposing your program saves information to a file, you could test it as such (as of JUnit 4.7):
#Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
#Test
public void informationIsSavedToFile() throws Exception {
File testFile = tempFolder.newFile();
String expectedContent = "This should be written to the file.";
uut.save(testFile.getAbsolutePath(), expectedContent);
try (Scanner scanner = new Scanner(testFile)) {
String actualContent = scanner.useDelimiter("\\Z").next();
assertEquals(actualContent, expectedContent);
}
}
JUnit will take care of creating a valid file and removing it at the end of the test run, leaving you free to test that it is properly treated by the CLI methods.
For any CLI you can use BATS (Bash Automated Testing System):
The test-specification from the docs is a script-file like example.bats:
#!/usr/bin/env bats
#test "addition using bc" {
result="$(echo 2+2 | bc)"
[ "$result" -eq 4 ]
}
#test "addition using dc" {
result="$(echo 2 2+p | dc)"
[ "$result" -eq 4 ]
}
When using the bats command to execute and the output look like this:
$ bats example.bats
✓ addition using bc
✓ addition using dc
2 tests, 0 failures
See related tag for more questions: bats-core
How can I make a main method take a text file as an argument on the command line?
So for example
java ClassWithMainMethod textFileNeededInMainMethod.txt
I've been told this is possible but I'm not sure how it's done.
You use the String[] args from the Java program entry point like
public static void main(String[] args) {
if (args.length < 1) {
System.err.println("no file provided");
System.exit(1);
}
File f = new File(args[0]);
// ...
}
That if could be used to set a default file if one isn't provided. Finally, it's a good idea to use File.canRead() before you try and read from a file.
The arguments passed to main are of type string so you'd pass the name of the file or path of the file and then create a file object and then read its content.
You can't pass the type file to a java main class
In your main method, the args array contains any arguments. For example, if you typed java ClassWithMainMethod textFileNeededInMainMethod.txt, then you could read the argument like this:
public static void main(String[] args) {
String file = "";
if(args.length > 0) file = args[0];
}
I am looking to do some error checking for my command line arguments
public static void main(String[] args)
{
if(args[0] == null)
{
System.out.println("Proper Usage is: java program filename");
System.exit(0);
}
}
However, this returns an array out of bounds exception, which makes sense. I am just looking for the proper usage.
The arguments can never be null. They just won't exist.
In other words, what you need to do is check the length of your arguments.
public static void main(String[] args) {
// Check how many arguments were passed in
if (args.length == 0) {
System.out.println("Proper Usage is: java program filename");
System.exit(0);
}
}
#jjnguy's answer is correct in most circumstances. You won't ever see a null String in the argument array (or a null array) if main is called by running the application is run from the command line in the normal way.
However, if some other part of the application calls a main method, it is conceivable that it might pass a null argument or null argument array.
However(2), this is clearly a highly unusual use-case, and it is an egregious violation of the implied contract for a main entry-point method. Therefore, I don't think you should bother checking for null argument values in main. In the unlikely event that they do occur, it is acceptable for the calling code to get a NullPointerException. After all, it is a bug in the caller to violate the contract.
To expand upon this point:
It is possible that the args variable itself will be null, but not via normal execution. Normal execution will use java.exe as the entry point from the command line. However, I have seen some programs that use compiled C++ code with JNI to use the jvm.dll, bypassing the java.exe entirely. In this case, it is possible to pass NULL to the main method, in which case args will be null.
I recommend always checking if ((args == null) || (args.length == 0)), or if ((args != null) && (args.length > 0)) depending on your need.
You should check for (args == null || args.length == 0). Although the null check isn't really needed, it is a good practice.
if i want to check if any speicfic position of command line arguement is passed or not then how to check?
like for example
in some scenarios 2 command line args will be passed and in some only one will be passed then how do it check wheather the specfic commnad line is passed or not?
public class check {
public static void main(String[] args) {
if(args[0].length()!=0)
{
System.out.println("entered first if");
}
if(args[0].length()!=0 && args[1].length()!=0)
{
System.out.println("entered second if");
}
}
}
So in the above code if args[1] is not passed then i get java.lang.ArrayIndexOutOfBoundsException:
so how do i tackle this where i can check if second arguement is passed or not and if passed then enter it.
need assistance asap.
If you don't pass any argument then even in that case args gets initialized but without any item/element.
Try the following one, you will get the same effect:
public static void main(String[] args) throws InterruptedException {
String [] dummy= new String [] {};
if(dummy[0] == null)
{
System.out.println("Proper Usage is: java program filename");
System.exit(0);
}
}