I am trying to write a simple fixture that opens the browser and navigates to www.google.com. When I run the wiki page, it passes with all green, but the browser never opens up (I don't think the method even gets called by the wiki). Can someone take a look at my fixture and wiki to see what I am doing wrong? Many thanks in advance,
Here is the Wiki -
!|SeleniumFitness|
|URL |navigateToSite?|
|http://www.google.com| |
After Running -
!|SeleniumFitnesse| java.lang.NoSuchMethodError: org.openqa.selenium.remote.service.DriverCommandExecutor.<init>(Lorg/openqa/selenium/remote/service/DriverService;Ljava/util/Map;)V
|URL |The instance decisionTable_4.setURL. does not exist|navigateToSite?
|http://www.google.com|!The instance decisionTable_4.navigateToSite. does not exist |
Here is the Fixture -
package FitNesseConcept.fitNesse;
import java.util.Properties;
import org.junit.BeforeClass;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeMethod;
//import com.google.common.base.Preconditions.*;
//import com.google.common.collect.Lists;
import fit.ColumnFixture;
public class SeleniumFitnesse extends ColumnFixture {
public static ChromeDriver driver = null;
private String navigateToSite = "";
public String URL = "";
public SeleniumFitnesse() {
Properties props = System.getProperties();
props.setProperty("webdriver.chrome.driver", "/home/ninad/eclipse-workspace/chromedriver");
driver = new ChromeDriver();
}
// SET-GET Methods
public String getURL() {
return URL;
}
public void setURL(String uRL) {
URL = uRL;
}
public String getNavigateToSite() {
return navigateToSite;
}
public void setNavigateToSite(String navigateToSite) {
this.navigateToSite = navigateToSite;
}
// Navigate to URL
public void navigateToSite() throws Throwable {
System.out.println("Navigating to Website");
try {
driver.navigate().to(URL);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
You are getting some good recommendations as comments - but to answer your question directly, for an old-style ColumnFixture, which is what you have written, the method "navigateToSite" is indeed not going to be called.
These styles of fixtures are not often used anymore, Slim is preferred, and your fitnesse instance in its documentation will show you how to use Slim style. However, for a column fixture as you have written, if you want a method to be called it needs to be a "?" following name of the method in the header row.
See basic docs for column fixture:
http://fitnesse.org/FitNesse.UserGuide.FixtureGallery.BasicFitFixtures.ColumnFixture
You are mis-using column fixture, even granted the old style though. Column fixture's pattern is "here is a series of columns that represent inputs, now here is a method call I want to make to get the output and check result". Navigating a website does not often fit that pattern. In old style fitnesse it would probably be approached by an ActionFixture:
http://fitnesse.org/FitNesse.UserGuide.FixtureGallery.BasicFitFixtures.ActionFixture
In the newer Slim style, a good fit for navigation and checking where you are would be a Scenario Table.
http://www.fitnesse.org/FitNesse.UserGuide.WritingAcceptanceTests.SliM.ScenarioTable
In general doing WebDriver / Selenium tests through a wiki is worth extra thought as to whether it's your best medium. Fitnesse is really designed to be a collaborative tool for documenting and verifying business requirements, directly against source code.
Here's an example of how to do with a ColumnFixture, although again ColumnFixture not exactly appropriate:
|url|navigateToUrl?|
|www.google.com| |
java class:
public String url;
public void navigateToUrl() {
}
You could return an "OK" if it navigates alright, or return the title of the page as opposed to void if you wanted.
Related
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 a newbie in automation testing, and m really confused about assert and verify.Since, I am using TestNG, according to my research I came to know that in webdriver, we dont have verify, we have hard and soft assertion. But when I search for it, I get all mixed answers. and nowhere can I find a detailed example.
For soft assertion I saw someone using 'customverification' but when I try to write that in my program I get error, asking to create a class or interface.
Can someone please help me in this. I am studying through internet so its really hard to get correct answers.
Thanks
package revision;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.Test;
public class Six {
WebDriver driver=new FirefoxDriver();
#Test
public void SandyOne() {
driver.get("file:///C:/Users/Sandeep%20S/Desktop/Test.html");
Assert.assertTrue(IsElementPresent(By.xpath("//input[#id='custom']")), "tab was missing");
driver.findElement(By.xpath("//input[#id='custom']")).sendKeys("abcd");
System.out.println("1st program");
System.out.println("blah 1");
System.out.println("blah 2");
}
public boolean IsElementPresent(By by) {
try {
driver.findElements(by);
return true;
} catch (org.openqa.selenium.NoSuchElementException e) {
return false;
}
}
}
If you have an assert that fails the test will be stopped, where for verify the test will be continued and the error will be logged.
Ideally you will have only one assert per test (e.g. the correct page has loaded) and verify will be used to check the information on that page in this case.
Therefore, if the correct page was not loaded, there is no point in checking the stuff on the page is correct.
You can get an idea and a visual example here.
Your test probably fails here:
Assert.assertTrue(IsElementPresent(By.xpath("//input[#id='custom']")), "tab was missing");
because IsElementPresent returns false. One way to avoid that would be:
try {
Assert.assertTrue(IsElementPresent(By.xpath("//input[#id='custom']")), "tab was missing");
driver.findElement(By.xpath("//input[#id='custom']")).sendKeys("abcd");
}
catch (AssertionError ae) {
//ignore
}
However, catching errors is quite ugly code. A better way would be to use WebDriver.findElements(By by) and check if the resulting list is empty or not.
Hard Assertions:Test execution stops as soon as assertion failure found.
Soft Assertions:Test execution continues even if assertion failure found.
e.g. You have 3 assert statements Assert1,Assert2,Assert3
Now if Assert2 fails in case of hard assertion the test will terminate.
In case of soft assertion it will move to next steps in test and then terminate.
You need to instantiate soft assertion as:
SoftAssertions softAssertion = new SoftAssertions();
softAssertion.assertTrue(condition,message)
In your given code snippet hard assertion makes sense since you cannot move to next step to send text until the input box is found.
In given example you don't need to assert element presence. If it's missing the findElement method will throw an error and you will know that it's not there.
If you have elements's Id, use it instead of xpath. This will make the code more readable and faster:
driver.findElement(By.Id("custom")).sendKeys("abcd");
Instead of directly calling the findElement method, it's recommended to use the PageObject pattern and pick elements with annotations, see PageFactory:
public class TestPage {
#FindBy(id = "custom")
WebElement custom;
private WebDriver driver;
public TestPage (WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public TestPage inputCustom(String txt) {
custom.sendKeys(txt);
return this;
}
}
#Test
public void SandyOne() {
// ...
TestPage page = new TestPage(driver);
page.inputCustom("abcd");
// ...
}
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
How to make the WebDriver wait until the page loading stops completely.
Means, it waits and checks whether entire page has been loaded or not, then only it proceeds with the next line execution.
The biggest problem is that there is no generic, one-size-fits-all solution that will work for even a majority of users. The concept of "when is my page finished loading" is rendered nearly meaningless in today's dynamic, AJAX-heavy, JavaScript-dependent web. One can wait for the browser to determine network traffic is complete, but that doesn't take JavaScript execution into account. One could define "complete" as the page's onload event having fired, but that overlooks the possibility of the page using setTimeout(). Furthermore, none of these definitions take frames or iframes into account.
When it comes to Selenium, there are a couple of factors to consider. Remember that the Selenium RC API is 10 years old. When it was designed and developed, the architecture of typical web pages made a method like waitForPageToLoad practical. The WebDriver API, on the other hand, recognizes the current reality. Individual driver implementations usually will try to wait for a page load during an explicit page navigation (e.g., driver.get()), but this wait will be a "best effort", and is not a guarantee. Please note that navigation caused by user interaction (e.g., element.click()) will be less likely to fully wait, because such interactions are asynchronous, and thus inherently have race conditions.
The correct approach for WebDriver is to wait for the element you want to interact with to appear on the subsequent page. This is best accomplished with a WebDriverWait or a similar construct. You might find some of these other constructs in the support library, mainly in those dealing with the Page Object pattern. You could also try setting the implicit wait timeout in your driver instance, but I believe using it obscures intent.
That's actually the default behavior of Selenium - it waits until all requests are complete before going on to the next line of code.
There is a design pattern provided through the Selenium support library SlowLoadableComponent that would do what you want: https://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/support/ui/SlowLoadableComponent.html. The gist is that you write your page object to extend SlowLoadableComponent. You will have to provide implementations for two abstract methods in SlowLoadableComponent: load() and isLoaded()
TheisLoaded() method should check everything you need to consider your page 'loaded'. The load() method performs the actions necessary to load your page object. You specify a load timeout for your page object (I do this through the page object's constructor). When you invoke the get() method on your page object, which is inherited from SlowLoadableComponent, it will call isLoaded(). If your page object is not loaded, it will then call load() to load your page object. It will continue to do this until your page object is loaded or until your timeout expires.
You will have to define yourself what it means for your page object to be loaded, however. There is no out of the box way for Selenium to determine if your particular page object is loaded or not because these determinations are so context-sensitive. For example, consider a page object representing the login page for a web app. It is 'loaded' if the username and password entry text boxes and the submit login button are visible. This does not apply to a page object representing some other page in a web app. You have to custom tailor the 'is loaded' criteria for any given page object.
Here is a simple example. Basic abstract loadable object:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.SlowLoadableComponent;
import org.openqa.selenium.support.ui.SystemClock;
public abstract class AbstractLoadableComponent<T extends AbstractLoadableComponent<T>> extends SlowLoadableComponent<T> {
public static final int DEFAULT_TIMEOUT_IN_SECONDS = 30;
private final WebDriver driver;
private final int timeoutInSeconds;
public AbstractLoadableComponent(final WebDriver driver, final int timeoutInSeconds) {
super(new SystemClock(), timeoutInSeconds);
this.driver = driver;
this.timeoutInSeconds = timeoutInSeconds;
this.load();
}
public final WebDriver getDriver() {
return driver;
}
public final int getTimeoutInSeconds() {
return timeoutInSeconds;
}
#Override
protected void load() {
PageFactory.initElements(getDriver(), this);
}
}
Basic abstract page object:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.SlowLoadableComponent;
public abstract class AbstractPage<T extends AbstractPage<T>> extends AbstractLoadableComponent<T> {
private final String url;
public AbstractPage(final WebDriver driver) {
this(driver, driver.getCurrentUrl(), DEFAULT_TIMEOUT_IN_SECONDS);
}
public AbstractPage(final WebDriver driver, final String url) {
this(driver, url, DEFAULT_TIMEOUT_IN_SECONDS);
}
public AbstractPage(final WebDriver driver, final String url, final int timeoutInSeconds) {
super(driver, timeoutInSeconds);
this.url = url;
}
public final String getUrl() {
return url;
}
#Override
protected void load() {
super.load();
if(url != null) {
getDriver().get(url);
}
}
}
Basic concrete page object class for a login page:
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import static org.testng.Assert.assertTrue;
public final class LoginPage extends AbstractPage<LoginPage> {
#FindBy(how = How.ID, using = "username")
private WebElement usernameBox;
#FindBy(how = How.ID, using = "password")
private WebElement passwordBox;
#FindBy(how = How.NAME, using = "login")
private WebElement loginButton;
public LoginPage(final WebDriver driver) {
this(driver, driver.getCurrentUrl(), DEFAULT_TIMEOUT_IN_SECONDS);
}
public LoginPage(final WebDriver driver, final String url) {
this(driver, url, DEFAULT_TIMEOUT_IN_SECONDS);
}
public LoginPage(final WebDriver driver, final String url, final int timeoutInSeconds) {
super(driver, url, timeoutInSeconds);
}
#Override
protected final void isLoaded() throws Error {
try {
assertTrue(usernameBox.isDisplayed(), "Username text box is not displayed");
assertTrue(passwordBox.isDisplayed(), "Password text box is not displayed");
assertTrue(loginButton.isDisplayed(), "Login button is not displayed");
} catch(NoSuchElementException nsee) {
throw new Error(nsee);
}
}
}
driver.manage.implicitlywait(3, TimeUnit.Seconds) will hep.
I've got a bunch of test scripts written using Test::WWW::Selenium (but the fact that I used perl is inconsequential, any language selenium supports probably has the problem I describe). When the cogs in my application come loose I'd like to replay the test using the Selenium IDE, letting me have full control over the action
But I'm not sure how to go from my test script back into the selenium IDE, you can't paste perl into the IDE and have it transmogrify back to "HTML" (aka, internal selenium language, aka selenese). It was easy enough getting it out, alas.
The RemoteRunner has the command history in it, and I can copy and paste from this directly into selenium ide, and that would be great, but the history box will only hold 5 or 6 lines and clears itself! So it taunts me and is useless.
So how to log these more effectively? The logging options for the selenium rc (-browserSideLog, -log) don't seem to be helpful in this regard. I'm thinking of finding its RemoteRunner.html and hacking at it maybe so it won't clear that list, but is there another way?
It seems to be a not very common task but very interesting one. I do not think that there's some standard way so something has to be implemented.
I do not know Perl much and I use Java, so this is just a heads up:
I would extend the DefaultSelenium class for my tests that will use extended HttpCommandProcessor that will logs all commands performed:
import com.thoughtworks.selenium.HttpCommandProcessor;
public class ExtHttpCommandProcessor extends HttpCommandProcessor {
public ExtHttpCommandProcessor(String serverHost, int serverPort,
String browserStartCommand, String browserURL) {
super(serverHost, serverPort, browserStartCommand, browserURL);
}
public String doCommand(String commandName, String[] args) {
StringBuffer sb = new StringBuffer();
sb.append("|" + commandName + "|");
if (args!=null) {
for (String arg : args) {
sb.append(arg + "|");
}
if (args.length<2) {
sb.append(" |");
}
} else {
sb.append(" | |");
}
System.out.println(sb.toString());
// or log it where you want
return super.doCommand(commandName, args);
}
}
And
import com.thoughtworks.selenium.DefaultSelenium;
public class ExtSelenium extends DefaultSelenium {
public ExtSelenium(String serverHost, int serverPort,
String browserStartCommand, String browserURL) {
super(new ExtHttpCommandProcessor(serverHost, serverPort, browserStartCommand, browserURL));
}
}
Then I would extend SeleneseTestCase for use as the base in my tests:
import com.thoughtworks.selenium.SeleneseTestCase;
public class ExSeleneseTestCase extends SeleneseTestCase {
public void setUp(String url, String browserString) throws Exception {
int port = 4444;
if (url==null) {
url = "http://localhost:" + port;
}
selenium = new ExtSelenium("localhost", port, browserString, url);
selenium.start();
selenium.setContext(this.getClass().getSimpleName() + "." + getName());
}
}
The output of such test will look like:
|getNewBrowserSession|*iexplore|http://localhost:8080/|
|setContext|SimpleTest.testNew| |
|open|/webapp/test.html| |
|isTextPresent|Sample text| |
|click|sampleLink| |
|waitForPageToLoad|10000| |
|testComplete| | |
This solution will not log verifys and asserts so they may also be overrided in ExSeleneseTestCase to produce some trace.
You could also go the other way, which is probably easier: save the (partial) selenese HTML files when you generate them, and from the perl/java/... code, parse the files and execute the lines using doCommand. That way, you don't have to reconstruct the asserts/verify statements, because they weren't lost in the first place.