I'm trying to encapsulate a Selenium script by breaking it up into three classes (Grid, Browser, and testCase). I'm able to get the browser to open, but I seem to be missing the connection for the testCase class to interject its commands.
Grid.java
package com.autotrader.grid;
import org.junit.After;
import org.junit.Test;
public class Grid {
Browser browser = new Browser();
TestCase testCase = new TestCase();
public Grid() {
browser.setUp("http://pbskids.org");
}
#Test
public void main() {
testCase.runCase();
}
#After
public void tearDown() throws Exception {
browser.stop();
}
}
Browser.java
package com.autotrader.grid;
import com.thoughtworks.selenium.Selenium;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverBackedSelenium;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.util.concurrent.TimeUnit;
public class Browser {
private String baseUrl;
private String driverNamespace;
private String driverLocation;
private DesiredCapabilities capabilities;
private WebDriver driver;
public Selenium selenium;
// constructor
public Browser() {
}
public DesiredCapabilities getCapabilities() {
return this.capabilities;
}
public String getDriverLocation() {
return this.driverLocation;
}
public String getDriverNamespace() {
return this.driverNamespace;
}
public Selenium getSelenium(){
return selenium;
}
public void open (String url) {
this.selenium.open(url);
}
public void setBaseUrl(String url) {
this.baseUrl = url;
}
public void setCapabilities() {
this.capabilities = DesiredCapabilities.firefox();
this.driver = new FirefoxDriver(capabilities);
}
public void setDriverLocation(String location) {
this.driverLocation = location;
}
public void setDriverNamespace(String namespace) {
this.driverNamespace = namespace;
}
public void setSpeed(String speed){
this.selenium.setSpeed(speed);
}
public void setUp(String url){
setDriverNamespace("webdriver.firefox.driver");
setDriverLocation(System.getenv("ProgramFiles(x86)") + "\\Mozilla Firefox\\firefox.exe");
System.setProperty(driverNamespace,driverLocation);
setCapabilities();
setBaseUrl(url);
this.selenium = new WebDriverBackedSelenium(driver, url);
this.driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
public void stop(){
this.selenium.stop();
}
}
TestCase.java
package com.autotrader.grid;
import com.thoughtworks.selenium.Selenium;
public class TestCase {
Browser browser = new Browser();
Selenium selenium;
// constructor
public TestCase(){
selenium = browser.getSelenium();
}
public void runCase(){
selenium.open("/privacy/termsofuse.html?campaign=fkhp_tou");
selenium.setSpeed("1000");
}
}
So; the driver is setup, I then opened using the Selenium object (in Browser.java), but when I try to interact with the Selenium object (in TestCase.java) it's not picking it up. Thank you for any help.
Instead of:
public class Grid {
Browser browser = new Browser();
TestCase testCase = new TestCase();
public Grid() {
...
Try:
public class Grid {
Browser browser = new Browser();
TestCase testCase = new TestCase(browser); // <-- this line changed
public Grid() {
...
And in here:
public class TestCase {
Browser browser = new Browser();
Selenium selenium;
// constructor
public TestCase(){
selenium = browser.getSelenium();
}
...
Do like this:
public class TestCase {
Browser browser = new Browser(); // <-- this line changed
Selenium selenium;
// constructor
public TestCase(Browser browser){ // <-- this line changed
this.browser = browser; // <-- this line was added
selenium = browser.getSelenium();
}
...
I don't see that you're ever initializing your Selenium object except for in Browser's setUp(String url) method. And that method is also not being called here.
You've also made your Browser's Selenium object public, so you don't need to declare another Selenium object in TestCase that's assigned by an accessor method -- you can just reference it from TestCase's Browser object.
Related
I have a situation- I want to write a test when a particular User Logs in, he should not see Budget Icon. Budget icon is obviously not available when he's logged in. So I want to make sure that its working right though assertion. I am confused how should I do it ..I am using Page Object Model and I am trying below: using isDisplayed method
Below is my Base class:
public class LaydownHomePage extends TestBase {
#FindBy(xpath="//nav[#id=\"mainnav-container\"]/div[2]/a[2]")
WebElement budgeticon;
public LaydownHomePage () {
PageFactory.initElements(driver, this);
}
public boolean CheckIfBudgetIconIsAvailable ()
{
return budgeticon.isDisplayed();
}
}
And this is my Test class:
public class VerifyLaydownBudgeticon extends TestBase
{
LoginPage loginpage;
LaydownHomePage homepage;
public VerifyLaydownBudgeticon()
{
super();
}
#Test(priority=1)
public void setUp()
{
//TestBase base= new TestBase();
initialization();
loginpage= new LoginPage();
loginpage.loginToBase(prop.getProperty("username"),prop.getProperty(
"password"));
homepage=loginpage.changeLogin();
}
#Test(priority=2)
public void BudgetIconDisplayed (){
// Assert.assertTrue(false);
Assert.assertEquals(true, homepage.CheckIfBudgetIconIsAvailable());
}
}
I have two pages, in one everything is fine, but in the other I get java.lang.NullPointerException
What is my mistake? Please help
LoginPage.java - all good
package page;
import Base.Base;;
import paths.LoginPath;
public class LoginPage extends Base {
LoginPath loginPath = new LoginPath();
public void ingresarPagina(){
chromeDriverConnection();
visit(loginPath.url);
maximize();
}
public void iniciarSesion(){
type("Qualityadmin", loginPath.txtUser);
type("pass1", loginPath.txtPass);
}
public void clickEnBoton(){
click(loginPath.btnLogin);
}
}
HomePage.java - I tried placing the chromeDriverConnection() again, but I get the same error
package page;
import Base.Base;
import paths.HomePath;
public class HomePage extends Base {
HomePath homePath = new HomePath();
public void mensajeExitoso() {
String mensaje = getText(homePath.txtMesajeExito);
System.out.println(mensaje);
}
}
Error
java.lang.NullPointerException
at Base.Base.getText(Base.java:35)
at page.HomePage.mensajeExitoso(HomePage.java:12)
at step.HomeStep.mensajeExitoso(HomeStep.java:10)
at stepdefinition.HomeStepDefinition.seMuestraUnMensajeDeExito(HomeStepDefinition.java:11)
at ✽.se muestra un mensaje de exito(file:///D:/Project/aer/features/src/test/resources/features/formulario.feature:22)
Process finished with exit code -1
Base.java - I don't think the error is in the Base class, but I put it anyway
Line 35: return driver.findElement (locator) .getText ();
When I put the mensajeExitoso() method in the LoginPage class everything goes fine
package Base;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class Base {
public WebDriver driver;
public Base(WebDriver driver){
this.driver = driver;
}
public Base() {
}
public WebDriver chromeDriverConnection() {
System.setProperty("webdriver.chrome.driver", "./src/test/resources/drivers/chromedriver.exe");
driver = new ChromeDriver();
return driver;
}
public WebElement findElement(By locator){
return driver.findElement(locator);
}
public String getText(WebElement element){
return element.getText();
}
public String getText(By locator){
return driver.findElement(locator).getText();
}
public void type(String inputText, By locator){
driver.findElement(locator).sendKeys(inputText);
}
public void iniciarSesion(String user, String pass){
}
public void click(By locator){
driver.findElement(locator).click();
}
Double num1 = 20.00;
String num2 = num1.toString();
public void visit(String url){
driver.get(url);
}
public void isDisplayed(By locator){
driver.findElement(locator).isDisplayed();
}
public void maximize(){
driver.manage().window().maximize();
}
}
You tried
chromeDriverConnection();
String mensaje = getText(homePath.txtMesajeExito);
System.out.println(mensaje);
right? and can you show me see homePath.txtMesajeExito
I am a selenium+testng tester in the making.
I have this codeigniter project.
i need to test the navigation.
What i have right now.
I have tested togin script for the site.
but here is the thing when i try to run the second script it goes to login again. I can't blame the developers. But the problem is how to login each time using selenium in test cases.
=======================FILE 1 CLASS: common ========================
package common;
/**
*
* #author Aruns
*/
public class common extends config {
public common() {
}
}
=====================FILE 2 CLASS:config ============================
==================== This is a config file ==========================
package common;
/**
*
* #author Aruns
*/
public class config {
private final String base_url = "http://localhost/hospitalnew";
private int timeout = 10;
private String browser = "chrome";
private final String chromeDriver = "C:\\xampp\\htdocs\\driver\\driver\\chromedriver.exe";
private final String geckoDriver = "C:\\xampp\\htdocs\\driver\\driver\\firefoxdriver.exe";
private final String ieDriver = "C:\\xampp\\htdocs\\driver\\driver\\operadriver.exe";
private String currentUrl = "";
private String currentTitle = "";
private String username = "arun-reception";
private String password = "arun";
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCurrentUrl() {
return currentUrl;
}
public void setCurrentUrl(String currentUrl) {
this.currentUrl = currentUrl;
}
public String getCurrentTitle() {
return currentTitle;
}
/**
* sets current Title
*
* #param currentTitle = url
*/
public void setCurrentTitle(String currentTitle) {
this.currentTitle = currentTitle;
}
public String getChromeDriver() {
return chromeDriver;
}
public String getGeckoDriver() {
return geckoDriver;
}
public String getIeDriver() {
return ieDriver;
}
public String getBrowser() {
return browser;
}
public void setBrowser(String browser) {
this.browser = browser;
}
public String getBase_url() {
return base_url;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
}
=======================FILE 3 CLASS:TestNavigationMenu===================
package critical;
import common.common;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import static org.testng.Assert.*;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
*
* #author Aruns
*/
public class TestNavigationMenu {
public TestNavigationMenu() {
}
// TODO add test methods here.
// The methods must be annotated with annotation #Test. For example:
//
// #Test
// public void hello() {}
WebDriver driver;
common common;
WebElement element;
#BeforeClass
public static void setUpClass() throws Exception {
}
#AfterClass
public static void tearDownClass() throws Exception {
}
#BeforeMethod
public void setUpMethod() throws Exception {
common = new common();
System.setProperty("webdriver.chrome.driver", common.getChromeDriver());
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(common.getTimeout(), TimeUnit.SECONDS);
}
#AfterMethod
public void tearDownMethod() throws Exception {
driver.close();
}
public void automatedlogin() throws Exception {
String title = "Hospital Software ";
String url = "http://localhost/hospitalnew/appointment/appointments";
TestNavigationMenu object = new TestNavigationMenu();
object.setUpMethod();
driver.navigate().to(url);
driver.manage().window().maximize();
driver.navigate().to("http://localhost/hospitalnew/login");
driver.manage().window().maximize();
element = driver.findElement(By.name("txtUserName__"));
element.sendKeys(common.getUsername());
element = driver.findElement(By.name("txtPass__"));
element.sendKeys(common.getPassword());
element = driver.findElement(By.name("submit"));
element.click();
}
#Test(priority = 1)
public void login() throws Exception {
String title = "Hospital Software ";
String url = "http://localhost/hospitalnew/appointment/appointments";
TestNavigationMenu object = new TestNavigationMenu();
object.setUpMethod();
driver.navigate().to(url);
driver.manage().window().maximize();
driver.navigate().to("http://localhost/hospitalnew/login");
driver.manage().window().maximize();
element = driver.findElement(By.name("txtUserName__"));
element.sendKeys(common.getUsername());
element = driver.findElement(By.name("txtPass__"));
element.sendKeys(common.getPassword());
element = driver.findElement(By.name("submit"));
element.click();
if (driver.getTitle().equals(title)) {
assertTrue(driver.getCurrentUrl().equals(url));
}
object.tearDownMethod();
}
// test case 3
#Test(priority = 2)
public void isWorkingMastersDepartment() throws Exception {
String title = "Hospital Software Department";
String url = "http://localhost/hospitalnew/department/page";
automatedlogin();
driver.navigate().to(url);
driver.manage().window().maximize();
element = driver.findElement(By.className("dropdown-toggle"));
element.click();
element = driver.findElement(By.className("dropdown-toggle"));
element.click();
if (driver.getTitle().equals(title)) {
assertTrue(driver.getCurrentUrl().equals(url));
}
}
}
i though of making a function(automatic login) then calling it each time. But the problem is.
Chrome is ram intensive. opening lots of windows and not closing might cause problem in the long run. how to call object.close() for each run of testng+selenium test cases?
Secondly, i though of extending common to contain login script. But i don't know whether it will work properly.Please point me out.To the right direction.
And please grade my code if it was good for reading and optimised!
Thanks ~
Arun
I am new in Selenium and Java and I need help with base class. I have I base where I set methods for driver browsers and for its close. Problem is that when I call these method from main always web driver is called and browser is open many times. What is best practice if I don't want to have code duplication
and I want a good structure of project.
Main:
public class Main extends TestBase {
public static void main(String[] args) throws InterruptedException, ClassNotFoundException, SQLException {
LoginTest LoginTest = new LoginTest();
LogofTest LogofTest = new LogofTest();
TestBase TestBase = new TestBase();
LoginTest.setUpBeforeTestMethod();
LoginTest.loginAsAdmin();
LogofTest.logofAsAdmin();
LoginTest.tearDownAfterTestClass();
}
}
TestBase:
public class TestBase {
String a = System.setProperty("webdriver.chrome.driver",
"path");
WebDriver driver = new ChromeDriver();
protected WebDriver setUpBeforeTestClass() {
return driver;
}
protected void setUpBeforeTestMethod() {
driver.get("website");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void tearDownAfterTestClass() {
driver.close();
}}
LoginTest:
public class LoginTest extends TestBase {
public void login() throws InterruptedException {
WebElement username = driver.findElement(By.name("username"));
username.sendKeys("username");
}
}
The main focus is that I don't want to write again
WebDriver driver = new ChromeDriver();
driver.get("website"); System.setProperty("webdriver.chrome,"path");
for each test in function or class. So I want to create base class and inherit from it.
Example Selenium Test with JUnit using the Page Object Model
TestBase
public class TestBase
{
private String a = System.setProperty("webdriver.chrome.driver", "path");
protected WebDriver driver;
#Before //Before each test case, use BeforeClass for before each test class
public static void setUpBeforeTestCase() {
driver = new ChromeDriver();
driver.get("website");
}
#After
public static void tearDownAfterTestCase() {
driver.Quit(); //driver.Close() closes the window, but doesn't properly dispose of the driver
}
}
LoginTest:
public class LoginTest extends TestBase {
#Test
public void loginAndOutAsAdmin(){
LoginPage loginPage = PageFactory.initElements(driver, LoginPage.class);
LandingPage landingPage = loginPage.login("adminUser", "adminPassword");
landingPage.logout();
//Do some sort of assert here that you are logged out
}
}
BasePage
public class BasePage
{
protected WebDriver driver;
//Other common stuff your Page Objects will do, like wait for an element
}
LoginPage
public class LoginPage extends BasePage
{
#FindBy(how = How.NAME, using = "username")
private WebElement usernameBox;
//something for passwordBox and loginButton
public LoginPage(WebDriver currentDriver)
{
driver = currentDriver;
}
public LandingPage login(String username, String password)
{
usernameBox.sendKeys(username);
passwordBox.sendKeys(password);
loginButton.click();
return PageFactory.initElements(driver, LandingPage.class);
}
}
I haven't tried to compile this, but that's the basic idea. I'll let you fill in the details.
I'm new in both Selenium WebDriver and Java. I have some webservices on my site on page /someservice.php. I've wrote few tests on Selenuim and they work fine. Code example (Main Class):
public class SiteClass {
static WebDriver driver;
private static boolean findElements(String xpath,int timeOut ) {
public static void open(String url){
//Here we initialize the firefox webdriver
driver=new FirefoxDriver();
driver.get(url);
}
public static void close(){
driver.close();
}
WebDriverWait wait = new WebDriverWait( driver, timeOut );
try {
if( wait.until( ExpectedConditions.visibilityOfElementLocated( By.xpath( xpath ) ) ) != null ) {
return true;
} else {
return false;
}
} catch( TimeoutException e ) {
return false;
}}
public static Boolean CheckDiameter(String search,String result){
driver.findElement(By.xpath("//input[#id='search_diam']")).sendKeys(search);
WebDriverWait wait = new WebDriverWait(driver, 5);
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//div[#class='ac_results'][last()]/ul/li")));
WebElement searchVariant=driver.findElement(By.xpath("//div[#class='ac_results'][last()]/ul/li"));
Actions action = new Actions(driver);
action.moveToElement(searchVariant).perform();
driver.findElement(By.xpath("//li[#class='ac_over']")).click();
Boolean iselementpresent = findElements(result,5);
return iselementpresent;
}
}
Code Example (Test Class)
#RunWith(Parameterized.class)
public class DiamTest {#Parameters
public static Collection<Object[]> diams() {
return Arrays.asList(new Object[][] {
{ "111", "//div[#class='jGrowl-message']",true},
{ "222", "//div[#class='jGrowl-message']",false},
{ "333", "//div[#class='jGrowl-message']",true},
});
}
private String inputMark;
private String expectedResult;
private Boolean assertResult;
public DiamTest(String mark, String result, boolean aResult) {
inputMark=mark;
expectedResult=result;
assertResult=aResult;
}
#BeforeClass
public static void setUpClass() {
}
#AfterClass
public static void tearDownClass() {
}
/**
* Test of CheckDiameter method, of class CableRu.
*/
#Test
public void testCheckDiameter() {
SiteClass obj=new SiteClass();
obj.open("http://example.com/services.php");
assertEquals(assertResult, obj.CheckDiameter(inputMark, expectedResult));
obj.close();
}
}
Now I have 2 tests like that with 3 parameters each (total 6 variants). As you can see in every variant I create new browser window and when I run all 6 variants that take too much time (up to 80 seconds).
How can I run all variants in one browser window to speed up my tests?
Just move contents of public static void close() method from your SiteClass to tearDownClass() method in DiamTest class. In this way the browser window will be closed when the class execution finished (because of #AfterClass annotation). Your code then should look like this:
//DiamTest class
#AfterClass
public static void tearDownClass() {
driver.close();
}
It's also a good practice to move browser window initialization to setUpClass() method which will be executed before each test class (according to #BeforeClass annotation)
//DiamTest class
#BeforeClass
public static void setUpClass() {
//Here we initialize the firefox webdriver
driver=new FirefoxDriver();
driver.get(url);
}
What you need to do is share your help class with all your tests, this mean, you should create an instance of SiteClass inside your setUpClass method.
This method are annotated with #BeforeClass assuring your test class will create this method will be executed before all the test be executed.
You can read more about #BeforeClass in jUnit doc: or have a simple overview in this response.
You will also need do some rewrite some code to allow share the driver with the another test, something like this:
#RunWith(Parameterized.class)
public class DiamTest {
#Parameters
public static Collection<Object[]> diams() {
return Arrays.asList(new Object[][] {
{ "111", "//div[#class='jGrowl-message']",true},
{ "222", "//div[#class='jGrowl-message']",false},
{ "333", "//div[#class='jGrowl-message']",true},
});
}
private String inputMark;
private String expectedResult;
private Boolean assertResult;
private static SiteUtil siteUtil;
public DiamTest(String mark, String result, boolean aResult) {
inputMark=mark;
expectedResult=result;
assertResult=aResult;
}
#BeforeClass
public static void setUpClass() {
siteUtil = new SiteUtil();
}
#AfterClass
public static void tearDownClass() {
siteUtil.close();
}
#Test
public void testCheckDiameter() {
siteUtil.open("http://example.com/services.php");
assertEquals(assertResult, obj.CheckDiameter(inputMark, expectedResult));
}
}
and:
public class SiteClass {
static WebDriver driver;
public SiteClass() {
driver = new FirefoxDriver();
}
public void open(String url){
driver.get(url);
}
...
Tip:
You should read about the TestPyramid.
Since functional tests are expensive, you should care about what is really necessary test. This article is about this.