I am new to Selenium and Arquillian framework. I am trying to implement Page Object Model. Webdriver browser capabilities are saved in arquillian xml file.
I am using TestNG and created the following classes:
public class Test{
#Drone
Webdriver driver;
#Page
Login login;
#Page
Home home;
public void createOrderTest(){
login.navigateURL();
login.setcredentials();
home.createOrder();
}
}
public class Login{
// Webelements needed in methods below are declared here
public void navigateURL(){
driver.get("//url/login.aspx");
}
public void setCredentials(){
// code to enter username, password and click login
Graphene.waitAjax().until().element(signIn).is().not().visible();
}
}
public class Home{
// Webelements needed in methods below are declared here
public void createOrder(){
// code to create order
}
}
Problem Statement:
I am not sure how to navigate between Login and Home pages in code. Once user logs in using Login page methods, how does Webdriver get to use Home page methods to continue the test ?
Error:
Test runs fine with navigateURL and setcredentials methods. However, test fails to access createOrder method as follows:
WARNING: Argument 1 for UpdateTestResultBeforeAfter.update is null. It won't be invoked.
FAILED CONFIGURATION: #BeforeMethod arquillianBeforeTest(public void Test.createOrder() throws javax.mail.MessagingException,java.io.IOException,java.security.GeneralSecurityException)
org.jboss.arquillian.graphene.enricher.exception.PageObjectInitializationException: Can not instantiate Page Object class Home
Please guide me. Thank you.
Is the home page a static page? I assume you should not redirect the login page to home page. This should be done by the application itself. That is, end user will access the login page with url. after the all the navigations should be done by the application itself.
#RunAsClient
public class Test extends Arquillian{
#Drone
Webdriver driver;
#Page
Login login;
#Page
Home home;
public void createOrderTest(){
login.navigateURL();
login.setcredentials();
//you do not need this
//home = Graphene.goTo(Home.class)
//use graphene fluent wait API to wait for the page load
home.createOrder();
}
}
Related
I have created a java/selenium/cucumber automation framework with 4 feature files each testing different functional area's.
I can run each of these within Eclipse as feature files and they all run fine.
However I am trying to figure out how I can run them all as a JUnit test so that I can generate the extent reports.
I run the mainRunner class as a Junit test like ..
The first feature runs fine but then the next three do not. A chrome browser is opened for each of these but
the site is not navigated to. The error
'org.openqa.selenium.NoSuchSessionException: Session ID is null. Using WebDriver after calling quit()?'
is shown in the console logs.
So is this issue to do with how I have set my feature files up to use the startBrowser, initBrowser and closeBrowser methods. Which are
defined in a seperate class 'BrowserInitTearDownStepDefinitions'?
All my feature files look like ..
Feature: Update a Computer in Database
-- left out details
#StartBrowser
Scenario: Start browser session
When I initialize driver
Then open browser
#MyTest4
Scenario Outline: Update a computer
-- left our details
Examples:
-- left out details
#CloseBrowser
Scenario: Close the browser
Then close browser
I have had a look at the other posts related to this message that reference the same error, but can't see a clear cut solution.
As the error would indicate I seem to be quitting the driver but then not reinitialising it for the next test. Although Im not sure why this
would be the case given that each feature file has the #StartBrowser and #CloseBrowser tags which should execute these methods. Below is my BrowserInitTearDownStepDefinitions class.
public class BrowserInitTearDownStepDefinitions {
//Initialises Chrome browser
#When("^I initialize driver$")
public void initializeDriver() {
System.out.println("initializeDriver runs");
System.setProperty("webdriver.chrome.driver","C:\\xxxx\\CucumberAutomationFramework\\src\\test\\java\\cucumberAutomationFramework\\resources\\chromedriver.exe");
WebDriverUtils.setDriver(new ChromeDriver());
}
//Opens Chrome browser and clicks in search input box
#Then("^open browser$")
public void openBrowser() {
System.out.println("Open Browser runs");
WebDriver driver = WebDriverUtils.getDriver();
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);
driver.manage().timeouts().setScriptTimeout(60, TimeUnit.SECONDS);
driver.get("https://computer-database.gatling.io/computers");
}
//Closes browser after all scenarios run and deletes cookies
#Then("^close browser$")
public void closeBrowser() {
System.out.println("Close Browser runs");
WebDriver driver = WebDriverUtils.getDriver();
driver.manage().deleteAllCookies();
driver.quit();
driver =null;
}
}
I create a new instance of the webdriver within my stepDefs file with ..
WebDriver driver = WebDriverUtils.getDriver()
The webdriver utils class code is ..
package cucumberAutomationFramework.utilityClasses;
import org.openqa.selenium.WebDriver;
public class WebDriverUtils {
private static WebDriver driver;
public static void setDriver(WebDriver webDdriver) {
if (driver == null) {
driver = webDdriver;
}
}
public static WebDriver getDriver() {
if (driver == null) {
throw new AssertionError("Driver is null. Initialize driver before calling this method.");
}
return driver;
}
}
Any advice would be much appreciated. Thanks.
My cucumber runner class cannot seem to find my step definition class, but it finds the feature file just fine.
Here is a snapshot of my very simple project structure:
Feature file:
Feature: Customer must be able to reach the Home Delivery page by clicking the Home Delivery button
Scenario: Test Home Delivery button
Given PS Restaurants web page is open
When User clicks on Home Delivery button
Then Home Delivery page should load
Step Definition class:
package stepDefinitions;
import java.util.concurrent.TimeUnit;
public class E_1_US_1 {
#Given("^PS Restaurants web page is open$")
public void ps_Restaurants_web_page_is_open() throws Exception {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^User clicks on Home Delivery button$")
public void user_clicks_on_Home_Delivery_button() throws Exception {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^Home Delivery page should load$")
public void home_Delivery_page_should_load() throws Exception {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
}
Runner class:
package runner;
import org.junit.runner.RunWith;
import cucumber.api.junit.Cucumber;
import cucumber.api.CucumberOptions;
#RunWith(Cucumber.class)
#CucumberOptions(
features= {"src/features/Feature_1_1.feature"},
glue= {"src/stepDefinitions/E_1_US_1.java"}
)
public class Runner {
}
The output from running the Runner class as a JUnit test:
1 Scenarios ([33m1 undefined[0m)
3 Steps ([33m3 undefined[0m)
0m0.040s
You can implement missing steps with the snippets below:
#Given("^PS Restaurants web page is open$")
public void ps_Restaurants_web_page_is_open() throws Exception {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^User clicks on Home Delivery button$")
public void user_clicks_on_Home_Delivery_button() throws Exception {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^Home Delivery page should load$")
public void home_Delivery_page_should_load() throws Exception {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
I just copied and pasted the output into my step definitions class and it still won't recognize the step definitions class. Earlier it was saying that there was no matching glue code for each step in the scenario, but that went away after I closed and reopened the feature file.
You can update your runner class as below:
package runner;
import org.junit.runner.RunWith;
import cucumber.api.junit.Cucumber;
import cucumber.api.CucumberOptions;
#RunWith(Cucumber.class)
#CucumberOptions(
features= {"src/features"}, //It will pick all the feature files located in this folder
glue= {"stepDefinitions"} //Only package name is required here.
)
public class Runner {
}
I've experience in Back-End automation testing, but I'm new to Front-End.
I've created BDD format tests for a website and now I want to automate it.
I decided to use Selenium + cucumber using Maven for desktop versions of website.
Now let's start:
For example my feature file looks something like this:
Feature: User change password page
Scenario: User doesn't provide passwords
Given user is logged in
And user is on change password page
When user clicks SAVE button
Then website should notify that password fields are mandatory
Scenario: User types wrong current password
Given user is logged in
And user is on change password page
When user provides invalid current password
And user clicks on save button
Then website should notify user that current password is invalid
At first I thought it would be good that I log in the system only for first scenario. (in this example in second scenario I already would be logged in).
But as I saw it's not good approach. So I open and close browser for each scenario using the code:
#Before
public void beforeScenario(){
driver.get("https://example.com");
}
#after
public void afterScenario(){
driver.close();
}
That's OK for me. But I don't want to create WebDriver for each scenario and I don't want to initialize my POM objects for each scenario.
Now my Before method looks like it:
WebDriver driver;
HomePage home;
LoginPage login;
RegistrationPage reg;
#Before
public void beforeScenario(){
driver = new ChromeDriver();
home = new HomePage();
login = new LoginPage();
reg = new RegistrationPage();
}
I want to initialize these objects before steps are run and use them in every step.
I research and found out that cucumber-JVM doesn't support #beforeAll hook.
Also I don't want to do some manipulation like:
if( firstTime) {
//initialise everythin
firstTime = false
} else {
//do nothing
}
How can I achieve that? Where can I initialize everything I want before my tests start?
I am testing Polarion application and after testing for couple of minutes session expires and login window pops up.
Session is expiring randomly hence I don't have any fixed point to stop and resume. My test case also starts failing as expected button is on the main window which become inactive after login window comes up.
My question is does Selenium provide any way to handle this scenario?
Using Selenium in Java/TestNg on Chrome.
You can try to use retryAnalyzer of TestNG
import org.testng.Assert;
import org.testng.annotations.Test;
public class Test001 {
#Test(retryAnalyzer = Tests.RetryAnalyzer.class)
public void Test1()
{
Assert.assertEquals(false, true);
}
#Test
public void Test2()
{
Assert.assertEquals(false, true);
}
}
The details you can find in below link :-
http://toolsqa.com/selenium-webdriver/retry-failed-tests-testng/
Just write a function in retry which check if the pop-up appear then it call your login function.
Dear friends and colleagues
Here is a wierd scenario or may be someone already facing this issue not sure but see for yourself.
Consider there are 5 fields initialized using PageFactory method. 3 fields are on login page which is already loaded in DOM and remaining 2(Home page after login) fields are not yet loaded in DOM.
Now when I start the login test from my machine remotely on some other client using grid, it works fine.
But when I start the test from another machine remotely on same client using grid does not work.
My toolset
Language binding => C# WebDriver 2.47.0, TestRunner => Gallio/mBUnit, Browser => Any(Chrome/FF), DotNet Grid Standalone Server 2.47.1
I have a Login function where all page elements are initialized through PageFactory method as given below
public LoginFunction(driver)
{
PageFactory.InitElements(driver, this);
}
Elements are declared as below
[FindsBy(How = How.CssSelector, Using = #"#UserName")]
[CacheLookup]
public IWebElement UserNameTextField { get; set; }
[FindsBy(How = How.CssSelector, Using = #"#Password")]
[CacheLookup]
public IWebElement PasswordTextField { get; set; }
[FindsBy(How = How.CssSelector, Using = #".span2>input")] //input[#value='Sign in']")]
[CacheLookup]
public IWebElement LoginButton { get; set; }
[FindsBy(How = How.XPath, Using = #"//h2[contains(text(),'Welcome, admin')]")]
[CacheLookup]
public IWebElement WelcomeFormMessageText { get; set; }
[FindsBy(How = How.Id, Using = #"tabslist")]
[CacheLookup]
public IWebElement MainTabsList { get; set; }
Now when the PageFactory.InitElements(driver, this); statement executes, the test fails while initializing WelcomeFormMessageText IWebElement which is actually not present in DOM. These elements are present on Home page after login is successful.
Now the question is the same test runs fine when I run it from my machine and fails when I run it from another machine :-(
Both the machine configs are same having identical OS, browser versions, bit systems etc.
I have tried to run the test on third machine and it fails there too. It only seems to run from my m/c.
Has anyone seen this issue? or have any clue?
Thanks in advance.
Running tests on a remote machine is usually slower than running it locally.
I think it is due to a delay after login to get to the home page on your remote machine and hence you are not able to see the elements on Homepage because HomePage is not loaded yet.
Try adding a wait after login and then access the elements on the HomePage, it should work.
You also need to re-initialize the PageFactory after login to get the newer elements on page.
Although, I highly recommend having separate PageFactory for Login and Home pages.