Pass a parameter with JUnitCore.run() method - java

I have one Test launcher class to run different type of tests by loading and executing classes generated to run with selenium. In this I am launching test by giving a string name and then running it with JUnitCore.run() method
Here is sample code for that:
Class clsTestStep = Class.forName("CheckLogin",true,new ClassLoader() {});
JUnitCore junit = new JUnitCore();
junit.addListener(new ExecutionListener());
org.junit.runner.Result runner= junit.run(clsTestStep);
Can Anyone tell me if I want to pass some object or property value with this class then How can I achieve it?
Note that I want that object to be available in 'CheckLogin' class at test running time, i.e username/password passed from launcher class to 'CheckLogin' class.

Related

JUnit - Run specific tests using JUnitCore

I have a couple of classes which contain Tests.
I have a main method that uses JUnitCore in order to run all tests.
What can I do in order to run specific tests in each class?
Currently I use something like this to run all my tests :
Result result = JUnitCore.runClasses(TestJunit.class, TestJunit2.class);
Maybe there is a possibility to categorize the relevant tests and then run them using JUnitCore ?? Thanks !
You can build a org.junit.runner.Request by providing class and method name and pass it to run method of JUnitCoreclass. This will execute given test of the specified class.
Request request = Request.method(TestClass.class, "methodName");
Result result = new JUnitCore().run(request);
You can check the result of test by invoking wasSuccessful() method available in Result class .

Java pass arguments dynamically to a junit test

I'm doing a special junit test, that the params are introduced in the front-end of the application by the user and received in back-end of the application. And i want to generate junit test that use that information as parameters.
I saw some guide (like mykong guide and tutorial points) but most of them use static parametrized and i want some dynamic thing. I already tried to use junit annotations, do a set or pass the params to the junit class, use mockito methods but nothings work as dynamic process
Can someone point me to the right direction?
Right now i have something like that
public void run (Object foo) //Class that contains the information introduced by the user
JUnitCore junit1 = new JUnitCore();
Result result4 = JUnitCore.runClasses(GeneratedTest.getClass()); //Junit class
//I tried: do a setFoo on the GeneratedTest ; pass the foo on the constructor;
for (Failure failure : result4.getFailures()) {
System.out.println(failure.toString());
}
Probably not the nicest solution, but maybe an acceptable workaround:
generate your unit test so that it fetches parameters from System properties
run the generated JUnit test in its own JVM, and pass the parameters/properties on the command line

How to carry testNG instance to another class

As IS:
Step 1: I am creating instance of testng in servelt.doPost method.
public void dummyDoPost(){
TestListenerAdapter adapter = new TestListenerAdapter();
testNG = new TestNG();
List<Class> listnerClasses = new ArrayList<Class>();
List<String> suiteNameList = new ArrayList<String>();
Class[] classList = new Class[]{
csvOperation.class
};
listnerClasses.add(straight2bank.csvOperation.class);
testNG.setDefaultSuiteName("suite");
testNG.setListenerClasses(listnerClasses);
testNG.setTestClasses(classList);
testNG.run();
Step 2:
I have class created which will read the user choice of platform returned by servelet (Say ios, Android or Chrome).
Pro gram as below.
That an another operation
Class B{
public void platformController (Map<String,String> testDataValues){
System.out.println("Platform Controller started.");
String platformToBeExecuted = testDataValues.get("JourneyId");
System.out.println("Journey ID returned to platformController " +platformToBeExecuted);
if(platformToBeExecuted.contains("chrome")){
System.out.println("Platform to be executed: Chrome");
System.setProperty("webdriver.chrome.driver",pathToChromeDriver);
/****
To remove message "You are using an unsupported command-line flag: --ignore-certificate-errors.
Stability and security will suffer."
Add an argument 'test-type'
ChromeOptions options = new ChromeOptions();
options.addArguments("test-type");
*****/
driver = new ChromeDriver();
driver.get(urlOfApplication);
System.out.println("3");
}else if(platformToBeExecuted.contains("ie")){
System.setProperty("webdriver.ie.driver", pathToIEDriver);
driver = new InternetExplorerDriver();
driver.get(urlOfApplication);
System.out.println("2");
}else if(platformToBeExecuted.contains("iOS")){
System.out.println("Platform to be executed: iOS");
System.out.println("Platform to be executed: iOS");
suites.add(".//iostestng.xml");<-----------------
dummyServletClass.testNG.setTestSuites(suites);
dummyServletClass.testNG.run();
}
SO here I have execute the iosTestng.xml using testng.
To do this :-
1) Do I have to declare testng as static in servelt class and use the same here ?
2) Do I need to create an another instance for testng in class B?
3) Is there any way to pass an argument constructor in setTestClasses?
I'm confused, as we may be working on to run the program in parallel on a long run.
If every POST call basically represents the intention of an end-user to run some tests, then I would suggest that you resort to creating a TestNG instance per invocation. That way, you would be able to isolate the test results etc., for every invocation
1) Do I have to declare testng as static in servelt class and use the same here ?
No don't do that. You will end up causing race conditions. You should instead be declaring TestNG object as a local data member in your POST method implementation. If you don't want your POST call to be a blocking call, you can basically have your POST call create a request to run some tests into a queue and you can have a polling mechanism driven by a separate thread that feeds off of the queue and runs them using TestNG.
2) Do I need to create an another instance for testng in class B?
Yes you would need to. Essentially the idea here is to localise the TestNG instance to the set of tests that it is executing, so that there is no overlapping of results, listener invocations etc.,.
3) Is there any way to pass an argument constructor in setTestClasses?
I didn't quite understand this question. What do you mean by this? Please elaborate.

How to initialize members of App without running the App (main)?

I have a class MyClass, which extends App. The thing is that, inside MyClass, there is a variable myValue that I need to initialize, without actually running the app. The reason for this is because I want to run unit tests of the methods of MyClass in a non-interactive way.
class MyClass extends App {
val myValue = "A value that I need to run the unit tests"
def myMethod: Unit = "A method that needs to be unit-tested and uses " + myValue
/* ... main (interactive) code that is not supposed to run in the unit test... */
}
So, the question is: How can I initialize members of App without running the app (main)?
From scaladocs of App trait:
==Caveats==
It should be noted that this trait is implemented using the DelayedInit functionality, which means
that fields of the object will not have been initialized before
the main method has been executed.
It seems that your only option is to declare main method def main(args: Array[String]): Unit = ... as you would do in Java instead of extending App.

Class<Test> object not the same type as a Test object? Junit

I'm trying to write some code which recursively adds TestSuites in a project to a suite of suites located at the root of the package hierarcy.
I've already written the code which returns a Collection object which contains a File object for each Test Suite found in my project.
I'm now trying to loop through them and add them to a TestSuite in a file called AllTests.java:
public static Test suite() throws IOException, ClassNotFoundException {
TestSuite suite = new TestSuite();
//Code not included for getTestSuites() in this snippet.
Collection<File> testSuites = getTestSuites();
for(File f: testSuites) {
//Truncate the path of the test to the beginning of the package name
String testName = f.getAbsolutePath().substring(f.getAbsolutePath().lastIndexOf("net"));
//Replace backslashes with fullstops
testName = testName.replaceAll("\\\\", ".");
//Take the .class reference off the end of the path to the class
testName = testName.replaceAll(".class", "");
//Add TestSuite to Suite of Suites
Class<? extends Test> test = (Class<? extends Test>) AllTests.class.getClassLoader().loadClass(testName);
suite.addTest(test);
}
Unfortunately I am getting the following compiler error on the suite.addTest(test) line:
The method addTest(Test) in the type
TestSuite is not applicable for the
arguments (Class < capture#3-of ? extends Test>)
Am I making a fundamental mistake by assuming that a Class< Test > reference and a Test reference are one and the same?
Yes, you are making a fundamental mistake by assuming that a Class< Test > reference and a Test reference are one and the same.
You need an instance of a Class that extends Test, not an instance of a Class object whose definition extends Test (Classes are objects too in java).
TestSuite.addTest needs a Test class instance; not just a Class object.
You could try using Class.newInstance() if your tests can be (they should) instantiated without parameters.
--
A maybe better strategy is to start using Maven; which automatically runs all Test classes in the src/test/java source folder. But that can be a quite big overhaul :).
Class<Test> describes the concept of class Test -- its fields, methods, and other stuff described by the Java code when defining class Test. There is generally (to keep classloaders out of this discussion) one instance of Class<Test> across the JVM, since there is basically just one Test class.
The same applies for every Test subclass -- there is generally one instance of Class<TestSubClass> for every TestSubClass.
On the other hand, there can be any number of Test objects.
Java allows you to create Test objects from a Class<Test>, by invoking newInstance against your Class<Test> instance. So basically, change your line from:
suite.addTest(test);
to
suite.addTest(test.newInstance());
And handle all potential exceptions.
Method you are using expects instance of Test (sub)class.
The one you are after is probably addTestSuite(Class testClass) which allows adding classes.

Categories