I have a hard time to get used to the WebDriver PageObject pattern. Please share your experience and ways of using PageObjects pattern and loadableComponents.
As PageObject represents usually a component or piece of functionality, it occurred to me at first that I should use it to actually do some things in load() and see if it does what it should in isLoaded().
Then I realized that it should be utilized only for "loading" objects (possibly initialization) as it is in case of moving around a website, each object with its own url. And using isLoaded() to test whether the object IS READY for testing.
But if you have a complex JavaScript order submitter to test, that is compound of JS file uploader, JS form that is based on 2 independent parts and there are three kinds of Orders, you don't move anywhere (regarding URL), just the state of elements is changing.
Consider the get() method. You get into the page with the interactive Form. It is loaded when the form exist on the page. Then you have form1 and form2 objects ... what should their load() and isLoaded() method look like, they are ready for action right away because they don't need any loading, just testing their services.
It's a mess, one doesn't know if the isLoaded() method is used for checking whether object loaded, or whether object loaded and was setup properly. But I guess the former way is correct and that validity of setting it up should be ensured within the tests.
Scenario:
Testing first part of html form - test that field client side validation works
Testing the second one that depends on the first one
Testing the following file uploader - upload, canceling, clearing, order, fileIDs
Testing the overall html form submission - ServerSide validation errors, results
The documentation says :
LoadableComponent
PageObjects
The public methods represent the services that the page offers
Validate, upload, upload Multiple, cancel, clear
Try not to expose the internals of the page
The only thing that occurs to me is having Driver instance hidden to UnitTests and use Only PageObjects to keep all field names, css class names in PageObjects + supply PageObjects with input data and assert boolean result of the services/functionality
Methods return other PageObjects
This is the most difficult thing to get used to. Having 4 page objects for one interactive form kinda doesn't feel natural. They recommend Form1, Form2(Form1), Upload(Form2), Submit(Upload), although I find the chaining and handing over a reference to the preceding object very chaotic. Calling get() on all of them in a test method seems better. But I guess that the idea behind it is not to expose the Driver instance to the Tests, but use only PageObjects that are using Driver instance internally
Different results for the same action are modelled as different methods
I suppose that this means that it shouldn't be decided about validity of that action on the Page object side, but on the Test side
I have a bit different approach when writing page objects. Translated to your terms load() method ends with conditional wait ensuring the page contains what you desire. Then I do not need any isLoaded() - either I'm there or Exception is thrown.
Components in page are properties of the page containing them and I set two-way relationship between a component and the page. They are not fully functional page objects. Maybe your forms can be modeled this way too.
The loadable component is an extension to the Page Object pattern. The LoadableComponent class in the WebDriver library will help test case developers make sure that the page or a component of teh page is loaded successfully. It tremendously reduces the efforts to debug your test cases. The page object should extend this Loadable Component abstract class and as a result, it is bound to provide implementation for the following two methods:
protected abstract void load()
protected abstract void isLoaded() throws java.lang.Error
The page or component that has to be loaded in the load() and isLoaded() methods determines whether or not the page is fully loaded. If it is not fully loaded, it throws an error.
https://code.google.com/p/selenium/wiki/LoadableComponent
Related
I am following Page Object Model to automate a flow in one application. In one of the module I have to assert Page Title and some more messages. As of now I am putting my Assertion code in the PageFactory itself as follows:
public class EditPost {
WebDriver driver;
public EditPost(WebDriver editPostDriver)
{
this.driver=editPostDriver;
}
#FindBy(how=How.XPATH,using="//*[#id='message']/p")
WebElement post_published;
public void assert_message()
{
String actual_message_title=post_published.getText();
Assert.assertEquals(actual_message_title, "Post published. View post");
System.out.println("Message: Post published, Successfully Verified");
}
}
I am calling the assert methods from the main file implementing TestNG as follows:
#Test (priority=5)
public void assert_message()
{
//Created Page Object using Page Factory
EditPost edit_post = PageFactory.initElements(driver, EditPost.class);
edit_post.assert_message();
}
Currently, I am running the execution through 3 packages. "Helper" package for the Browser Factory, "Pages" package for the PageFactories and "Testcase" package for the Testcases.
My objective is moving forward I want to reuse the code written for all the different utilities.
My questions are:
As per the concept of PageFactory & Page Object Model is my approach correct? Or do I need to move the Assertions to the "Helper" package? Or should I create a separate library/package for the Assertions? (In the comming days I may need to perform multiple Assertions on a single page)
In the next sprint I may require to do some other activities like taking Screen Shots of All/Failed Testcases. So how do I keep my design structured and organized so I can reuse the code/libraries/utilize them in a optimum way?
Best practice, according to most sites I've seen, is to keep the asserts out of the page objects. One example is below from the Selenium docs.
http://www.seleniumhq.org/docs/06_test_design_considerations.jsp#page-object-design-pattern
There is a lot of flexibility in how the page objects may be designed, but there are a few basic rules for getting the desired maintainability of your test code.
Page objects themselves should never make verifications or assertions. This is part of your test and should always be within the test’s code, never in an page object. The page object will contain the representation of the page, and the services the page provides via methods but no code related to what is being tested should be within the page object.
There is one, single, verification which can, and should, be within the page object and that is to verify that the page, and possibly critical elements on the page, were loaded correctly. This verification should be done while instantiating the page object. In the examples above, both the SignInPage and HomePage constructors check that the expected page is available and ready for requests from the test.
The page object should return things like product name, product price, currently selected quantity, and so on. The test code would then assert that the returned string matches what is expected.
assert_message() would become getMessage() and return the message as a String. See below.
public String getMessage()
{
return driver.findElement(messageLocator).getText();
}
(NOTE: read on for why I've changed the PageFactory element to a locator here.)
and then in your test code, you would have
Assert.assertEquals(editPost.getMessage(), "Post published. View post");
Now you've kept the assert code in your test script and out of the page object.
Looking at your code, I would make some further recommendations.
I would suggest you read up on some Java naming conventions. There are a number of sites that have recommendations and I think there are a lot of similarities between them but here's the oracle recommendations to start with. Your method names should be
verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized.
So assert_message() would turn into assertMessage() and so on. The _s make it look more like python.
Order of preference for locators: ID, CSS selector, and in rare circumstances, XPath. ID should always be your first choice because it (by W3C definition) should be unique on the page. CSS selector should be next because it's the fastest (in my testing faster than ID), has the best browser support, and is most consistently implemented across browsers. XPath should be reserved only for things that cannot be done by CSS seletors like finding an element by contained text. XPath locators are poor performers compared to CSS selectors and do not have the same level of support as CSS selectors. For example, your XPath locator can easily be converted to a CSS selector, "#message > p".
Here are some CSS selector references to get you started.
CSS Selectors reference
CSS Selector tips
Drop PageFactory. Yes, it seems to make things easier but I think in many situations it causes more problems, like stale element exceptions and the like. Prefer instead to scrape the page as needed. Declare all locators at the top of the class and use them in methods when needed.
public class EditPost {
WebDriver driver;
By messageLocator = By.cssSelector("#message > p")
public EditPost(WebDriver editPostDriver)
{
this.driver = editPostDriver;
}
public String getMessage()
{
return driver.findElement(messageLocator).getText();
}
}
I know this is more than you asked but hopefully it's helpful.
Selenium Java Page-Object Model: Should we write separate page-object for the error pop-ups coming in a page?
I am using the Page Object model and have each page as a single class and the actions in that page as methods.
Now, Should i include the pop-up handling on the same page as a method or should I have to create a separate page-object class for those pop-ups?
What is the best practice.?
Each pop-up has 2 options and some info about the pop-up to verify.
Assuming all pop-ups have particular properties in common, you can create a separate class which would be included into each Page Object. If those description and option fields are always identified with same locators, it seems like a great idea.
In case those pop-ups differ in a way it is hard to handle them with single class you might consider creating an interface for pop-ups and have each of actual Page Object implement it and handle it on its own.
I am trying to implement an MVC type pattern in my Eclipse plugin, but I'm stuck. I can't figure out how to have my controls tell the form that they belong to that they have changed. There's no isDirty() method and no firePropertyChanged() method like I am using in the form/editor relationship.
In your FormPage derived class you add form page parts based on SectionPart or AbstractFormPart or IFormPart which contain the controls for the page.
AbstractFormPart has a markDirty method (also markStale, refresh and commit) which are intended to be the main ways to manage the form state.
I have a struts2 form.
In this form the user is asked to fill several fields.
2 of those fields are filled by picking an object from another action.
In fact :
main form => pickup button => new action with a new form to fill => return to the main form and filling the corresponding field.
My problem is that after the user finished the subaction, I want to return to the main form but not lose everything he filled before ...
I don't know how to handle this, should I pass to the subaction every field from the main form ?
Several ways come to mind, depending on factors will determine the best one for you.
1) Send out all the parameters you want to keep each time. Easiest way to do this is use hidden fields. Model driven may also make sense here or placing several actions into one class, either way it highlights that those actions share a common set of properties.
2) Store the value in the session like Vasily recommended however Struts2 has the scope interceptor... If you need to do this often it is worth looking at (see last example on page): http://struts.apache.org/2.3.1.2/docs/scope-interceptor.html however to do this right is a little tricky, because if this is an office application and the users are anything like me they we'll have a dozen windows open at any given time. In this situation you'll want to consider also adding a token (see: struts2 token tag) to to each "flow" which will prevent one of a dozen windows when doing a refresh to pick up the latest data from what I would expect rather than, get polluted from some global store that all actions use. There are some other ways to handle flows/conversations... for instance someone wrote a plugin which I suppose would implement what was just explained: http://code.google.com/p/struts2-conversation/
It's always worth a quick look over the struts2 plugins to make sure you aren't reinventing the wheel, although I must say I can't vouch for that plugin.
3) Don't have them leave the page at all. This is very slick... If you need to select additional parameters, when they click on the "pickup" button have the form expand with the required fields then when they click "update" in this subsection, it is close and update the rest of the fields. You will need a combination of JS on the client side with generally an XML or JSON response. For your own pages JSON is the easier way to go, to produce JSON responses see the struts2-json-plugin.
I would go with #3 in most cases. Possibly #1 if I knew the action would only be used from the calling action and/or I wanted a very bookmark safe form(pass all parameters if possible with GET). #2 in more complicated scenarios where multiple actions needed to collaborate and I could not use ajax for some strange reason. Note #3 and #2 are not very book mark friendly, and they are in general not very state friendly without using client side storage.
Store your mainform in session.
public class Test extends ActionSupport implements Preparable {
private MainForm form;
public void prepare(){
form = (MainForm)ServletActionContext.getRequest().getSession().getAttribute("mainForm");
if(form == null) {
form = new MainForm();
}
}
public String execute(){
//Do something useful
//Do something useful
//Do something useful
return SUCCESS;
}
public MainForm getForm() {
return form;
}
public void setForm(MainForm form) {
this.form = form;
}
"prepare" method is a part of Preparable interfeice. It will be executed before all parameters readings and before "execute" method every time when your call the acton.
You need the following to have a working struts2 platform:
2 struts form classes with fields
A struts action class
A jsp page
A struts config file
Then go through the below process:
When the first form is loaded save its bean in the second form
through a field
After you return from the first form load its fields in the second
form through the above field
I am using a MVC framework which is a bit like struts.
So, say I have a "Edit Store" link in my application this is how the url would look like:
http://localhost:9080/test?action=editStore&storeNum=10
Now, action determines my Action (analogous to Struts Action) to be run. The corresponding action here is: EditStoreAction. Clicking this would open a pop up with different attributes of a store for edit.
My question here is:
How do I write my actions? Do I write two actions in this context?
EditStoreAction which will render
edit.jsp
StoreSaveAction which
will invoked when user presses
accept on the rendered response of
edit.jsp.
OR Do I just write one action? EditStoreAction and submit form to the same action, I would know that the user has pressed the accept button for changes on submission. So, I would execute a different flow in the Action, which would save updates to database and redirect to a diff page.
What is the best pratice here? Create as many actions as possible coz it keeps the code modular? OR just write one action to handle everthing in a jsp?
I know this question sounds a bit trivial, however, sometimes you just want to get everything right. Hence, the question. Appreciate your help.
The idea is, similar to Spring MVC, to map your actions to the methods of a specific class, say it controller.
So, in your case, these two actions will be mapped on two different methods of the same class. You can call the class StoreFormController and two methods, editStore() and saveStore().
Better still if you make two controllers for each entity. May be one for all GET requests and another is for POST requests. So, in your case there would be two controllers StoreController for all other requests and StoreFormController for all form submissions, namely post requests. Now, your first action being GET will go to editStore() method of StoreController, whereas the second being POST request will go to saveStore() method of StoreFormController. You can define as many methods as needed in any of these two classes based on the request type.
You can easily see, where I am coming from, if you know Spring MVC API.
I like to use struts DispatchAction class because I could define more than one method in the action class (the "execute") method. Behind the hood, all it does is to find the method that it has to execute (submitted in the form or passed in the URL), find the method using reflection, invoke it with the right set of arguments (the method must have the same signature of the "execute" method), gets it result and pass it along. The DispatchAction simply overrides the "execute" method of the Action class to implement that behavior.
That being said, in your case, I would define only one class - let's say "DispatchStoreAction", and I would define two methods, probably "prepare" and "save". I like doing it that way because I still have a good class abstraction (and you don't put the "action" you're executing in the class name), because your methods can clearly identify what they are supposed to do, and also because, by definition, action classes tend to be small. You will probably have a "StoreLogic" or "StoreBusiness" defined somewhere, and this class will handle the business logic related to the entity that you're working on. I personally think that it's nice if you have one "StoreAction" and then one "StoreLogic", one "UserAction" and one "UserLogic" and so on - the relationship doesn't need to be 1 to 1 but I think it helps maintaining the code.
Check the source code of the DispatchAction class for ideas on how to do this, but the implementation should be trivial.