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.
Related
Using Java, I am trying to write a general check for a particular text on every page in a web application that existing tests visit. Instead of having to write it on each and every page individually, is it possible to do in one place at a high level (may be in the base class)?
public class BaseClassForUiTest {
public BaseClassForUiTest() {
...
}
public void test() throws Exception {
boolean isNewPage = checkIfNewPage();
if (isNewPage)
// perform a text check on the page
}
}
Every test extends from BaseClassForUiTest and overrides the test() method.
Instead of having to write it on each and every page individually, is it possible to do in one place at a high level (may be in the base class)?
Yes, it is possible by implementing WebDriverEventListener into BaseClassForUiTest and override event handler methods to handling the appropriate WebDriver events according to need in one place.
Here every method corresponds to an event. According to your requirement you need to handle afterNavigateTo() method. This one is called every time the navigate to a page is completed.
You have to do perform a text checker on the page code in this method so that your code is executed every time the page navigates to some other page.
public class BaseClassForUiTest implements WebDriverEventListener
{
---------
---------
public void afterNavigateTo(String arg0, WebDriver arg1) {
// perform desire text checker stuff on the page here
}
}
Now Create Event Throwing WebDriver to perform your test :-
Create a regular WebDriver.
FirefoxDriver driver = new FirefoxDriver();
Now create an EventThrowingWebDriver using our regular WebDriver created above.
EventFiringWebDriver eventDriver = new EventFiringWebDriver(driver);
Create an instance of your eventHandler class and register it for events using the register method of EventFiringWebDriver object created above as :-
BaseClassForUiTest handler = new BaseClassForUiTest();
eventDriver.register(handler);
Full code :-
import org.openqa.selenium.support.events.EventFiringWebDriver;
public class BaseClassForUiTest {
public void test() throws Exception {
FirefoxDriver driver = new FirefoxDriver();
EventFiringWebDriver eventDriver = new EventFiringWebDriver(driver);
BaseClassForUiTest handler = new BaseClassForUiTest();
eventDriver.register(handler);
eventDriver.get("your url");
//Now do your further stuff
}
}
As for me, you'd better create a separated test class for this check using Parameterized or JUnitParams and give it a urls to run where as parameters, but it depends on what is your common approach to running tests (we run all testpack at the same time, so it's a solution for us in this situation).
Also it is seems like well-logically-separated solution
If you are going to use this check as an assertion you can rewrite your current code for this case and call for it in #Before block (but it is still not a good solution, in my opinion)
I'm trying to set up a web app test suite using Selenium and Java. I am going to create 3 packages under src
Objects - used for my page objects
Tasks - used for testing methods
Tests - used for the tests
Under Tasks I created a class called CommonTasks, which is used to store methods created for testing. Here are some examples.
protected void verifyNumberOfElements(By selector, int expectedsize){
int size = driver.findElements(selector).size();
log.info("INFO: Verifying the number of elements is "+expectedsize+"");
Assert.assertEquals(size, expectedsize);
log.info("PASS: The number of elements returned was "+expectedsize+" ");
}
public static void verifyText(By selector, String expectedtext){
//verify that the expected text is present
String actualtext = driver.findElement(selector).getText();
Assert.assertEquals(actualtext, expectedtext);
log.info("PASS: "+expectedtext+" was present and verified");
}
protected void verifyElement(By selector){
//Verify that a certain selector is present in the page
smartSleep(selector);
boolean isPresent = driver.findElements(selector).size() > 0;
Assert.assertEquals(isPresent, true);
log.info("PASS: Element was found");
boolean notPresent = driver.findElements(selector).size() > 0;
Assert.assertEquals(notPresent, false);
log.info("FAIL: Element was NOT found");
}
Under the Tests package, I create a class called ABC for testing feature ABC. I have some basic steps like below
verifyText(PageObjects.ItemText, "Multiple Choice - Single Answer Radio - Vertical");
verifyText(PageObjects.Progress_PercentComplete, "0%");
The issue I am having is I don't know where to create the webdriver. I want to be able to create many test classes and call any method created in the Tasks package. I know that I need to import the class from Tasks, but can't figure out the webdriver creation part. Both the Tasks and Test packages will reference driver, so how to I make this work? Does it need to be created in Tasks.CommonTasks, or Tests.ABC?
I will also need the test to connect to SauceLabs instead of my local machine.
From the code above, all your methods in the Tasks packages are utility methods and are common to your test suite so these methods are invoked from the Test methods only where your driver was initialized already so create your webdriver in your test class and pass it on to utility methods in the tasks package.
Hope it helps
I have two test classes each containing a number of tests. I'd like to run both of these together without having to have the #BeforeClass setup method being ran both times. I am calling the classes like this:
public static void main(String[] args) {
TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { TestClass1.class, TestClass2.class });
testng.addListener(tla);
testng.run();
}
The reason for this is because I have both of them calling in a pop up menu and only want to select the option one time. If this is unclear I will try to further explain.
I have a collection of individual tests across 5 classes. I want each class to be able to run separately, but I also want to make them run collectively should I desire. In the #BeforeClass I have each of them calling another class that will select what URL I want to use (I am testing with TestNG and using Selenium WebDriver).
When this code runs it will execute the #BeforeClass in each class I list, and I would like to, if possible, ignore the #BeforeClass in all the tests if I execute the tests using the code above.
I would recommend passing a transformer in to your TestNG test case that implements, IAnnotationTransformer2. That transformer can allow you to control the behavior of the non #Test Annotations at runtime.
IAnnotationTransformer2
You can use a #BeforeTest in a common class of your 2 test classes.
I understand you want to run the stuff inside #Before only once for your 2 test classes that will be executed at same time together.
If you are using maven + junit 4.x, there is an option for setup things before and after test suit start and complete.
Or you can simply create a #ClassRule at suite level, please see the doc
I am working on a test suite using WebDriver and TestNG. The application under test has a "report menu" which is a set of links to a ton of different reports. The list of reports is dynamic based on a bunch of different variables. I'd like to create a #Factory which creates a distinct test case for each of these links. So far so good.
However, to discover the links, I need WebDriver initialized (to go to the page, and find all of the links), but that is happening via injection from Spring IOC, and the autowiring (using #Autowired) happens much later in the lifecycle of the test runner. All of the parameters used to construct the driver itself are also injected (base url, driver class, download directory etc), so it's not feasible in this case to create a WebDriver instance "by hand" - it has to be done via the Spring application context as configured using #ContextConfiguration annotation.
So is there a manual way to get the injection to happen this early in the lifecycle of the runner?
My somewhat poor solution to this is:
Since the #Factory method runs really early, just have it return a pre-defined size array of some "empty" test cases. Say the test is MyTest, just do:
#Factory
public Object[] factoryMethod() {
Object[] tests = new MyTest[100];
for (int i = 0; i < 100; i++) {
tests[i] = new MyTest();
}
return tests;
}
Have the test method, say test() inside MyTest run at priority=1. Have a completely separate test method at priority=0, which goes to the "menu" page using the now-instantiated WebDriver object, find the links (hopefully less than 100 of them), and go "fill in" the missing parameters in the pre-created test instances. Finally, when the MyTest instance's test() method gets called, if the parameters were not filled in, throw a SkipException to have that "extra" instance not do anything. A bit clunky, but working.
I'd downvote this answer based on the dirty feeling it gives me.
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.