How to add testng parameters in a java main method? - java

I wanted to trigger the execution from a java main method instead of testng.xml file.
My doubt is how to add the parameters to Java main method for the execution. I have found .addListener and .setGroups to add listener and groups respectively, but couldn't able to find a way to add parameters.
Please help me out to start the exection through java main method.
Sample:
public class Execution {
public static void main(String[] args) throws IOException {
TestNG test = new TestNG();
test.setTestClasses(new Class[] {AETVTests.class});
test.addListener(new MyTestListenerAdapter());
test.setGroups("");
test.run();
}
}

If you would reconsider using xml - you can also trigger execution through the main method with the xml file. Add the testng.xml file to your project path (in eclipse you can right click project - new - file - testng.xml), and this will work:
public static void main(String[] args) throws IOException
{
TestNG testng = new TestNG();
List<String> suites = Lists.newArrayList();
suites.add("C:\\eclipse-2018\\Tests\\testng.xml"); //path to xml
testng.setTestSuites(suites);
testng.run(); //run TestNG
}

You can access args by arg[0],arg[1] likewise. in cmd run your jar file>
java -jar classname.jar param1 param2

Related

How to provide java program with external files when executing the run command in console?

So it might seem like a trivial question, but I cannot find any information out there that answers my question. Nonetheless, it is a very general coding question.
Suppose you have a java program that reads a file and creates a data structure based on the information provided by the file. So you do:
javac javaprogram.java
java javaprogram
Easy enough, but what I want to do here is to provide the program with a file specified in the command line, like this:
javac javaprogram.java
java javaprogram -file
What code do I have to write to conclude this very concern?
Thanks.
One of the best command-line utility libraries for Java out there is JCommander.
A trivial implementation based on your thread description would be:
public class javaprogram {
#Parameter(names={"-file"})
String filePath;
public static void main(String[] args) {
// instantiate your main class
javaprogram program = new javaprogram();
// intialize JCommander and parse input arguments
JCommander.newBuilder().addObject(program).build().parse(args);
// use your file path which is now accessible through the 'filePath' field
}
}
You should make sure that the library jar is available under your classpath when compiling the javaprogram.java class file.
Otherwise, in case you don't need an utility around you program argument, you may keep the program entry simple enough reading the file path as a raw program argument:
public class javaprogram {
private static final String FILE_SWITCH = "-file";
public static void main(String[] args) {
if ((args.length == 2) && (FILE_SWITCH.equals(args[0]))) {
final String filePath = args[1];
// use your file path which is now accessible through the 'filePath' local variable
}
}
}
The easiest way to do it is using -D, so if you have some file, you could call
java -Dmy.file=file.txt javaprogram
And inside you program you could read it with System.getProperty("my.file").
public class Main {
public static void main(String[] args) {
String filename = System.getProperty("my.file");
if (filename == null) {
System.exit(-1); // Or wharever you want
}
// Read and process your file
}
}
Or you could use third a party tool like picocli
import java.io.File;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
#Command(name = "Sample", header = "%n#|green Sample demo|#")
public class Sample implements Runnable {
#Option(names = {"-f", "--file"}, required = true, description = "Filename")
private File file;
#Override
public void run() {
System.out.printf("Loading %s%n", file.getAbsolutePath());
}
public static void main(String[] args) {
CommandLine.run(new Sample(), System.err, args);
}
}
You can pass file path as argument in two ways:
1)
public class Main {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("File path plz");
return;
}
System.out.println("File path: " + args[0]);
}
}
2) Use JCommander
Let's go step by step. First you need to pass the file path to your program.
Lets say you execute your program like this:
java javaprogram /foo/bar/file.txt
Strings that come after "javaprogram" will be passed as arguments to your program. This is the reason behind the syntax of the main method:
public static void main(String[] args) {
//args is the array that would store all the values passed when executing your program
String filePath = args[0]; //filePath will contain /foo/bar/file.txt
}
Now that you were able to get a the file path and name from the command-line, you need to open and read your file.
Take a look at File class and FileInputStream class.
https://www.mkyong.com/java/how-to-read-file-in-java-fileinputstream/
That should get you started.
Good luck!

Create TestNG.xml file dynamically and pass parameter

I have to execute test scripts using dynamic testng.xml file which means I have to create testng.xml file thru code and pass the parameters to the #Test methods pro grammatically.
For that I have created two Java files DynamicTestNG.java which should generate testng.xml file and run SampleClass.java where the #Test method has been written along with the parameters.
DynamicTestNG.java
public class DynamicTestNG {
public void runTestNGTest(Map<String,String> testngParams) {
//Create an instance on TestNG
TestNG myTestNG = new TestNG();
//Create an instance of XML Suite and assign a name for it.
XmlSuite mySuite = new XmlSuite();
mySuite.setName("MySuite");
//Create an instance of XmlTest and assign a name for it.
XmlTest myTest = new XmlTest(mySuite);
myTest.setName("MyTest");
//Add any parameters that you want to set to the Test.
myTest.setParameters(testngParams);
//Create a list which can contain the classes that you want to run.
List<XmlClass> myClasses = new ArrayList<XmlClass> ();
myClasses.add(new XmlClass("SampleClass"));
//Assign that to the XmlTest Object created earlier.
myTest.setXmlClasses(myClasses);
//Create a list of XmlTests and add the Xmltest you created earlier to it.
List<XmlTest> myTests = new ArrayList<XmlTest>();
myTests.add(myTest);
//add the list of tests to your Suite.
mySuite.setTests(myTests);
//Add the suite to the list of suites.
List<XmlSuite> mySuites = new ArrayList<XmlSuite>();
mySuites.add(mySuite);
//Set the list of Suites to the testNG object you created earlier.
myTestNG.setXmlSuites(mySuites);
TestListenerAdapter tla = new TestListenerAdapter();
myTestNG.addListener(tla);
//invoke run() - this will run your class.
myTestNG.run();
}
public static void main (String args[])
{
DynamicTestNG dt = new DynamicTestNG();
//This Map can hold your testng Parameters.
Map<String,String> testngParams = new HashMap<String,String> ();
testngParams.put("searchtext1", "testdata1");
testngParams.put("searchtext2", "testdata2");
dt.runTestNGTest(testngParams);
}
}
And SampleClass.java
public class SampleClass {
private WebDriver driver;
#BeforeTest
public void setUp()
{
System.setProperty("webdriver.chrome.driver","C:\\Users\\AK5040691\\Desktop\\IE driver\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.navigate().to("http://executeautomation.com/blog/custom-testng-library-for-appium/#more-1562");
}
//#Parameters({"searchText1","searchText2"})
//#Test
public void searchText(String text1, String text2)
{
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
driver.findElement(By.className("search-field")).sendKeys(text1);
driver.findElement(By.className("search-field")).clear();
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
driver.findElement(By.className("search-field")).sendKeys(text2);
}
}
Its not running. Please let me know the mistake here.
You have to uncomment the #Test annotation in your SampleClass file. And if your SampleClass is in a package , then absolute package name + class name is to be specified in this statement.
myClasses.add(new XmlClass("com.some.package.SampleClass"));
Generally TestNG classes have a suffix or prefix labelled "Test" so that surefire plugin can include them in the execution flow, in case if you are using maven.
You can instead use the constructor with parameter of class object .
myClasses.add(new XmlClass(SampleClass.class));

how to create executable jar file with cucumber tests?

My service create an executable jar by gradle. When i create and run my jar (java -jar file.jar) i recive error:
no main manifest attribute, in "file.jar"
because i don't have main_class.
I created main method:
public static void main(final String[] args) throws Throwable {
String[] arguments = {"--plugin", "html:build/reports/cucumber", "src/test/resources/features", "--glue", "src/test/java/steps"};
cucumber.api.cli.Main.main(arguments);
}
and My program founds the features but doesn't found glue code.
Could someone help me with this problem? Thank you in advance.
The value for the glue option should be a java classpath. And the feature files should be the last option.
{"--plugin", "html:build/reports/cucumber", "--glue", "steps", "src/test/resources/features"}
The below code worked for me to execute the cucumber tests from runnable jar with test frame work as TestNG.
Executing jar:
java -jar ProductsAutomation-0.0.1-SNAPSHOT-jar-with-dependencies.jar
import io.cucumber.core.cli.Main;
public static void main(String args[]) throws Throwable {
try {
Main.main(new String[] {
"-g","com.sadakar.cucumber.common",
"-g","com.sadakar.cucumber.runner",
"classpath:features",
"-t","#SmokeTest",
"-p", "pretty",
"-p", "json:target/cucumber-reports/cucumber.json",
"-p", "html:target/cucumber-reports/cucumberreport.html",
"-m"
}
);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Main method exception : " + e);
}
}

What's the best way to execute a .jar in java code

I need develop a "launcher" for a java application. This launcher need be able to:
check if main application is up-to-date;
if not, download a update;
run this application and self terminate.
Something like this:
public final class Launcher {
public static void main(String[] args) throws Exception {
String jarName = args[0];
if (jarHasUpdate(jarName)
refreshJar(jarName);
executeJar(jarName);
}
}
What better way of develop the step 3?
I'm trying 2 distinct ways:
1- Run another instance of Java
With the code:
Runtime.getRuntime().exec("java -jar mainApp.jar");
Problem: the launcher still running until mainApp have finished.
2- Using ClassLoader to load .jar at runtime
Like this:
public final class Launcher {
#SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.out.println("Invalid number of arguments.");
System.exit(1);
}
Refresh.refreshFile(args[0]);
// args[0] .jar name
// args[1] class with main function
File file = new File(args[0]);
try (URLClassLoader cl = new URLClassLoader(new URL[] { file.toURI().toURL() });) {
Class cls = cl.loadClass(args[1]);
Method method = cls.getDeclaredMethod("main", new Class[] { String[].class });
Object params = new String[] {};
method.invoke(cls, params);
}
}
}
Problem: if "mainApp.jar" has dependencies, this isn't loaded.

Run all tests in a source tree, not a package

My unit tests are in a separate directory tree from my integration tests, but with the same package structure. My integration tests need external resources (e.g. a server) to be available, but my unit tests are properly independent of each other and the environment.
In IntelliJ-IDEA (v7) I have defined a JUnit Run/Debug Configuration to run all the tests in the top-level package, and this of course picks up my integration tests which fail.
I want to define a run-junit configuration that runs all my unit tests. Any ideas?
The answer is to create a test suite that contains only those tests underneath the unit test folder and run that instead. There is a junit-addon which does just this called DirectorySuiteBuilder but I only found this after I had pretty much re-invented the wheel.
And it's already been asked here!
import junit.framework.JUnit4TestAdapter;
import junit.framework.TestSuite;
import java.io.File;
import java.io.IOException;
public class DirectoryTestSuite {
static final String rootPath = "proj\\src\\test\\java\\";
static final ClassLoader classLoader = DirectoryTestSuite.class.getClassLoader();
public static TestSuite suite() throws IOException, ClassNotFoundException {
final TestSuite testSuite = new TestSuite();
findTests(testSuite, new File(rootPath));
return testSuite;
}
private static void findTests(final TestSuite testSuite, final File folder) throws IOException, ClassNotFoundException {
for (final String fileName : folder.list()) {
final File file = new File( folder.getPath() + "/" +fileName);
if (file.isDirectory()) {
findTests(testSuite, file);
} else if (isTest(file)) {
addTest(testSuite, file);
}
}
}
private static boolean isTest(final File f) {
return f.isFile() && f.getName().endsWith("Test.java");
}
private static void addTest(final TestSuite testSuite, final File f) throws ClassNotFoundException {
final String className = makeClassName(f);
final Class testClass = makeClass(className);
testSuite.addTest(new JUnit4TestAdapter(testClass));
}
private static Class makeClass(final String className) throws ClassNotFoundException {
return (classLoader.loadClass(className));
}
private static String makeClassName(final File f) {
return f.getPath().replace(rootPath, "").replace("\\", ".").replace(".java", "");
}
}
IntelliJ IDEA CE 10.5 has a (new?) option to run all tests inside a configured directory:
Unfortunately there's no way to separate the output from the IntelliJ compile other than by classes and test classes within a single module (it's the classes that test runner is looking at).
So when I have integration tests I simply use a second module specific to these tests to get round this problem, specifying output directories as necessary for each module.

Categories

Resources