Can HTMLUnit package be used with PhantomJsDriver.java - phantomjs

I am using "org.openqa.selenium.phantomjs.PhantomJsDriver" Java class.
At times, I need to identify whether a given WebElement is a particular type of web element; eg: Is this webelement a input type element or not.
This does not seem to come with PhantomJsDriver package.
"com.gargoylesoftware.htmlunit." package seems to have useful wrappers on top of web elements. I can write code like "element instanceof HtmlInput".
Question here is
- Can I really HTMLunit package with phantomjsdriver ? Am I using two libraries which are not supposed to be used with one-another ?

No. Unfortunately, you can't do this the way you're doing it. PhantomJsDriver is backed by WebKit, while HtmlUnitDriver is backed by HtmlUnit which has its own browser core. Selenium is able to wrap both these (and some more) under one hood, but we can't use them interchangeably.
There are, however, different ways of doing what you're trying to do, the best probably being using Selenium's own methods getTagName() and getAttribute() if needed.
If you ran getTagName() on your input element, it would gladly return "input".

Related

Using different sets of page objects with the same selenium tests

[This is cross-posted with SQA - https://sqa.stackexchange.com/questions/35081/using-different-sets-of-page-objects-with-the-same-selenium-tests]
I'm working on a selenium test suite for a set of similar websites. The test suite would be execute separately for each site and the tests in the suite are applicable to all websites.
These websites are built on the same underlying platform, however have different theme/scheme and therefore page objects for these sites need to be different. This is not a case of one or two selectors being different, but majority of selectors different - yet the rest of the structure is the same.
I can easily create two (or three, or whatever) sets of page objects, however I can't figure out how to tell the test executor (Cucumber cli in my case) which page objects to use.
The closest I can come up with is use different package names with common base classes and then individual pages extending from the common base classes. Another possibility is to extract all the selectors into property files and load one or another based on an input parameter, however this would preclude me from using PageFactory. I can also, probably, create separate sets of page objects in different source sets and then compile one or the other based on my need - but, again, I can think of the theory, yet not the execution.
So, what's the right approach and how to achieve this? If it matters, the project is built using gradle.
Since the tests are suitable for all the sites I will assume the only difference between the pages is the selectors behind the objects.
cssSelector and xpath provides or. Assuming text field has ID id1, id2 or id3 depends on the page you can use
#FindBy(how = How.CSS, using = "#id1, #id2, #id3")
private WebElement textField;
This will return the WebElement matching one of the ids.
The solution turned out to be a custom ElementLocator and ElementLocatorFactory with a corresponding custom annotation. It's a bit more work, but it's a very clear solution. I published it on github. In short, the implementation allows to do this:
public class MyPage {
#SearchWith(page="MyPage", name="myElement", locatorsFile="{locators}")
WebElement someElement
...
}
Then run the whole test with -Dlocators=site1.json or -Dlocators=site2.json - and corresponding locators will be loaded from one or the other. It even allows to specify -Dlocators=[site3.json] and load locators from site3.json resource (as obtained using this.getClass().getResourceAsStream(locatorsFile))

Performance comparison of #FindBy() and driver.findElement()

I am using selenium framework to automate a web application wherein basically, driver.findElement() is commonly used. but I got the suggestion that #FindBy() works faster than driver.findElement(). suggest me which is better to use ?
When the code - PageFactory.initElements(....) is run it creates Proxy objects for all the fields which are annotated with #FindBy (or even #FindBys and #FindAll). So initially no searching of WebElements are performed.
Then if something like element.sendKeys(...) is run, the actual WebElement is searched using driver.findElement(...) before sendKeys() is run. Then if the same sendKeys() code is run the element is found again.
But if you add the CacheLookup annotation to the field then the second lookup is not performed but element is returned from the cache. So there is a performance gain. But the problem occurs in a javascript or ajax heavy page, stale element exception can show up.
For any non-trivial application testing use the PageObjectModel framework. Makes things organized and not littered with findElements and locators, even if you do not use the CacheLookUp annotation.

Two different syntax structure for Selenium

I'm using using AutoHotkey to drive SeleniumBasic v2.0.9.0
I'm new to Selenium and have been looking at a lot of different pages discussing how to get/set elements on a webpage. I've noticed there seems to be (at least )two different types of format for syntax.
Here are two examples:
1. driver.findElementByID("search_form_input_homepage").SendKeys("hello")
2. driver.findElement(By.id("search_form_input_homepage")).SendKeys("hello")
In my case the first one works but the second throws an error saying No such interface supported. I'm just curious of the origin of the second structure. Is it from Selenium 3?
Here is the Answer to your Question:
driver.findElementByID("search_form_input_homepage").SendKeys("hello") : Is in use through the VBA module maintained by #FlorentB.
driver.findElement(By.id("search_form_input_homepage")).SendKeys("hello") : Is in use through the Java bindings of Selenium.
Let me know if this Answers your Question.

What is the solution for this error in Junit 4.0? The error is "dom locators are not implemented yet"

I have generated the script using Selenium IDE. But not giving me proper output.
ERROR: Caught exception [Error: Dom locators are not implemented yet!]
ERROR: Caught exception [Error: Dom locators are not implemented yet!]
This gets displayed instead of the element code.
I have tried xpath locator. But its not working.
Read the error.
Dom locators are not implemented yet!
That could maybe, I'm not sure, mean, that the DOM locators are not implemented yet and you need to use another locator strategy. Look at all available locator strategies and pick one. The often used ones are id, name, css, xpath, ideally in this order (from weakest to strongest, but also from fastest to slowest).
By the way, Selenium RC has been oficially deprecated two years ago in favor of the new and shiny Selenium WebDriver. If you want to use something that's actually supported and developed, export your scripts to WebDriver.

Learning GEB and Spock

I am a manual tester trying to learn GEB and Spock. To learn these do I have to have prior knowledge of java or groovy? I have been reading the book of GEB, What are the prerequisites, books or learning resources? Please help. Thanks.
I tried compiling some essentials and some 'good-to-haves' that I found very helpful when I picked up Geb.
Some Groovy Magic. Most of all that you need to learn Groovy is covered in this manual but for obvious reasons if you get obsessed with the language you might want to consider Groovy in Action. While Java is not needed to pick up Groovy, If you are from a Java (except for closures) or even a Python background, you could probably skim through the tutorial for 15 minutes and you are there already).
A little Selenium. The more, the better but fear not, this single page tells you all that you need to know about the Selenium Webdriver that you would generally use. But to stress, the more the better.
jQuery selectors (everybody says that it is easy but frankly, I refer to the manual at least twice per hour. I am dumb, so…). If you are new to jQuery, you would want to start from basic selectors and click on the left navigation menu for more. Please note that not all jQuery selectors are applicable for Geb but the selectors section of Geb tutorial wasn't very exhaustive and engaging.
At the end of my testcases, I need to generate a fanciful report which stretches across multiple testcases and I had dependencies among testcases. So, I went for TestNG instead of Spock. Frankly, I didn't give Spock a lot of chance.
PageObjects is actually not a prerequisite for Geb but PageObjects are so awesome that you never wanted to think about Geb outside of it. PageObjects is a cute little pattern which says that you wrap the structure of your HTML page into an Object so that the actual test does not have to deal with it. Hah. Got you. Let me put that in plain English.
Say, you have a registration form with input textbox which has an id of "nametext". How would you get the handle of the textbox? In DOM terms, in javascript, you would just do a
document.getElementById("nametext")
In Selenium, you would do a very similar thing
driver.findElement(By.id("nametext"))
So, if you would want to populate Jason in your text box in Selenium, you would do a
driver.findElement(By.id("nametext")).sendKeys("Jason");
If you do that for all your input fields, very soon your testcases become ugly and hateful. Instead of that, in OO terms, you encapsulate. You create a new class, say RegistrationPage and wrap your findElement and sendKeys as in :
public class RegistrationPage{
…
public RegistrationPage fillRegistrationForm(String name, String email){
driver.findElement(By.id("nametext")).sendKeys(name);
driver.findElement(By.id("emailtext")).sendKeys(email);
}
}
and from your testcase, you would say
RegistrationPage regPage=new RegistrationPage();
regPage.fillRegistrationForm("Jason","jason#bourne.com");
(Even better idea is to wrap your input values into a class and pass it to the fillRegistrationForm)
In fact, Geb leverages PageObjects in a much better way - jQuery selectors to the rescue
class InputFormPage extends Page{
…
static content={
name {$("input", id:"entry_0")}
emailAddress {$("input", id:"entry_1")}
}
}
and in your testcase, you would just say
name.value ("Jason")
emailAddress.value ("jason#bourne.com")