I'm trying to verify that a former colleague's old demo Selenium script still works, but have run into a curious error. The colleague is no longer around to consult, unfortunately. First, here's the script in question, which is supposed to drag and drop one element over another on a page:
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Supplier;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
public class DragNDrop {
#Test
public void testDragAndDropWithCheck() throws InterruptedException {
System.setProperty("webdriver.gecko.driver","D:\\WebDriver\\geckodriver.exe");
WebDriver driver=new FirefoxDriver();
driver.get("https://the-internet.herokuapp.com/drag_and_drop");
By css = By.cssSelector("div[id^=\"column-\"]");
WebDriverWait wait = new WebDriverWait(driver, 10);
Supplier<List<WebElement>> fetchComponents = () -> wait
.until(ExpectedConditions.presenceOfAllElementsLocatedBy(css));
/**
* Starting check for element position
*/
List<WebElement> startingCheck = fetchComponents.get();
Assert.assertEquals("Starting - Draggable number does not match!", 2, startingCheck.size());
Assert.assertEquals("Starting - A position does not match!", "A", startingCheck.get(0).getText());
Assert.assertEquals("Starting - B position does not match!", "B", startingCheck.get(1).getText());
int index = ThreadLocalRandom.current().nextInt(startingCheck.size());
WebElement from = startingCheck.get(index);
WebElement to = startingCheck.get(1 - index);
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript(
dndScript() + "simulateDragAndDrop(arguments[0], arguments[1])",
from,
to);
/**
* Ending check for element position
*/
List<WebElement> endingCheck = fetchComponents.get();
Assert.assertEquals("Ending - Draggable number does not match!", 2, endingCheck.size());
Assert.assertEquals("Ending - A position does not match!", "A", endingCheck.get(1).getText());
Assert.assertEquals("Ending - B position does not match!", "B", endingCheck.get(0).getText());
}
}
The problem is with this part:
jse.executeScript(
dndScript() + "simulateDragAndDrop(arguments[0], arguments[1])",
from,
to);
Eclipse highlighted dndScript() and threw the message:
The method dndScript() is undefined for the type DragNDrop
I first figured this was due to a missing import, so I got to googling, but I can't find any information on it. The most I could find was some references to something called "RichFaces", but I couldn't find any further clarification (may be my own fault -- I'm by no means a Selenium/Java expert).
Any idea on what the story is with this function and how to properly implement it in this script?
It is unlikely related to the missing import (probably the static one). Since this is just a method name there could be three cases:
This is a static method in scope of some different classand used to be imported with static import
This is the method that has to be implemented in the scope of your current class
This is the method that has to be implemented in scope of parent classes
The reason of you currently have is that the code of your current class changed since that time. You need to check revision history if you take this code from version control.
There are few possible stories which seem possible:
There was a method in scope of current class and then it was moved so some parent class. In some reason someone forgot to add extends keyword to current class.
There was a method in scope of parent class. After that someone decided to break relationship between the classes and forgot to move that method to your current class.
There was static method in some different class. It was imported to the current class as static import. Then someone loaded that class to IDE and didn't add that "different class" to project's class path. Then they applied "organize imports" feature which removed that broken import from your current class.
Related
I am using my implicit wait as below:
//import
import org.openqa.selenium.WebDriver;
//driver declaration
public static WebDriver driver = null;
//implicit wait
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
having error as below:
The method timeouts() is undefined for the type WebDriver.Options
Need help to resolve this.
Nice catch. Seems to me a Bug with Selenium JARS
Here is the Answer to your Question:
As of now your code have only 2 lines. The first line public static WebDriver driver = null; shows no error as you have imported org.openqa.selenium.WebDriver;
In the second line , you are providing Implicit Wait as in driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);. In this case the IDE on which you are working tries to resolve the method timeouts() from org.openqa.selenium.WebDriver which we have already imported. Hence no error should have been shown for timeouts() method.
Hence the following error is not justified:
The method timeouts() is undefined for the type WebDriver.Options
The error should have been shown for either implicitlyWait() method or parameter TimeUnit.
Now, the actual error is with the parameter TimeUnit which is passed within implicitlyWait() method. The IDE clearly suggests about importing java.util.concurrent.
Solution:
The solution is to import java.util.concurrent.TimeUnit; and your code will be error free as follows:
import java.util.concurrent.TimeUnit;
Let me know if this Answers your Question.
Recently I have started learning selenium and I have applied to the job.
They asked me to write code for CRUD operation for this website
http://computer-database.herokuapp.com/computers
I am pasting the code here.Although it was running fine on my machine and I used framework as well.
Can anyone help me what is not up to the mark because I have been asked to write down code for the second interview and I don't want to repeat my mistake.
Looking forward for your help.
public class Add {
public static WebDriver driver;
public static WebDriver getdriver(){
System.setProperty("webdriver.gecko.driver",
"/Users/sonali/Downloads/geckodriver");
driver = new FirefoxDriver();
return driver;
}
#Test(priority=1) //Create a computer
public static void create(){
driver=getdriver();
driver.get("http://computer-database.herokuapp.com/computers?f=ACE");
driver.manage().window().maximize();
driver.findElement(By.xpath(".//*[#id='add']")).click();
driver.findElement(By.xpath(".//*[#id='name']")).sendKeys("newtest");
driver.findElement(By.xpath(".//*[#id='introduced']")).sendKeys("2017-03-20");
driver.findElement(By.xpath(".//*[#id='discontinued']")).sendKeys("2017-03-29");
Select s= new Select(driver.findElement(By.id("company")));
s.selectByValue("2");
driver.findElement(By.xpath(".//*[#id='main']/form/div/input")).click();
driver.findElement(By.xpath(".//*[#id='main']/div[1]")).isDisplayed();
System.out.println("Creating data is working");
}
#Test(priority=2) //Search for a computer and check its available
public static void read(){
driver.findElement(By.xpath(".//*[#id='searchbox']")).sendKeys("newtest");
driver.findElement(By.xpath(".//*[#id='searchsubmit']")).click();
driver.findElement(By.linkText("newtest")).click();
System.out.println("Reading data is working");
}
#Test(priority=3) // Update a computer name and company
public static void update(){
driver.findElement(By.id("name")).sendKeys("one");
Select s= new Select(driver.findElement(By.id("company")));
s.selectByValue("5");
driver.findElement(By.xpath(".//*[#id='main']/form[1]/div/input")).click();
driver.findElement(By.xpath(".//*[#id='main']/div[1]")).isDisplayed();
System.out.println("Updating computer is working fine");
}
#Test(priority=4) // Deleting computer from the list
public static void delete(){
driver.findElement(By.xpath(".//*[#id='searchbox']")).sendKeys("newtestone");
driver.findElement(By.xpath(".//*[#id='searchsubmit']")).click();
driver.findElement(By.linkText("newtestone")).click();
driver.findElement(By.xpath(".//*[#id='main']/form[2]/input")).click();
driver.findElement(By.xpath(".//*[#id='main']/div[1]")).isDisplayed();
System.out.println("Deleting computer is working fine");
}
}
For the code to be actually useful, it needs to be :
Readable
Maintainable
Structured properly
Try developing a framework for the tests i.e.:
Separate the driver generation to a driver factory class.
Separate the selectors and the respective actions to some other functional or page based classes.
Use assertions to verify. (an exception not appearing does not mean the functionality is working)
e.g.
driver.findElement(By.xpath(".//*[#id='main']/div[1]")).isDisplayed();
It will not matter what it returns as the code does not do anything with it.
It should be -
Assert.assertTrue(driver.findElement(By.xpath(".//*[#id='main']/div[1]")).isDisplayed());
Or better yet-
Assert.assertTrue(updatePage.isupdateDisplayed());
Try putting comments in the code which might make it more easy to understand
Run tests through a runner / xml.
I agree with what #amita said in her answer.
There is a lot you can do to improve on your code but it will take a bit of study, so not sure if you'll be able to follow my advice in time but hopefully this will be helpful to further your understanding of test automation with Selenium WebDriver.
Learn about the Page Object Model design pattern. This is probably the most popular design pattern used with WebDriver. There are lots of free tutorials online but here's a good one to get you started.
Once you have a good idea of Page Object Model you can enhance it by learning about LoadableComponent. Again lots of free tutorials online, here's one I picked at random
You're using XPath extremely heavily. Make sure you understand the preferred hierarchy of locator methods and use them appropriately. ID should be your first preference. XPath and CSS you last resort. For example,
By.xpath(".//*[#id='add']") //Never use this
By.id("add") //When you could have just used the ID locator
Study how TestNG works, in particular Annotations like #BeforeTest,
#AfterTest, and so on. Your tests should be independent, so avoid setting them up in such a way that they require you to force their priority order. It's well documented here but again lots of tutorials online to help you through it.
There's more but if you get your head round all that you'll have a very good base from which to build further. I wish you all the best with your interview
Here is the Answer to your Question:
Considering it as a Interview Question and writing it at a Interview Venue, I think you have done a commendable work.
A few words about the solution:
As you integrated TestNG, apart from #Test Annotation consider using #BeforeTest and #AfterTest Annotation and Assert Class too.
Consider generating some log messages to the console which helps in debugging your own code.
Consider moving the WebDriver instance initialization within #BeforeTest annotation.
Consider starting your #Test with priority=0.
Your xpath like .//*[#id='add'] are not proper, consider using valid xpath e.g. //input[#id='name']
Induce proper ExplicitWait i.e. WebDriverWait while trying to search for elements on new webpages.
When perform some #Test try to validate the Result through Assert Class.
Consider adding the imports wisely.
Once you create a WebDriver instance consider releasing it after your #Test within #AfterTest Annotation.
Here is the minimal code to Create a Computer by the name Debanjan
package demo;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class Q44852473_GOOD_CODE_sonali_arjun
{
public static WebDriver driver;
String myname = "Debanjan";
#BeforeTest
public void initDriver()
{
System.out.println("=====Test Started=====");
System.setProperty("webdriver.gecko.driver", "C:/Utility/BrowserDrivers/geckodriver.exe");
System.out.println("=====Initializing Webdriver=====");
driver = new FirefoxDriver();
}
//Create a Computer
#Test(priority=0)
public void create()
{
driver.get("http://computer-database.herokuapp.com/computers");
driver.manage().window().maximize();
driver.findElement(By.id("add")).click();
WebDriverWait wait1 = new WebDriverWait (driver, 10);
WebElement name = wait1.until(ExpectedConditions.elementToBeClickable(By.xpath("//input[#id='name']")));
name.sendKeys(myname);
driver.findElement(By.xpath("//input[#id='introduced']")).sendKeys("2017-07-01");
driver.findElement(By.xpath("//input[#id='discontinued']")).sendKeys("2017-07-01");
Select select = new Select(driver.findElement(By.id("company")));
select.selectByValue("1");
driver.findElement(By.xpath("//input[#class='btn primary']")).click();
WebDriverWait wait2 = new WebDriverWait (driver, 10);
WebElement searchbox = wait2.until(ExpectedConditions.elementToBeClickable(By.xpath("//input[#id='searchbox']")));
WebElement add_success_ele = driver.findElement(By.xpath("//section[#id='main']/div[#class='alert-message warning']/strong"));
String success = add_success_ele.getText();
Assert.assertTrue(success.contains("Done"));
System.out.println("Computer "+myname+" - created Successfully");
}
#AfterTest
public void tearDown()
{
driver.quit();
System.out.println("=====Test Completed=====");
}
}
Enhancements:
This Solution can be modified by using other TestNG annotations documented here.
This Solution can be enhanced by implementing through POM (Page Object Model) documented here.
This Solution can be further enhanced by implementing POM through PageFactory documented here.
Let me know if this Answers your Question.
I am writing selenium program to Login to Gmail account.I have given username through source code and further step is click Next button.
package com.core.selenium;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class Gmaildemo {
public static void main(String args[]) {
System.setProperty("webdriver.chrome.driver", "D:\\REKHA\\SOFTWARES\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.gmail.com");
driver.findElement(By.name("identifier")).sendKeys("rekha.sompalli#gmail.com");
driver.findElement(By.className("RveJvd snByac")).click();
}
}
Getting below error.
Exception in thread "main" org.openqa.selenium.InvalidSelectorException: invalid selector: Compound class names not permitted
Getting below error.It is not able to recongnise Next button.
You are trying to click the <span> element, which is wrong. The span doesn't have the click functionality. aim for the div element with id identifierNext. try this: driver.findElement(By.id("identifierNext")).click();
Selenium doesn't allow compund class names in By.className. Even if it did, that particular name, "RveJvd snByac", is not unique on the webpage and may yield different result than expected.
I wrote the below code :
package LoginMercuryTour;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class LoginMercuryTour {
public static void main(String[] args) throws InterruptedException
{
WebDriver driver=new FirefoxDriver();
String baseUrl="http://newtours.demoaut.com/";
driver.get(baseUrl);
WebElement userName;
WebElement Password;
userName=driver.findElement(By.name("userName"));
Password=driver.findElement(By.name("password"));
userName.sendKeys("tutorial");
Password.sendKeys("tutorial");
driver.findElement(By.name("login")).click();
Thread.sleep(10000);
driver.findElement(By.cssSelector("input[value='oneway']")).click();
Select passengersCnt=new Select(driver.findElement(By.name("passCount")));
passengersCnt.selectByVisibleText("1");
Select Dep=new Select(driver.findElement(By.name("fromPort")));
Dep.selectByVisibleText("London");
}
}
this is ruuning fine without any error. But the click functionality is not working. the button is not getting clicked. While checking the javadoc it is showing
org.openqa.selenium.firefox.FirefoxDriver.FirefoxDriver()
Note: This element neither has attached source nor attached Javadoc and hence no Javadoc could be found.
Note: I am able to click the Login button.
But the second click is not working/
Please Help. I am a beginner to selenium Webdriver.
It's working just fine for me. The Thread.sleep() is not needed so I commented it out. I simplified a few things in your code but other than that, it's all the same. The sleep was 10s so maybe you didn't give it time to finish?
If you aren't going to reuse the username and password elements, there is no need to store them in variables so I removed the declaration and combine the sendKeys() call with the find. I changed the passenger count to 4 to make sure that part was working since the default is 1.
WebDriver driver = new FirefoxDriver();
String baseUrl = "http://newtours.demoaut.com/";
driver.get(baseUrl);
driver.findElement(By.name("userName")).sendKeys("tutorial");
driver.findElement(By.name("password")).sendKeys("tutorial");
driver.findElement(By.name("login")).click();
// Thread.sleep(10000);
driver.findElement(By.cssSelector("input[value='oneway']")).click();
Select passengersCnt = new Select(driver.findElement(By.name("passCount")));
passengersCnt.selectByVisibleText("4");
Select Dep = new Select(driver.findElement(By.name("fromPort")));
Dep.selectByVisibleText("London");
If you want to fix the no Javadoc error, mk08 provided that solution.
As selenium is distributed in form of JARs, you need to add explicitly a java doc location for it. Follow the instruction given in THIS blog (9th & 10th instruction). It should resolve the problem.
When I try to run my code, it only shows cucumber skeleton. I use a JUnit runner class as JUnit test suite.
Code is below for all three classes.
Feature is :
Feature: Check addition in Google calculator
In order to verify that google calculator work correctly
As a user of google
I should be able to get correct addition result
#Runme
Scenario: Addition
Given I open google
When I enter "2+2" in search textbox
Then I should get result as "4"
Selenium Class :
package cucumberTest;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class SeleniumTest {
private SeleniumTest()
{
}
private static WebDriver driver = null;
public static void seleniumTest() {
// Create a new instance of the Firefox driver
driver = new FirefoxDriver();
//Put a Implicit wait, this means that any search for elements on the page could take the time the implicit wait is set for before throwing exception
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
//Launch the Online Store Website
driver.get("http://www.store.demoqa.com");
// Find the element that's ID attribute is 'account'(My Account)
driver.findElement(By.xpath(".//*[#id='account']/a")).click();
// Find the element that's ID attribute is 'log' (Username)
// Enter Username on the element found by above desc.
driver.findElement(By.id("log")).sendKeys("testuser_1");
// Find the element that's ID attribute is 'pwd' (Password)
// Enter Password on the element found by the above desc.
driver.findElement(By.id("pwd")).sendKeys("Test#123");
// Now submit the form. WebDriver will find the form for us from the element
driver.findElement(By.id("login")).click();
// Print a Log In message to the screen
System.out.println("Login Successfully");
// Find the element that's ID attribute is 'account_logout' (Log Out)
driver.findElement (By.xpath(".//*[#id='account_logout']/a")).click();
// Print a Log In message to the screen
System.out.println("LogOut Successfully");
// Close the driver
driver.quit();
}
}
JUnit Class:
package cucumberTest;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
#RunWith(Cucumber.class)
//#CucumberOptions(
// features = "Feature/googleCalc.feature"
////,glue={"stepDefinition"}
// )
#CucumberOptions(
features = {"Feature/googleCalc.feature"},glue={"stepDefinition"},
plugin = {"pretty"},
tags = {"#Runme"}
)
public class TestRunner {
}
Step Definitions :
package stepDefination;
import java.util.concurrent.TimeUnit;
import org.junit.Assert;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.By;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import cucumberTest.SeleniumTest;
public class googleCalcStepDefinition {
#Given("^I open google$")
public void i_open_google() throws Throwable {
// Write code here that turns the phrase above into concrete actions
SeleniumTest.seleniumTest();
}
#When("^I enter \"(.*?)\" in search textbox$")
public void i_enter_in_search_textbox(String arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
SeleniumTest.seleniumTest();
}
#Then("^I should get result as \"(.*?)\"$")
public void i_should_get_result_as(String arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
SeleniumTest.seleniumTest();
}
}
Output shown is :
Feature: Check addition in Google calculator
In order to verify that google calculator work correctly
As a user of google
I should be able to get correct addition result
#Runme
Scenario: Addition [90m# Feature/googleCalc.feature:7[0m
[33mGiven [0m[33mI open google[0m
[33mWhen [0m[33mI enter "2+2" in search textbox[0m
[33mThen [0m[33mI should get result as "4"[0m
1 Scenarios ([33m1 undefined[0m)
3 Steps ([33m3 undefined[0m)
0m0.000s
You can implement missing steps with the snippets below:
#Given("^I open google$")
public void i_open_google() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^I enter \"(.*?)\" in search textbox$")
public void i_enter_in_search_textbox(String arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^I should get result as \"(.*?)\"$")
public void i_should_get_result_as(String arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
I found the reason it was not executing because i added Selenium test class and Junit runner class in Package cucumberTest; and skeleton was in package stepDefination; so what i did was i moved skeleton to pacakge cucumberTest; where junit runner and selenium classes are it resolved the issue for . Issue was occuring because when you place Junit class in package it will search for skeleton in that package but if you add JUnit runner class in source folder then it will be able to find the page under src folder