When you are modelling your page objects, how would you deal with a page which has form and about 50 input fields on it? What is the best practice here?
Would you create a page object and write a separate function for each input action? or would you write one function which parameters are passed to it and enters the text?
e.g.
public void enterFirstName(String firstName) {
driver.type("firstNameField", firstName);
}
public void enterSecondName(String secondName) {
driver.type("secondNameField", secondName);
}
or
public void fillInForm(String inputFieldName, String text) {
driver.type(inputFieldName, text);
}
I can see in the first model, when writing tests, the tests are more descriptive, but if the page contains too many input fields, creating the page object becomes cumbersome.
This post is also quite interesting in structuring selenium tests in Page Objects
Functional Automated Testing Best Practices with Selenium WebDriver
The idea behind the page object model is that it abstracts the implementation away from the caller. In the first mechanism, you are successfully doing that because the caller doesn't need to know if the html input field name changes from "firstName" to "user_first_name", whereas in your second implementation any changes to the actual page would have to be trickled out to all callers of your page object.
While it may be more work up front to create your page object, if you maintain the encapsulation it'll save work in the long run when the real html page inevitably changes.
I always like to break things up into groups of related information. For instance, if I have a user class I might break that up into a few smaller classes: LoginCredentials, ProfileInfo, Settings, etc, but I would still usually have a top level User class that contains these sub classes.
One thing I would certainly recommend would be to pass in an object to one FillForm function rather than all of those individual functions. There are some great advantages using this approach. One, you could have some "common" pre-configured objects that you use for many of your test cases. For instance:
public class FormInfo
{
string Domain;
string Name;
string Category;
// etc...
public FormInfo(string domain, string name, string category)
{
Domain = domain;
Name = name;
Category = category;
// etc...
}
}
// Somewhere in your initialization code
public static FormInfo Info1 = new FormInfo("myDomain1", "myName1", "myCategory1");
public static FormInfo Info2 = new FormInfo("myDomain2", "myName2", "myCategory2");
You can still update one of your common merchants if you need to do something one-off:
// In your test case:
Info1.Category = "blah";
FormPage.FillForm(Info1);
OR, you can create a brand new merchant object for a specific test case if necessary. You can also do things like field validation either using these objects, or what I normally do is break the page object pattern for specific field validation, so if I am validating the merchant domain field I might do this:
Info1.Domain = null; //This should make the FillForm function skip doing anything with this field.
FormPage.FillForm(Info1);
FormPage.DomainTextBox.Text = "field validation string";
Another important advantage of this approach is that if the page is ever updated to add, remove or modify fields, you would only need to update your FormInfo object and FillForm function, and would not need to modify specific test cases that call the FillForm function - assuming they are using one of your common FormInfo objects. Another possibility to get more coverage would be to set up one of your common FormInfo objects to generate random strings for each of the fields that comply to the min/max length and cycle between all different allowed characters. This allows you to get some additional testing out of the same set of tests, although it could also add some noise if you start getting failure results only from specific strings, so be careful.
In addition to your enterWhatever() methods, I usually also create a createWhatever(field1, field2, ...) method, which I can use as a fast path to creating whatever the form builds, for use when the real purpose of the test is something else. Thus, if I need to create a Customer in order to test submitting a Ticket, the test goes to the CreateACustomer page and just invokes createCustomer(firstName, lastName, emailAddress, ...), and then continues on to the more-nuanced task of creating a Ticket using that Customer.
I am answering an old question for the benefit of readers.
Along with other good answers here, I would like to add few suggestions here for those who are new to POM.
Page objects is a well known design pattern, widely accepted by the automation engineers, to create separate class file for each page of the application to group all the elements as properties and their behaviors / business functionalities as methods of the class. But it has few issues in creating a class for a page - especially when the page has more / different sets of elements / complex element like a grid / calendar widget / a HTML table etc.
The class might contain too many responsibilities to handle. It should be restructured and broken into smaller classes. Ie, following the Single Responsibility Responsible.
Check the image here for the idea.
That is, create reusable page fragments & let the main page object serve the page fragments.
Check here for more info.
The way I do this in my forms is to get a list of all of the inputs on the page. Then remove any input elements that are not displayed. After that I can put valid or invalid text to each of the inputs. From there I catch the validation summary to make sure I am getting the correct error or not. If not then log exception.
What this does is allow me to input text into as many inputs as are on the page, and it still allows me to log exceptions and send them via e-mail. I also catch textareas and password fields in my list and I have a separate list for checkbox fields and Options since there are different things that I usually want to do with those.
what it boils down to is that all I have to do to test a page is this:
for (int i = 0; i < inputs.Count(); i++)
{
//This captures the error message string created in the input validation method
//nextButton is the IWebElement of the button to click to submit the form for validation
//ErrorMessageID is the ID of the Validation Summary display box (i.e. ErrorMessageID = "FormSummary" <asp:ValidationSummary ID="FormSummary" runat="server" CssClass="errorMessage" />
string InputValidationText = utilities.InputValidation(driver, inputs, i, nextButton, ErrorMessageID)
if(InputValidationText != string.Empty)
{
//LogError
}
}
Please have a look at the readme, https://github.com/yujunliang/seleniumcapsules
Related
If we have a Class Book and we want to calculate the score of a Book following some rules like "if the number of pages is lower than X then we need to substract Y from the score" and using an Hexagonal Architecture. Should we place this method calculateScore() in a separate Service in case this logic changes in the future using different fields or this reponsibility should be in the Domain itself?
1st approach
package com.xxx.domain;
[...]
public class Book {
[...]
public Double score() {
[...]
}
[...]
}
2nd approach
package com.xxx.application;
[...]
public interface ScoreService {
[...]
void calculateScore(Book book);
[...]
}
Should we place this method calculateScore() in a separate Service in case this logic changes in the future using different fields or this reponsibility should be in the Domain itself?
First the clean architecture is very clear when it comes to the question "Where should business logic be placed?".
Application agnostic business logic in the entities layer.
Application specific business logic in the use case layer.
But I think your question is about something a bit different, it's about anemic or rich domain models. I can't tell you every of my thoughts here, but I have written down most of them in the blog I linked in the sentence before.
The condensed statement of mine is
rich domain models combine data and logic while anemic models separate them.
Let's think about the anemic way...
If you place the logic in a separate service it usually means that you have to expose all properties of the book. You will make them public or at least package scope if the service is in the same package.
Your question also focuses on change. You make the statement that logic changes can be better handled if the logic is put in a separate service. That's true, but it comes at a cost.
It's true that an anemic model let you add logic easier, but it is also true that each logic (each service) must have the same interpretation of the anemic model. I mean each service must know how to modify the data structure properly to keep it consistent and that will be hard to maintain when the number of services grows.
But implementing the service can also be a good intermediate step, because it will give you a hint about cohesion. The cohesion usually shows you where to place a method. E.g.
public class ScoreService {
public BookScore calculateScore(Book book, BookRentals rentals){
int pageCount = book.getPageCount();
Author author = book.getAuthor();
// calculate a new value based on pageCount and the author
// ...
OtherValue ov = book.getSomeOtherValue();
// do something with ov
int rentalCount = rentals.getCountSince(someDate);
// ... and so on
}
}
When you look at the calculateScore above you will recognize that there are a lot of get invocations on Book and less on BookRentals. This is a hint that most of the data that calculateScore needs is placed in the Book. Thus the calculateScore's cohesion is higher to Book and the method might be placed in the Bookclass. E.g.
public class Book {
public BookScore getScore(BookRentals rentals){
int pageCount = this.getPageCount();
Author author = this.getAuthor();
// calculate a new value based on pageCount and the author
// ...
OtherValue ov = this.getSomeOtherValue();
// do something with ov
int rentalCount = rentals.getCountSince(someDate);
// ... and so on
}
}
The difference is obvious:
the number of method parameters decreases. Maybe you apply DDD and Book is an aggregation root and also has access to BookRentals. Then your parameters might decrease to zero.
Since most of the properties that getScore needs are located in the Book class, you might want to lower their visibilily to private. So that uncontrolled access is not allowed.
One question that often arises when developers put the logic in the entities is: "How can an entity access data from a data store?"
My solution is to just pass a repository to the methods that need it. E.g.
public class Book {
public BookScore getScore(BookRentalRepository repo){
// ...
int rentalCount = repo.getRentalCountSince(this, someDate);
}
}
Whatever way you want to go, anemic or rich, keep the logic in a POJO. Also keep in mind that a POJO can be more than a simple data structure.
I hope my answer helps you to make a decision for your specific application.
If the calc of the score depends only on the book state, i would create a method in the book entity to calc it.
Otherwise, if it depends on other domain objects also, i would create a domain service for calculating it.
Regarding to persist the score. I would persist it just if the calc process is very complicated and takes a lot of time. Otherwise, I wouldn't persist it and calc it when need it.
In case you persist jt, you have to consider that you have to recalculate it and persist the new value every time the other values it depends on change too.
In Java, assume you have a data object object with an attribute bar that you need to set with a value that is returned from a complex operation done in an external source. Assume you have a method sendRequestToExternalSource that send a request based on 'object' to the external source and gets an object back holding (among other things) the needed value.
Which one of these ways to set the value is the better practice?
void main(MyObject object) {
bar = sendRequestToExternalSource(object);
object.setBar(bar);
}
String sendRequestToExternalSource(MyObject object) {
// Send request to external source
Object response = postToExternalSource(object);
//Do some validation and logic based on response
...
//Return only the attribute we are interested in
return response.getBar();
}
or
void main(MyObject object) {
sendRequestToExternalSourceAndUpdateObject(object);
}
void sendRequestToExternalSourceAndUpdateObject(MyObject object) {
// Send request to external source
Object response = postToExternalSource(object);
//Do some validation and logic based on response
...
//Set the attribute on the input object
object.setBar(response.getBar());
}
I know they both work, but what is the best practice?
It depends on a specific scenario. Side-effects are not bad practice but there are also scenarios where a user simply won't expect them.
In any case your documentation of such a method should clearly state if you manipulate arguments. The user must be informed about that since it's his object that he passes to your method.
Note that there are various examples where side-effects intuitively are to be expected and that's also totally fine. For example Collections#sort (documentation):
List<Integer> list = ...
Collections.sort(list);
However if you write a method like intersection(Set, Set) then you would expect the result being a new Set, not for example the first one. But you can rephrase the name to intersect and use a structure like Set#intersect(Set). Then the user would expect a method with void as return type where the resulting Set is the Set the method was invoked on.
Another example would be Set#add. You would expect that the method inserts your element and not a copy of it. And that is also what it does. It would be confusing for people if it instead creates copies. They would need to call it differently then, like CloneSet or something like that.
In general I would tend to giving the advice to avoid manipulating arguments. Except if side-effects are to be expected by the user, as seen in the example. Otherwise the risk is too high that you confuse the user and thus create nasty bugs.
I would choose the first one if I have only these two choices. And the reason of that is "S" in SOLID principles, single responsibility. I think the job of doComplicatedStuff method is not setting new or enriched value of bar to MyObject instance.
Of course I don't know use case that you are trying to implement, but I suggest looking at decorator pattern to modify MyObject instance
I personally prefer the variant barService.doComplicatedStuff(object); because I avoid making copies
I have written an array in beanshell assertion in jmeter as shown below.
String[] myList = {"CM_Name","OwnerID"};
for (int i = 0; i < myList.length; i++)
{
vars.put("create_"+myList[i],ctx.getCurrentSampler().getArguments().argumentsAsMap.get(myList[i]));
log.info("create_"+myList[i]);
}
I want myList[] to be accessible in another beanshell assertion which is located in another controller.
I have tried this
vars.put("myArr",myList);
But it didn't worked. What can i do to retrieve the above String array in another beanshell assertion ?
vars.put() method expects String only as the second argument therefore you cannot put an array there, the solutions are in:
Use vars.putObject() method like:
vars.putObject("myArr", myList);
Later on you will be able to access it like:
String [] myList = vars.getObject("myArr");
Use bsh.shared namespace like:
In first assertion:
bsh.shared.myArr = myList
In second assertion:
String [] myList = bsh.shared.myArr
This way you will even be able to share objects between different Thread Groups.
See How to Use BeanShell: JMeter's Favorite Built-in Component article for more Beanshell-related tips and tricks
You can use putObject() to let a key point to an Object of any type.
Note you will have to use getObject() to retrieve it in the later assertion. If you don't, You'll get a ClassCastException of some sort.
It is your job to keep Strings and Objects from being messed up.
Protip: never store alternatively strings and objects under the same variable name. This actually opens a little door to hell vulnerability, where your script will sprout demons Exceptions from some place but the culprit will be in an entirely different script. Source: I inherited from a script that does that everywhere.
I have a web application that is using a framework where I have to implement an interface named Plot:
interface Plot {
Image getImage();
String getTitle();
}
I know the framework calls the getImage() before the getTitle(). In some cases, I need the results from the image generation in order to create the title.
I know if I do something naive like this:
class MyNaivePlot implements Plot {
private String title;
public Plot getImage() {
title = "...";
}
public String getTitle() { return title; }
}
Then I could introduce a race condition. It seems I can fix this by using a ThreadLocal but I haven't seen enough examples to know if my solution is correct (and these sorts of things are hard to test with certainty). So here's what I've come up with:
class MyThreadLocalPlot implements Plot {
private ThreadLocal<String> title = new ThreadLocal<String>();
public Plot getImage() {
title.set("...");
}
public String getTitle() {
return title.get();
}
}
Is this sufficient? Am I using ThreadLocal correctly? Note that I only need the title to hang around long enough until it is called for by getTitle(). I don't care what it's value is after that nor before getImage() is called.
Also note that I believe the framework "long lives" the MyPlot object, and a new one isn't created for each request / thread, otherwise this would be a non-issue.
Thanks!
To directly answer your question - it sounds ok.
However, I would consider some additional points:
(1) If you have a hook for a beginning/end of request - you might want to clear the thread local at the end of each such request (e.g. if it's a servlet I'd use a filter). That's for two reasons: release it for the garbage collection, and for cases of errors (so that if the next request runs into some parsing error, it will see an empty image and not the previous user's).
(2) Make sure your framework indeed guarantees a single thread (and same machine) during those 2 requests. Perhaps also check if it's going to work on upcoming versions, and on horizontal scaling/clusters.
(3) As a side note, one might also consider other solutions - e.g. a cache (which would help you as a side effect). Obviously this requires some though as to cache size, periodical clearing/updating etc.
You code is quite right; you don't have a setter method but I guess there is a typo and instead of getImage you want to write setTitle().
threadLocal has also a remove method that you should invoke when you don't need the title attribute anymore. You could find some usage examples here and here
Before deploying a ThreadLocal based version of Plot I suggest you to check if your framework create one o or more instances; simply create a regolare class with a counter and increase the counter value in the get method; you can log it to see how the counter value changes with different calls. If you use a logging framework such as log4j or logback I suggest to put the thread name in the log so you can check how/if the counter value changes with different checks.
I also suggest you to test it with multiple clients concurrently, if you have a "serial client" you may end up using always the same server thread if you are using a dedicated test instance.
I can call variables 2 ways.
One is just to do it like this:
MyClass myClass = new MyClass();
myLocalVar = myClass.myVarVal;
And the other way is to use a getter like this:
myLocalVar = myClass.getMyVarVal();
Both ways are working fine, but I was wondering what would be the most efficient/proper way of doing this?
Thanks
Both techniques are terrible, but using the getter is the common (and safer) practice.
In order to access a public data member (a.k.a. public field or public property) of a class, you must know the implementation details of the class (the data member name and the data member type). This is a bad thing; it breaks the OOP concept "information hiding" and increases "coupling".
Using a getter is also bad (as in a bad OOP practice) because objects are not just wrappers around data; objects are supposed to encapsulate functionality and data. "store this here value so I can get it later" is not functionality; it is hoot functionality (as in a monkey in a cage hooting). Getters are; however, an accepted practice in java (and other OOP-lite languages like c++ and c#).
Lest you think I am some ivory tower purest, of course I use getters; I use java, so I use getters.
Getters are fine for getting the work done (no pun), just don't walk around believing that "I R gud OOP Prgmr", because if you use getters you are not a "good oop programmer", you are just a programmer who gets work done.
Edit: Perhaps a better way.
The better way is to not use getters, but to instead design your classes so they expose functionality not data. In practice, there is a point where this breaks down; for example, if you need to display an address on a JSP page, you put a bean in the request (or session or blah) with the address and expose the values using getters. A "more oop pure" way would be to put a bean that exposed "display the address on a jsp" functionality.
Edit2: Perhaps a better example.
Say I work for a phone company, in the USA, and I have an object that represents a customers phone number. This might look like the following:
public class CustomerPhoneNumber
{
private String npa; // numbering plan area (google search nanp for more details)
private String nxx; // exchange.
private String serviceNumber;
public String toString()
{
return "(" + npa + ") " + nxx + "-" + serviceNumber;
}
public boolean equals(Object object)
{
... standard equals implementation (assume this works)
}
}
Now say I get a phone number as an input from a web page in the form String inputPhoneNumber. For the purposes of discussion, the class that receives this input is called "the servlet".
How can I answer this question: "Is the input phone number in my list of CustomerPhoneNumber objects?"
Option 1 is make the npa, nxx, and serviceNumber data members public and access them. This is terrible.
Option 2 is provide getters for npa, nxx, and service number and compare them with the input. Also terrible, too many internal details exposed.
Option 3 is provide a getter that returns the formatted phone number (I called this toString() above). This is smarter but still terrible because the servlet has to know the format that will be used by the getter and ensure that the input is formatted the same way.
Option 4 (I call this "Welcome to OOP") provide a method that takes a String and returns true if that matches the customer service number. This is better and might look like this (the name is long, but sufficient for this example):
public boolean doesPhoneNumberMatchThisInput(final String input)
{
String formattedInput;
String formattedCustomerPhoneNumber = npa + nxx + serviceNumber;
formattedInput = ... strip all non-digits from input.
return StringUtils.equals(formattedCustomerPhoneNumber, formattedInput);
}
This is the winner because no implementation details are exposed. Also the toString can be used to output the phone number on a JSP page.
StringUtils is part of Apache Commons Lang.
For the sake of encapsulation you should always go with the second alternative.
myLocalVar = myClass.getMyVarVal();
Efficiency wise you most likely won't notice a difference.
Do ALWAYS use getter and setter to access your properties!
You should also take a look at this.
myClass.getMyVarVal() is slower since it is a method call and so it creates entrance on the stack for return value, etc. But it is better OOP practice to use getters.
Just create object and object.variablename; or object.methodName(); can be used to make non-static reference...no use of getter is required.
myLocalVar = myClass.getMyVarVal();
it will be good to use it if you are working with OOP concept
Tomcat + Heroku + Maven project:
How to reference Main class static variable:
HEROKU_PRJ_FOLDER\src\main\java\servlet\HelloServlet.java:
import launch.Main;
String my_str = Main.TEST_STRING;
HEROKU_PRJ_FOLDER\src\main\java\launch\Main.java
package launch;
....other imports here....
public class Main {
public static final String
TEST_STRING = "[TEST_STRING]";
public static void main(String[] args){
...somelogic...
};
};
This will probably work for any Tomcat project,
but I did this using Tomcat+Heroku+Maven. Posted answer because
the closest question I could find was this, which I already knew
how to do, just the exact import paths I found a bit confusing for
my particular problem.