I'm new and I'm learning webdriver and java:)
I have beginner question.
I created classes whit locators(findBy) and methods working with this locators (senKeys(), click(), etc.) - I use pagefactory.
HomePage
LoginPage
...
My main class AddNewLeadTest is a class where i initialize method from classes with locators, and I do it like this:
HomePage hp = new HomePage(driver);
hp.loginButton.click()
I would like do to this like this:
HomePage.loginButton.click()
It's faster and I will not have to create in AddNewLeadTest new object for everyone xxxPage class.
How should I write class/method to simplify creating new object?
I found example I would like to use in my project(in C#), but I don't know how to use it in Java. See below.
public static class Pages
{
private static T GetPage<T>() where T : new()
{
var page = new T();
PageFactory.InitElements(Browser.Driver, page);
return page;
}
public static AboutPage About
{
get { return GetPage<AboutPage>(); }
}
public static TopNavigationPage TopNavigation
{
get { return GetPage<TopNavigationPage>(); }
}
public static HomePage Home
{
get { return GetPage<HomePage>(); }
}
public static ContactPage Contact
{
get { return GetPage<ContactPage>(); }
}
public static RegisterPage Register
{
get { return GetPage<RegisterPage>(); }
}
public static LoginPage Login
{
get { return GetPage<LoginPage>(); }
}
public static ManageAccountPage ManageAccount
{
get { return GetPage<ManageAccountPage>(); }
}
In this example calling method is like this:
public void CanRegisterNewAccount()
{
Pages.Register.Goto();
Pages.Register.RegisterNewUser();
}
So its very simple and clear.
So how can I write it another way, i think it dont look good..
/*------------------------------------------------------------------------*/
HomePage gotologin = new HomePage(driver);
gotologin.gotoLoginPage();
/*------------------------------------------------------------------------*/
LoginPage login = new LoginPage(driver);
login.loginUserToBase("login","pass");
/*------------------------------------------------------------------------*/
addLeadPage newLead = new addLeadPage(driver);
newLead.gotoLeadsPage();
newLead.addNewLead();
newLead.enterLeadName("Tolek");
newLead.enterLeadLastName("Banan");
newLead.enterLeadTitle("Boss");
newLead.enterLeadEmail("tolekbanan#gmail.com");
newLead.enterLeadMobile("123456789");
newLead.enterLeadWorkPhone("9876541");
newLead.enterLeadStreet("Kowalskiego");
newLead.enterLeadCity("Kraków");
newLead.enterLeadCode("12-123");
newLead.enterLeadRegion("Małopolska");
newLead.enterLeadTag("testBase");
newLead.clickSubmit();
/*------------------------------------------------------------------------*/
LeadPage checkStatus = new LeadPage(driver);
LeadPage.checkUsrStat();
...
...
...
I was inpired by method from my before post from https://www.youtube.com/watch?v=DO8KVe00kcU
I thought that is a solution i should use im my tests
I show U now all part of this test.
Pages.class
public static class Pages
{
private static T GetPage<T>() where T : new()
{
var page = new T();
PageFactory.InitElements(Browser.Driver, page);
return page;
}
** public static LoginPage Login
{
get { return GetPage<LoginPage>(); }
}**
public static AboutPage About
{
get { return GetPage<AboutPage>(); }
}
public static TopNavigationPage TopNavigation
{
get { return GetPage<TopNavigationPage>(); }
}
...
}
LoginPage.class
public class LoginPage
{
public void Goto()
{
Pages.TopNavigation.LogIn();
}
}
TopNavigation.class
[FindsBy(How = How.LinkText, Using = "Log in")]
private IWebElement logInLink;
public void LogIn()
{
logInLink.Click();
}
and AddNewLeadTest.class
public void CanGoToLoginPage()
{
Pages.Home.Goto();
}
Is it really bad solution??
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());
}
}
For example, if I wanted to do something like this to call a method:
myLights.addLight(new Fluorescent(lumens));
in order to create a new object in the Fluorescent class and pass down the lumens data. How would I then set up the method to receive this?
Assuming method is not returning anything.
void addlight(Fluorescent a){
// your logic
}
In your Lights class create a method that accepts a Fluorescent object as an argument.
public void addLight(Fluorescent fluorescent){
// do something
}
Here is a basic example:
public class HelloWorld
{
public static void main(String[] args)
{
Light light = new Light();
light.addLight(new Fluorescent("300 lm"));
System.out.print(light.getLumen());
}
}
public class Light {
private String lumen;
public Light() {
}
public void setLumens(String lumen){
this.lumen = lumen;
}
public String getLumen(){
return this.lumen;
}
public void addLight(Fluorescent fluorescent) {
if(fluorescent.getLumen() != null) {
this.lumen = fluorescent.getLumen();
}
}
}
public class Fluorescent {
private String lumen;
public Fluorescent(String lumen){
this.lumen = lumen;
}
public void setLumen(String lumen){
this.lumen = lumen;
}
public String getLumen(){
return this.lumen;
}
}
Seeing that a Fluorescent is a Light, you might want to look in to inheritance.
Look here for some explanation
Java 101: Inheritance in Java, Part 1
public class Fluorescent() {
public Fluorescent(String lumens) {
// do something
}
}
public class Lights() {
public void addLight(Fluorescent fluorescent) {
// do something
}
}
I have a class that has static variables assigned during initialization. I would like to write unit tests for this class with modifying values for this static variable. Below is a simple code to explain my scenario
Class to test:
public class Hello {
private final static String HELLO_FINAL = "Hello " + HelloTo.getInstance().getHelloTo(); // I would like to modify this value between tests
public String sayHello() {
return HELLO_FINAL;
}
}
Supporting class:
public class HelloTo {
private String helloTo = "World";
private static HelloTo singleton = new HelloTo();
private HelloTo() {}
public static HelloTo getInstance() {
return singleton;
}
public void setHelloTo(String helloTo) {
this.helloTo = helloTo;
}
public String getHelloTo() {
return helloTo;
}
}
Test class:
import org.junit.Assert;
import org.junit.Test;
public class HelloTest {
#Test
public void testDefault() {
Assert.assertEquals("Hello World", new Hello().sayHello());
}
#Test
public void testDynamic() {
HelloTo.getInstance().setHelloTo("My name");
Assert.assertEquals("Hello My name", new Hello().sayHello());
}
}
Is there a way to make both tests successful. Currently I get a failure for testDymanic() saying:
org.junit.ComparisonFailure: expected:<Hello [World]> but was:<Hello [My name]>
Thanks in advance!
Using a mutable singleton in a tests is an known problem. You have to reset the state of the singleton between tests, of even better, don't use a singleton in your tests.
You could do something like:
public enum HelloTo {
INSTANCE;
private String helloTo = "World";
public void reset() {
setHelloTo("World");
}
public void setHelloTo(String helloTo) {
this.helloTo = helloTo;
}
public String getHelloTo() {
return helloTo;
}
}
public class Hello {
public static String sayHello() {
// has to be dynamic as helloTo can change.
return "Hello " + HelloTo.INSTANCE.getHelloTo();
}
}
public class HelloTest {
#Before
public void setUp() {
HelloTo.INSTANCE.reset();
}
#Test
public void testDefault() {
Assert.assertEquals("Hello World", Hello.sayHello());
}
#Test
public void testDynamic() {
HelloTo.INSTANCE.setHelloTo("My name");
Assert.assertEquals("Hello My name", Hello.sayHello());
}
}
HELLO_FINAL is only initialized once per run; you can't reinitialize it within the same JVM. Is there a way to make both tests successful? Sure, there are countless ways. But that depends on what you're trying to test, which is not completely clear from your example.
I am trying to update code from Jmockit 1.1 to 1.9 to Access Real Instance, But it seems to be unsuccessful as below:
java.lang.IllegalArgumentException: Matching real methods not found for the following mocks:
CopyOfAccessRealInstanceTest$1#getRealInstanceName(String m, mockit.Invocation inv)
at CopyOfAccessRealInstanceTest$1.<init>(CopyOfAccessRealInstanceTest.java:28)
at CopyOfAccessRealInstanceTest.mockConstructor(CopyOfAccessRealInstanceTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
I think it is due to mock method:
#Mock(invocations = 1)
public String getRealInstanceName(String m,Invocation inv)
-------------------------Codes 1.9---------------------------------
public class CopyOfAccessRealInstanceTest {
private Constructor constructor = new Constructor("");
#Test
public void mockConstructor() {
// Mockit.setUpMock(Constructor.class, new MockedConstructor());
MockUp<Constructor> mockup = new MockUp<Constructor>() {
//public Constructor it;
#Mock(invocations = 1)
public String getRealInstanceName(String m,Invocation inv)
{
if ("real".equals(m)) {
return inv.proceed(inv.getInvokedArguments());
// return it.getRealInstanceName(m);
} else {
return "mock";
}
}
};
Assert.assertEquals("mock",
constructor.getRealInstanceName(""));
Assert.assertEquals("real_m_real",
constructor.getRealInstanceName("real"));
}
}
-----------------------Code of Jmock 1.1--------------------------------
public class AccessRealInstanceTest {
private Constructor constructor = new Constructor("");
#Test
public void mockConstructor() {
Mockit.setUpMock(Constructor.class, new MockedConstructor());
Assert.assertEquals("real_m_real",
constructor.getRealInstanceName("real"));
}
public static class MockedConstructor {
public Constructor it;
#Mock(reentrant = true)//reentrant allow to access real instance
public String getRealInstanceName(String m) {
if ("real".equals(m)) {
return it.getRealInstanceName(m);
} else {
return "mock";
}
}
}
}
Class to be Mocked:
public class Constructor {
private String memberId;
public Constructor(String memberId) {
this.memberId = memberId;
}
public String getRealName() {
return "real_" + this.memberId;
}
public String getRealInstanceName(String m) {
return "real_m_" + m;
}
}
It is resolved. Thank you for Rogério and Sean!
Note the API documentation says that an Invocation parameter must be the first parameter in the mock method. – Rogério
I want to do something like this:
public class ScadenzaService {
...
public List<Scadenza> tutteLeScadenze() {
List<Scadenza> scadenze = null;
txm.doInTransaction(new TransactionAction() {
#Override
public void perform() {
scadenze = dao.getAll(Scadenza.class);
}
});
return scadenze;
}
But I can't access scadenze in the inner class, since it's not final. However, final wouldn't help: it makes a constant.
What's the workaround?
Make scadenze final and initialise it to a new List. Inside your anon class you can still add to the list; being declared final does not prevent this.
public List<Scadenza> tutteLeScadenze() {
final List<Scadenza> scadenze = new ArrayList<Scadenza>();
txm.doInTransaction(new TransactionAction() {
#Override
public void perform() {
scadenze.addAll(dao.getAll(Scadenza.class));
}
});
return scadenze;
}