Make use of a java object in Perl - java

Scenario :
there is a java class as given below :
public class TestSelenium {
public void googleTest() throws Exception {
WebDriver driver = new InternetExplorerDriver();
driver.get("http://www.google.com/webhp?complete=1&hl=en");
}
}
There is a perl program which makes use of Inline::Java module to call the googleTest of java class written above. Perl program looks like.
use warnings;
use Selenium::Remote::Driver;
use Inline Java => 'STUDY',
CLASSPATH => 'C:\selenium\selenium-java-2.37.0\selenium-2.37.0\libs\selenium-java-2.37.0.jar;C:\selenium\SeleniumTestPoc\bin\MyJar.jar;C:\selenium\selenium-java-2.37.0\selenium-2.37.0\libs\selenium-server-standalone-2.37.0.jar',
STUDY => ['TestSelenium'];
$test= TestSelenium->new;
$test->googleTest;
Now the above Perl code will open IExplorer and go to google.com page. In my Perl program further to $test->googleTest; I want to make use of same browser that was opened by java(WebDriver driver = new InternetExplorerDriver();) and perform a search for text "Cheese".
Question is, can the object of WebDriver class("driver" in this case) be further used in my Perl program so that I can use same browser and perform different UI operations on it in Perl?

I'm assuming that if you bring the WebDriver variable outside of the googleTest() method (making it available for all methods in the class) then you can write other methods in TestSelenium that reference the same WebDriver which you can then call in perl.
Modify TestSelenium to something like this:
public class TestSelenium {
private WebDriver driver = new InternetExplorerDriver();
public void googleTest() throws Exception {
driver.get("http://www.google.com/webhp?complete=1&hl=en");
}
public void searchForCheese() throws Exception {
// Your actions here can still reference the driver
}
}
And then after you call $test= TestSelenium->new;
Performing $test->googleTest; and $test->searchForCheese; should theoretically reference the same driver and in turn the same browser window.
EDIT :
If you want to pass the driver object back to perl try something like this.
Change the googleTest() java method to return the driver once it's done with the method (I will be using your original method but both should work):
public WebDriver googleTest() throws Exception {
WebDriver driver = new InternetExplorerDriver();
driver.get("http://www.google.com/webhp?complete=1&hl=en");
return driver;
}
And then I think you can hook onto the driver handle in perl via $mydriver= $test->goggleTest;
I assume you'll then be able to access the WebDriver hooks via $mydriver

Related

Appium on App Center can't switch between iOS and Android (Java)

When I write appium tests specifically to run on App Center (and therefore must use the custom 'Enhanced Driver'), it looks like I can only declare driver as either an EnhancedAndroidDriver type, or an EnhancedIOSDriver type.
public EnhancedAndroidDriver<MobileElement> driver;
// public EnhancedIOSDriver<MobileElement> driver; <----- can't declare same variable twice
public AppiumDriver<MobileElement> getDriver() throws IOException {
String PLATFORM_NAME = System.getenv("XTC_PLATFORM");
if (PLATFORM_NAME.equals("Android")) {
EnhancedAndroidDriver<MobileElement> androiddriver = Factory.createAndroidDriver(new URL("http://localhost:4723/wd/hub"), caps);
driver = androiddriver;
} else if (PLATFORM_NAME.equals("iOS")) {
EnhancedIOSDriver<MobileElement> iosdriver = Factory.createIOSDriver(new URL("http://localhost:4723/wd/hub"), caps);
driver = iosdriver; <---- compiler error, wrong type
}
return driver;
}
I want to run a simple test in a single file that will run on both platforms, but it seems I must choose either android or ios for that file to run on. How do I avoid duplicating all my test files? I am using react native and my app is basically identical on both platforms. I have done something similar with the regular AppiumDriver.
Any suggestions to programmatically switch which type 'EnhancedIOS/AndroidDriver' the variable driver refers to in Java??
With the regular AppiumDriver, I can do this:
private static AppiumDriver<MobileElement> driver;
public AppiumDriver<MobileElement> getDriver() throws IOException {
if (PLATFORM_NAME.equals("Android")) {
driver = new AndroidDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
} else if (PLATFORM_NAME.equals("iOS")) {
driver = new IOSDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
return driver;
}
And then use the driver in the tests generically. But it seems impossible to take this approach with the App Center Enhanced drivers because they don't share a common type (or I don't know enough about Java to figure it out). Is there any way to work around this??
I ended up writing an Interface that wrapped the driver, which instantiated and operated on the platform specific driver for each driver method I use, and allowed me to use the common name driver to refer to it throughout the rest of the test framework.
I passed in the platform name to the Interface when I instantiated the interface. The platform name was read as an environment variable I set in the App Center branch build settings.

Compile java code at runtime

I have a java class that is used to perform login action using selenium. There are currently 10+ different login types and as such there is a lot of if else involved which looks bad and is not efficient.
Eg:
if (logintype == 1 )
{
driver.findElement(By.id("username")).clear();
driver.findElement(By.id("username")).sendKeys(username);
driver.findElement(By.id("password")).clear();
driver.findElement(By.id("password")).sendKeys(password);
driver.findElement(By.id("signin")).click();
}
else if (logintype ==2 )
{
driver.findElement(By.id("username")).clear();
driver.findElement(By.id("username")).sendKeys(username);
driver.findElement(By.id("password")).clear();
driver.findElement(By.id("password")).sendKeys(password);
driver.findElement(By.id("signin")).click();
}
...........
...........
Other than code not being efficient the new code needs to be written, pushed and the server needs to be restarted every time a new login module is added.
I wanted to see if i can get the logic for login can be stored in db and if it can be compiled at runtime. I found groovy shell but i dont know how to get the results back to my class file. Also running groovy shell would require a lot of code changes. Is it possible in java
public class ExecuteAuth implements Runnable{
private WebDriver driver;
driver = new FirefoxDriver(firefoxBinary, profile, cap);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
//MongoDB code
DBCursor dbObjects = loginCollection.find();
while (dbObjects.hasNext()) {
DBObject dbObject = dbObjects.next();
loginModule.add(new LoginModule((BasicDBObject) dbObject));
String loginType = (String) dbObject.get("loginType")
String script;
if (loginType.equals("1")) {
script = (String) dbObject.get("script")
}
}
GroovyShell shell = new GroovyShell ();
shell.evaluate(script);
RUN REST OF THE LOGIN LOGIC AFTER THE CODE IS EVALUATED
}
I strongly advise against that approach. You are opening a door to bad code be injected in your application. Another way could be upload to your server your new jars and take advantage of class loader to load classes at runtime:
How should I load Jars dynamically at runtime?
Also, you have alternatives to avoid if-else's: usage of interfaces and factory methods are the way to go, imho. And put your login's implementations on different classes implementing a Login interface, for example.
Factory method design pattern:
http://www.oodesign.com/factory-method-pattern.html
http://www.javaworld.com/article/2077386/learn-java/factory-methods.html

Determine Type of Selenium Driver in Java

I'm working on building out a testing framework for some sites using selenium webdriver, and my goal is to have a number of drivers running the same tests concurrently (aka a firefoxdriver, an internetexplorerdriver, and a chromedriver all running at the same time with some shared resources). However, I'm having trouble with logging which driver is doing what. I'm passing the drivers through a lot of my code, but as far as I can tell a webdriver has no knowledge of what specific type of driver it is. Is there any way to ask a webdriver element what it was instantiated as?
You can use instanceof like
if( driver instanceof FirefoxDriver) {
System.out.println("Firefox it is!!");
}
else if( driver instanceof ChromeDriver) {
System.out.println("Chrome it is!!");
}
// and so on
For more details : What is the 'instanceof' operator used for?
/******************************************************************************************
* Name: getBrowserDetails | Description: Gets Browser Name and Version
******************************************************************************************/
public String getBrowserDetails() throws Exception {
Capabilities caps = ((RemoteWebDriver)BaseTest.driver).getCapabilities();
String browserName = caps.getBrowserName();
String browserVersion = caps.getVersion();
String browser = (browserName + " " + browserVersion).toUpperCase();
return browser;
}
If using instanceof, be sure to also consider org.openqa.selenium.WrapsDriver so as to handle EventFiringWebDriver.

How to pass the host name,username and password through command line arguments in junit?

I don't want to use system.getproperty or setproperty.I have a before method which fetches a URL
#Before
public void setUp( String baseUrl){
driver = new FirefoxDriver();
driver.get(baseUrl);
}
#test
public void logIn(){
driver.findElement(By.id("username")).sendKeys("admin");
driver.findElement(By.id("password")).sendKeys("xxx");
}
When I call the above Junit test case through:
D:\>java -cp D:\Jars\hamcrest-core-1.1.jar;D:\Jars\junit-4.11.jar;D:\Jars\POC_PR
OJECT.jar;D:\Jars\selenium-java-2.31.0.jar;D:\Jars\selenium-server-standalone-2.
31.0.jar **-Dbaseurl="https://gmail.com/"** org.junit.runner.JUnitCore POC.LogInTest
The browser opens but no URL is opened and fails by saying 1) logIn(POC.LogInTest)
java.lang.NullPointerException: null value in entry: url=null..
I tried writing the URL in #test also,but no use.
Could somebody tell me how the command line will know in junit on how the -DbaseUrl should get linked to baseUrl mentioned in #test or #before..
In simple words how to pass the url value to the junit code through cmd line.
Thx a ton in advance..
AFAIK you can't link baseUrl parameter with parameter passed in command line via the framework itself.
The thing you can do is to write custom AOP which will intercept the call of setUp(String baseUrl) read baseUrl via System.getProperty("baseUrl") and pass it to method as parameter. But is it worth it?

How to test a web page using selenium through a desktop application?

I need to test a webpage via desktop application, I'm trying to use
the selenium IDE, I had sucess to create the test cases, but I'm not
able to execute them on java.
I've been looking for something helpful, but I can't find any help at all.
Thank you
A framework that has been created for just this cause, (it's in Java) can be downloaded here or you can check the project out from github here.
This project was designed to be very simple, yet very effective. This type of framework is a "free version" of my interpretation of a framework that I use every day in production-type environments.
There is a sample test that is enclosed in the project named SampleFunctionalTest.java. Assuming you follow the ReadMe to the T, you should have no problem getting started.
Here is what a test would look like in this framework.
#Config(url = "http://ddavison.github.io/tests/getting-started-with-selenium.htm", browser = Browser.FIREFOX) // You are able to specify a "base url" for your test, from which you will test. You may leave `browser` blank.
public class SampleFunctionalTest extends AutomationTest {
/**
* You are able to fire this test right up and see it in action. Right click the test() method, and click "Run As... jUnit test".
*
* The purpose of this is to show you how you can continue testing, just by taking the semi colon out, and continuing with your test.
*/
#Test
public void test() {
// click / validateAttribute
click(props.get("click"))
.validateAttribute(props.get("click"), "class", "success") // validate that the class indeed added.
// setText / validateText
.setText(By.id("setTextField"), "woot!")
.validateText(By.id("setTextField"), "woot!") // validates that it indeed set.
// check / uncheck
.check(By.id("checkbox"))
.validateChecked(By.id("checkbox")) // validate that it checked
.check(props.get("radio.2")) // remember that props come from <class name>.properties, and are always CSS selectors. (why use anything else, honestly.)
.validateUnchecked(props.get("radio.1")) // since radio 1 was selected by default, check the second one, then validate that the first radio is no longer checked.
// select from dropdowns.
.selectOptionByText(By.xpath("//select[#id='select']"), "Second") // just as a proof of concept that you can select on anything. But don't use xpath!!
.validateText(By.id("select"), "2") // validateText() will actually return the value="" attr of a dropdown, so that's why 2 works but "Second" will not.
.selectOptionByValue(By.cssSelector("select#select"), "3")
.validateText(props.get("select"), "3")
// frames
.switchToFrame("frame") // the id="frame"
.validatePresent(By.cssSelector("div#frame_content"))
// windows
.switchToWindow("Getting Started with Selenium") // switch back to the test window.
.click(By.linkText("Open a new tab / window"))
.waitForWindow("Google") // waits for the url. Can also be the you are expecting. :) (regex enabled too)
.setText(By.name("q"), "google!")
.closeWindow(); // we've closed google, and back on the getting started with selenium page.
}
}
You should create an instance of a WebDriver and call methods on the instance of that object.
An easy example is shown here: http://www.seleniumhq.org/docs/03_webdriver.jsp#introducing-the-selenium-webdriver-api-by-example
I hope you have created the script in webdriver.
Now in the script recorded by the selenium ide you have three methods called
setup, testSomeName and tearDown.
From the very basic: to run this script all you need to do is create a main method in the same class and in that you need to call these methods in the same order as specified above.
After that you just need to run that program.
Here is an example to make it more clear:
public class p_adjcb {
public void setUp() throws Exception {
}
public void testP_adjcb() throws Exception {
}
public void tearDown() throws Exception {
}
public static void main(String[] args) {
p_adjcb obj = new p_adjcb();
try {
obj.setUp();
obj.testP_adjcb();
obj.tearDown();
} catch (Exception ex) {
}
}
}
If you get any compiler error make sure you have downloaded the selenium-standalone-server.jar file and added it to your class path.
This is a very basic start. Later on you may need to use som framework like junit.
Hope it helps.

Categories