Hi I have following setup with my current framework,
ClassA
{
//Which Receives Selenium WebDriver call the 'driver' object reference to manipulate the locators in UI
public WebDriver get()
{
return MainClass.driver;
}
}
MainClass
{
public static Webdriver driver;
method A()
{
//which uses Firefox instance and it is passed to ClassA to operate
driver = new FirefoxDriver();
}
methodB()
{
//which creates new instance of Chrome
driver = new ChromeDriver();
}
}
What I wanted to do is once I call methodB() the instance of Chrome is created but once it is done I want to resume back to firefox instance that is available or invoked before chrome run, but with my approach since I am referring the same webdriver object the old firefox reference is getting deleted.
Any Suggestions ?
PS: Please forgive my bad code conventions I followed
Simplest solution would be to create seperate objects for FF and Chrome. Modify get method to take a parameter(browserType) and then return the correspoding object.
Why are you switching browsers?
You might want to see a different approach to your situation. I believe that if you have to use 2 browsers you are most likely trying to pass some info from one to the other. Here is how I see it:
ClassA
{
//Which Receives Selenium WebDriver call the 'driver' object reference to manipulate the locators in UI
public WebDriver get()
{
return MainClass.driver;
}
}
MainClass
{
public static Webdriver currentBrowser, firefoxInstance chromeInstance;
firefoxInstance = new FirefoxDriver();
chromeInstance= new ChromeDriver();
currentBrowser = firefoxInstance; //if you want start out with Firefox
currentBrowser()
{
return currentBrowser;
}
switchBrowser(Cookies passingInfo) //passingInfo could be like cookies but also just current page etc...
{
if(currentBrowser==firefoxInstance)
{
chromeInstance.cookies()=passingInfo; // this is definitely not the correct way of passing cookies in Selenium but you get my point
currentBrowser=chromeInstance;
}
else
{
firefoxInstance.cookies()=passingInfo;
currentBrowser=firefoxInstance;
}
}
}
Of course there are more than one way of doing this and it depends on what you end goal is. But keep in mind that some websites are designed differently depending on the user agent of the browser connecting to them and that might cause your code to crash (like i just experienced 2 minutes ago.) I recommend sticking to one web browser if you can.
PS: Please forgive me using your bad code conventions :)
Related
How to initialize the driver so it can be used by all classes
Hi All,
I am writing a test automation framework in JAVA using Appium, Selenium and Cucumber.
I start off by declaring an Appium Driver in one of my test step files and then this gets cast to an Android Driver or iOS Driver depending on the app under test.
I need some help please - I need all of my class files to have access to this instance of the driver but I’m not sure how to do this. The test is driven from the feature file and some of the test steps are in different class files so how can they all access this instance of the driver?
Thanks
Matt
You can make an initialising method in the class where all the other config setup can be done and then you can make an instance of that class to call the getDriver method.
For example:
public class initialiseDriver{
private static AppiumDriver<MobileElement> driver;
public AppiumDriver<MobileElement> getDriver() throws IOException {
if (PLATFORM_NAME.equals("Android")) {
// setup the android driver
} else if (PLATFORM_NAME.equals("iOS")) {
// setup the ios driver
}
return driver;
}
}
You can just call this method where you want to use the driver. Ideally, you should initialise the driver by calling this method in the #BeforeSuite/#BeforeClass method, so that you don't need to call this method everytime you start your script as it would be called implicitly with the #BeforeSuite/#BeforeClass.
you can define your AppiumDriver as static
public class AppiumHelper(){
public static AppiumDriver<MobileElement> driver;
public void setupDriver(){
//define your DesiredCapabilities
//initialize your driver
}
Then you can use your driver in your test method like
public void test1(){
MobileElement element= AppiumHelper.driver.findElementById("elements id");
}
The serenity PageObject class provides an inbuilt getDriver() method which you can call wherever you want to initialize the driver(preferably in the test classes). Avoid trying to initialize the driver in any of your step definations/step libraries(Managing using #Managed annotation) else it will throw a :
null pointer exception.
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 have Selenium IE driver, coding in Java. This Webapp is only compatible with IE9. I have to use SSL trust certificate and then Autoit_script to Bypass these Cert popups in IE9.
I would like to find a solution where I do not have to repeat this code with each new Testcase/class. The IE9 gets so slow that the first Testcase does not finish executing, the second browser instance opens.
Is there a way to have this code placed in a way so I do not have to repeat it with each test?
Here is the Code, just Logon to Web application:
public class LoginACMSbutton {
private static WebDriver driver;
private String baseUrl;
#Before
public void setUp ()throws Exception {
DesiredCapabilities ieCapabilities = DesiredCapabilities.internetExplorer();
driver = new InternetExplorerDriver(ieCapabilities);
System.setProperty("webdriver.ie.driver","C:\\IEDriverServer.exe");
baseUrl =("https://My website Link/");
}
#Test
public void LogintoWeb() throws Exception {
driver.get(baseUrl);
Runtime.getRuntime().exec("C:\\Autoitscripts\\IElogin.exe");
try {
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.alertIsPresent());
Alert alert = driver.switchTo().alert();
alert.accept();
} catch (Exception e) {
System.out.println("show error");
} //handle the popup
}
#After
public void End() throws Exception {
driver.close();
}
}
At this time, I am just adding new Test info in #Test section, which is not smart way to do. :)
Please advise. Thanks in advance!
I'd suggest you to have a separate singleton class "Browser" or "Driver" to manage and handle the browser. you can call this class either in your page object or your tests(which would be hard to maintain). Another suggestion is to have a page object your login page that would have a method to log you in the system, you can call that in the test (create as many different logins as you need). Generally is not a good idea to mock-up login by storing a session or some quick and dirty hack, that's why I won't recommend it. Here's some info link. Hope it helps.
I have created PageObjects Package.
Then Created Java class and a method name "DriverLogin", in this method I have added client certificate info, site URL with IE capabilities etc.
Then I have called this method in Main Java class/PageObjects.
I have created Junit Framwork and extends each Junit Test class with PageObjects java Method. I dont have to copy and paste the same code over and over again. ppphhheewwww!
It works for me like a charm. No issues. Thank you all for your support and feedback. !!
I am fairly new to Java so forgive me if this is a silly question, but believe me when I say I really cannot find a solid answer.
This is what I'm working with:
So I'm testing a program, and the easiest way to keep it maintained and updated is to create my own library of "buttons". Everything in the library are small functions like "enterValidCredentials" and "clickLoginButton".
So let's take a look at my test cases. In a perfect world I'd be able to just:
public class progressCheck {
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
driver.get("http://mail.google.com/");
enterValidCredentials;
clickLoginButton;
}
}
enterValidCredentials and clickLoginButton exist in my library of classes. I know very well that that's not going to work as written above. What, literally, is the correct way to do this?
If it helps at all, my enterValidCredentials class looks like this:
public class loginPageButtons {
private WebDriver driver;
Actions actions = new Actions(driver);
public class enterValidCredentials { // This class enters in a valid username and valid password on the login page.
public void enterValidCredentials2() {
driver.findElement(By.cssSelector("input[type=\"text\"]")).clear();
driver.findElement(By.cssSelector("input[type=\"text\"]")).sendKeys("XXXXXXXX");
driver.findElement(By.cssSelector("input[type=\"password\"]")).clear();
driver.findElement(By.cssSelector("input[type=\"password\"]")).sendKeys("XXXXXXXX");
}
}
All my other functions follow a relatively similar structure (depending on their function, of course).
You can use a unit test to check single functionalities of your classes.
The most used library to create unit tests is JUnit.
If you use an ide (like IntelliJ or Eclipse) running the test can be done with a simple command exactly as running a main method.
If you need to create mocks of your objects you can use a library like Mockito (but there are many other valid alternatives).
Note: A mock is an object that has the same interface as a complex object that is difficult to use in a test environment (for example a db connection, a file handler, a network handler).
Here is an example, I tried to imagine your code and a possible test. I assumed that clickLoginButton returns an integer just to show a possible assert statement.
Example:
#Test
public static void testCredentials() {
WebDriver driver = new FirefoxDriver();
driver.get("http://mail.google.com/");
EnterValidCredentials enterValidCredentials = new EnterValidCredentials(); // Or create a mock if necessary
// Set values if necessary
int returnValue = enterValidCredentials.clickLoginButton();
assertEquals(returnValue, 1);
}
With WebDriver and PageFactory, using Java we are implementing a new automation project, and we've been experimenting with various ways of having PageObjects created. We're torn on a few different ideas, and want to make sure we don't work ourselves into a corner.
Is it best to, as documented in the WebDriver documentation, provide an initialized WebDriver to a PageFactory, along with the class template to create a new PageObject?
driver.get(URL);
PageObject page = PageFactory.initElements(driver, PageObject.class);
// elsewhere
class PageObject {
private WebDriver driver;
public PageObject(WebDriver driver) {
this.driver = driver;
this.validateUrl();
}
public void validateUrl() throws Exception {
if (!driver.getUrl().equals(url)) {
throw new Exception("URL not valid");
}
}
}
However, since the PageObject knows a lot about itself, such as perhaps its URL, can we not have the Page Object do the work?
PageObject page = new PageObject(driver);
page.goToUrl();
// elsewhere
class PageObject {
private WebDriver driver;
private String url;
public PageObject(WebDriver driver) {
PageFactory.initElements(driver, this);
}
public void goToUrl() {
driver.get(url);
}
}
I suppose I don't see much of an advantage to having the PageFactory do the instantiation versus just initialization, however I don't want to stray from the standards setup by the architects if there's a reason for it.
Thanks
One of the advantage of Page Factory:
Scenario:
In your application, you are having 100 fields in a page. The same page is called for 50 times.
If this type of scenario is done by using Page Object means, it will find each element again and again. There may be a chance for degradation of the performance.
If the same scenario is done by using Page Factory means, it will find the elements only for the first time, and then it will take from the cache. By this the performance is increased.
The best way is to let the frameworks like Geb and Thucydides abstract out the PageObjects and their initialization. I have been using Geb + Spock BDD combination for this and the results so far has been excellent.