HtmlUnitDriver browser emulate mode - java

I have created a simple factory method that creates a HtmlUnitDriver in a specified mode. For example
public static HtmlUnitDriver createHtmlUnitDriver(String browserMode) {
switch(browserMode.toLowerCase()) {
case "chrome":
return new HtmlUnitDriver(DesiredCapabilities.chrome());
case "firefox":
return new HtmlUnitDriver(DesiredCapabilities.firefox());
case "ie":
case "internet explorer":
return new HtmlUnitDriver(DesiredCapabilities.internetExplorer());
case default:
return new HtmlUnitDriver(true);
}
}
I'd like to write a quick unit test of this method, but I can't see how to tell which "mode" the returned HtmlUnitDriver is in. How would I do this?

Using reflection, you can get the private field webClient
#Test
public void test() throws Exception {
WebDriver driver = new HtmlUnitDriver(BrowserVersion.CHROME);
WebClient webClient = (WebClient) get(driver, "webClient");
System.out.println(webClient.getBrowserVersion());
System.out.println(webClient.getBrowserVersion().isIE());
driver.close();
}
private static Object get(Object object, String field) throws Exception {
Field f = object.getClass().getDeclaredField(field);
f.setAccessible(true);
return f.get(object);
}

Related

Why is this class method returning 'null'?

I have a class in my Selenium framework that is responsible for getting a fresh driver object and passing it to the tests for use.
But for some reason, it's returning a null error and I can't figure out why.
Here is the class:
DriverManager
private WebDriver driver;
public WebDriver getDriver() {
WebDriverFactory factory = new WebDriverFactory();
driver = factory.CreateBrowser(CHOSEN_BROWSER);
return driver;
}
My Factory class:
public WebDriver CreateBrowser(BrowserType browser)
{
switch(browser) {
case Chrome:
return createChromeDriver();
case Firefox:
return createFirefoxDiver();
case InternetExplorer:
return createInternetExplorerDriver();
default:
System.out.println("Invalid browser type");
return null;
}
}
My tests where I am creating an instance of the DriverManager:
BaseTest:
public DriverManager driverManager;
public WebDriver driver;
#Before
public void CreateDriver()
{
driver = driverManager.getDriver();
Pages.init(driver);
Logging.info("TEST STARTING: " + name.getMethodName());
}
But as soon as it hits the first line in the CreateDriver method. I recieved a null pointer error and the tests fail with a NullPointerException.
I assume your driverManager attribute is null. That's why driver = driverManager.getDriver(); is causing a NPE.
I guess public DriverManager driverManager = new DriverManager(); would solve this already.

How to quit the page if i type hello world on google search using selenium?

Hi guys I want to quit the page afte I type "Hello World" in google search using firefox browser and selenium
WebDriver driver = null;
public static void main(String args[]) {
SimpleSelenium ss = new SimpleSelenium();
ss.openBrowser();
ss.getPage();
ss.quitPage();
}
private void openBrowser() {
System.setProperty("webdriver.gecko.driver", "C:/geckodriver.exe");
driver = new FirefoxDriver();
}
private void quitPage() {
driver.quit();
}
private void getPage() {
driver.get("http://www.google.com");
}
1) Create a Junit test class
2) Initialize the driver in your setup method like
ChromeDriver driver = new ChromeDriver();//Download chromeDriver.exe file and point to location where you have installed the like as you mentioned. `driver.System.setProperty("webdriver.gecko.driver", "C:/geckodriver.exe");`
3) Create a test method with your business logic to type hello world
3) Create After and Before Class annotations for the methods .In After class annotation method you can write driver.quit.
You can refer to following link for more clarity
https://www.guru99.com/selenium-tutorial.html
I am Added sample format which is written Using java and testNG..Here Every time First before method will run then 1st test case will execute then after method will work then again before method work then next test case......In this way you can manage your test case and it will also generate Report also.Here you will get better explanation.
public class GoogleTest {
FirefoxDriver driver;
#BeforeMethod
public void setUp1() throws Exception {
System.setProperty("webdriver.gecko.driver", "D:\\\\ToolsQA\\trunk\\Library\\drivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://www.google.com");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void GoogleInputField() throws InterruptedException {
System.out.println("Hello world");
System.out.println("Hello world");
//Write Your test case for test case 1
}
#Test
public void google suggestion() throws InterruptedException {
//Write Your test case for test case 1
}
#AfterMethod
public void getResult(ITestResult result) throws IOException {
driver.quit();
}
}
Dont forget to add Firefox driver on gecko.driver path
I am assuming that you want to open the browser using selenium, load google and then listen till you MANUALLY enter "hello world" in the input box. The method listenForHelloWorld() will do that.
public static void main(String args[]) {
SimpleSelenium ss = new SimpleSelenium();
ss.openBrowser();
ss.getPage();
ss.listenForHelloWorld();
ss.quitPage();
}
private void listenForHelloWorld() {
// Get the search field
WebElement searchField = driver.findElement(By.name("q"));
int count = 1;
while (count++ < 20) {
// if search field value is "hellwo world" break loop which will eventallu lead to `quit()` as it is the next method to exit.
if (searchField.getAttribute("value").equalsIgnoreCase("hello world")) {
break;
}
Thread.sleep(5000)
}
}
If you are asking how to enter "hello world" in browser automatically use below.
driver.findElement(By.name("q")).sendKeys("hello world");

Multiple Browser Profiles for Multiple (Concurrent) Test Execution?

Multiple Browser Profiles for Multiple (Concurrent) Test Execution?
Is this even possible?
For example I can execute two tests at the same time but when two tests open at the same time within the same browser they seem to share the same cookies.
Please find my main Browser factory class listed below, can anyone advise the best way to alter my code, or settings required which will enable me to meet my objective?
Thanks for your help
public class BrowserFactory implements ISuiteListener {
private static WebDriver webdriver;
public static WebDriver getDriver() throws Exception {
try {
Properties p = new Properties();
FileInputStream fi = new FileInputStream(Constant.CONFIG_PROPERTIES_DIRECTORY);
p.load(fi);
String browserName = p.getProperty("browser");
switch (browserName) {
//firefox setup
case "firefox":
if (null == webdriver) {
System.setProperty("webdriver.gecko.driver", Constant.GECKO_DRIVER_DIRECTORY);
webdriver = new FirefoxDriver();
}
break;
//chrome setup
case "chrome":
if (null == webdriver) {
System.setProperty("webdriver.chrome.driver", Constant.CHROME_DRIVER_DIRECTORY);
DesiredCapabilities caps = DesiredCapabilities.chrome();
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.BROWSER, Level.ALL);
caps.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
webdriver = new ChromeDriver(caps);
}
break;
//IE setup
case "ie":
if (null == webdriver) {
System.setProperty("webdriver.ie.driver", Constant.IE_DRIVER_DIRECTORY);
webdriver = new InternetExplorerDriver();
}
break;
}
} catch (Exception e) {
System.out.println("Unable to load browser! - Exception: " + e.getMessage());
}
return webdriver;
}
#AfterClass
public void quitDriver() throws Exception {
if (null != webdriver) {
getDriver().manage().deleteAllCookies();
webdriver.quit();
webdriver = null;
}
// Output the time when a test class has ended
String tempTimeEndClass = new SimpleDateFormat("hh.mm.ss").format(new Date());
System.out.println("\nTEST CLASS END TIME: " + tempTimeEndClass);
}
}
Yes, of course it is possible!
They share the same cookies because the instance of the WebDriver you are creating is static, trying removing the static modifier so on every launch of the webdriver you get a unique instance.
public webdriver driver; public WebDriver getDriver() throws Exception
{ }
If the above isn't enough and you want to do additional things with the profiles; just pass it as a parameter via xml or as a String var in the method:
currentProfile = "user-data-dir=/path/to/your/custom/profile";
ChromeOptions options = new ChromeOptions();
options.addArguments(currentProfile);
Again, careful here currentProfile needs to be an instance variable not a static one!
Best of luck!

Selenium Webdriver TestNG tests are "overwriting" each other

I am trying to run Selenium Webdriver tests in parallel on a single machine, using TestNG. I have 3 #Test methods, where 3 different users log in to the same application and reach the home page. I need #Test methods to run in parallel, and write to an ExtentReports report.
My problem is, despite 3 completely different methods in different classes, one of the users will be logged into 2 out of 3 of the browsers, leaving a user out.
The login method is located in a PageFactory page object class.
Here are my 3 test methods:
#Test(enabled = true, priority = 0)
public void JohnLogin() throws Exception {
ExtentTest t = ClientReportFactory.getTest();
try {
Login objLogin = new Login(getDriver());
String username = "John";
String password = "Password";
objLogin.SignIn(username, password);
HomePage objHomePage = new HomePage(getDriver());
assertTrue(objHomePage.clientName.getText().c‌​ontains("John"));
} catch (Exception e) {
}
}
#Test(enabled = true, priority = 1)
public void BobLogin() throws Exception {
ExtentTest t = ClientReportFactory.getTest();
try {
Login objLogin = new Login(getDriver());
String username = "Bob";
String password = "Password";
objLogin.SignIn(username, password);
HomePage objHomePage = new HomePage(getDriver());
assertTrue(objHomePage.clientName.getText().c‌​ontains("Bob"));
} catch (Exception e) {
}
}
#Test(enabled = true, priority = 2)
public void SamLogin() throws Exception {
ExtentTest t = ClientReportFactory.getTest();
try {
Login objLogin = new Login(getDriver());
String username = "Sam";
String password = "Password";
objLogin.SignIn(username, password);
HomePage objHomePage = new HomePage(getDriver());
assertTrue(objHomePage.clientName.getText().c‌​ontains("Sam"));
} catch (Exception e) {
}
}
So, if I pause the tests on the Homepage. I will have 2 browser windows opened as "John", one "Bob" and no "Sam"... Causing failures.
Here's the PageFactory Object's login method.
public void SignIn(String strUsername, String strPassword) throws InterruptedException {
WebDriverWait wait = new WebDriverWait(driver, 15);
username.clear();
username.sendKeys(strUsername);
password.clear();
password.sendKeys(strPassword);
submit.click();
wait.until(ExpectedConditions.visibilityOf(homePagePanel));
}
At first I was sure the problem was in the #BeforeMethod threading (As in, the tests were in a different thread than the #Before and #After). But I don't see how that could be the case. The Base Test method successfully opens and closes 3 browsers. It just seems like the #Test methods use each other's data! But just in case, here's my #Before and #After, with my Threading code.
public class BaseTest {
public String browser;
private ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();
#BeforeMethod(alwaysRun = true)
#Parameters({ "browser"})
public void setup(String browser)throws MalformedURLException,
InterruptedException {
WebDriver driver = null;
if (browser.equalsIgnoreCase("Internet Explorer")) {
System.setProperty("webdriver.ie.driver", "C:\\Selenium\\IEDriverServer.exe");
driver = new InternetExplorerDriver();
} else if (browser.equalsIgnoreCase("Firefox")) {
System.setProperty("webdriver.gecko.driver", "C:\\Selenium\\geckodriver.exe");
driver = new FirefoxDriver();
} else if (browser.equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver", "C:\\Selenium\\chromedriver.exe");
driver = new ChromeDriver();
} else if (browser.equalsIgnoreCase("MicrosoftEdge")) {
System.setProperty("webdriver.edge.driver", "C:\\Selenium\\MicrosoftWebDriver.exe");
driver = new EdgeDriver();
}
setWebDriver(driver);
this.browser = browser;
ClientReportFactory.getTest(ExtentTestName, ExtentTestDescription);
baseURL = "testApp.com";
driver.get(baseURL);
driver.manage().window().maximize();
}
public WebDriver getDriver(){
return threadedDriver.get();
}
public void setWebDriver(WebDriver driver) {
threadedDriver.set(driver);
}
#AfterMethod
public void afterMethod() {
ClientReportFactory.closeTest(ExtentTestName, ExtentTestDescription);
getDriver().quit();
threadedDriver.set(null);
}
#AfterSuite
public void afterSuite() {
ClientReportFactory.closeReport();
if (getDriver() != null) {
getDriver().quit();
} else {
System.out.println("Drivers already closed");
}
}
Assuming that all of your #Test methods are in different classes, I am guessing that the problem is perhaps due to the fact that your ThreadLocal variable is NOT STATIC but is an instance variable. This causes the behaviour to be per thread per instance rather than the desired behaviour viz., per thread across all instances. You can refer to this StackOverFlow thread for a better explanation on this.
You would resort to using an instance variant of ThreadLocal if and only if all your #Test methods belong to the same test class (Because now you are only trying to ensure that the class level data member WebDriver is shared in a thread safe manner across all the test methods that belong to the same test class)
So if each of your #Test methods reside in its own Test class, then please try changing:
private ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();
to
private static ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();
You could try this.
public class DriverFactory(){
private static ThreadLocal<WebDriver> driverThread;
public WebDriver driver;
#Parameters("browser")
public WebDriver instantiateDriverObject(String browser) {
DriverFactory factory = new DriverFactory();
driver = factory.createInstance(browser); //Driver instantiation goes here
driverThread = new ThreadLocal<WebDriver>() {
#Override
protected WebDriver initialValue() {
webDriverPool.add(driver);
return driver;
}
};
return driver;
}
public WebDriver getDriver() {
return driverThread.get();
}
}

java factory pattern issue

I am using selenium webdriver for testing and want to give the opportunity to select which browser to run each set of tests in. I have used a factory to achieve this but for some reason I can't seem to get it working. Here is what I have
class WebDriverFactory {
private WebDriver driver;
private String baseUrl;
private StringBuffer verificationErrors = new StringBuffer();
private WebDriverFactory() {
}
public static void setChromePath() {
// Set file path here
}
public static void setIEPath() {
// Set file path here
}
public static WebDriver getWebDriver(String type) {
System.out.println("choose a browser:");
Scanner scan = new Scanner(System.in);
scan.next();
if (type.equalsIgnoreCase("chrome")) {
return createChrome();
} else if (type.equalsIgnoreCase("firefox")) {
return createFirefox();
} else if (type.equalsIgnoreCase("IE")) {
return createInternetExplorer();
} else {
return null;
}
}
private static WebDriver createChrome() {
System.setProperty("webdriver.chrome.driver", "C:/Program Files
(x86)/Google/Chrome/Application/chromedriver_win32_2.1/chromedriver.exe");
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
ChromeOptions chromeOptions = new ChromeOptions();
capabilities.setCapability("chrome.binary",
"C:/AppData/Local/Google/Chrome/Application/chrome.exe");
WebDriver driver = new ChromeDriver(capabilities);
return driver;
}
private static WebDriver createFirefox() {
WebDriver driver = new FirefoxDriver();
return driver;
}
private static WebDriver createInternetExplorer() {
File file = new File("C:/Utils/IEDriverServer_Win32_2.33.0/IEDriverServer.exe");
System.setProperty("webdriver.ie.driver", file.getAbsolutePath());
WebDriver driver = new InternetExplorerDriver();
return driver;
}
}
And in the test class I have:
String type = null;
WebDriverFactory.getWebDriver(type);
When I enter a string the scanner doesn't seem to do anything and the browser doesn't open? Could anyone help me out?
I now have this in the test class:
System.out.println("choose a browser:");
Scanner scan = new Scanner(System.in);
String type = scan.next();
WebDriverFactory.getWebDriver(type);
As Jayan mentioned, you should have got a NPE since you are passing null to the getWebDriver method. However, keeping that aside, in your code, you are reading a string using scan.next() statement, but you haven't assigned the read value to the variable type.
Saying that, your statement should be as below:
Scanner scan = new Scanner(System.in);
type = scan.next();
Apart from that, I don't see any use of passing type variable to the getWebDriver method, as you are anyhow, taking the input from user for type in getWebDriver method.
You should first correct the method getWebDriver(type) so it doesn't return null always! And then see where you go. As Mubin suggested, you could let go of the input parameter type if you are going to read the input inside the method. However, Based on the discussion in comments to this answer here's how the method getWebDriver(type) should look like:
public static WebDriver getWebDriver(String type) {
if (type.equalsIgnoreCase("chrome")) {
return createChrome();
} else if (type.equalsIgnoreCase("firefox")) {
return createFirefox();
} else if (type.equalsIgnoreCase("IE")) {
return createInternetExplorer();
} else {
return null;
}
}
OP was passing null to this method in the test implementation, and also not assigning the value read by Scanner. It isn't clear what the OP was expecting. As Jayan mentioned, we should get an NullPointerException.

Categories

Resources