Ok selenium gurus a bit of an open question here. I am looking for some guidance on the best way to organize my tests that use object oriented principles.
At the moment I am creating a testrunner main class from which I create an object of a general test class. I am then extending this class for more granular tests.
An example.
I need to open the browser, enter the url, log in as a user.
From there you can access perhaps 40 different links each containing their own pieces of functionality. E.g. A profile link which leads to a profiule screen where you can enter introduction text, upload a picture, change a picture etc...
Another example would be a notification screen where you can navigate to view and mark as read etc...notifications you have received.
I can write the code to test this by for example by creating a ton of methods in that 1 class and then calling these from the main testrunner class. There has to be a better organized way where I can have a separate class for functionality but wont I then have to create a new object for each test?
Sorry about the confused post I'm trying to learn Java thoroughly and selenium also.
EDITED
I have copied the process of creating a page object hybrid model that is documented in the YouTube video:
https://www.youtube.com/watch?v=gxwh8D_tx-0
I created a Pages package which contains all of the Page specific class such such ProfilePage, NotificationPage etc...
I have a second package which contains the tests and a testbase class which generates the driver object, opens the browser.
I want to get to the stage where in my tests class I can have a specific class for a test for example:
class test_that_user_can_upload_profile_picture
When I create such a class I have methods inside the class such as: test_that_navigation_to _profile_page_successful()
test_to_upload_valid_picture()
Should such navigation methods be inside this class?
Also I find that in order to access my methods from a package I need to mark my methods as static. Is this ok? I noticed on the youtube video the instructors methods were not static. Looking at the setup I dont quite understand why I cant access the methods unless I mark them as static. The error i get is
"Cannot make a static reference to a non-static method"
Here is my setup:
Also Im finding that in my ProfilePageNavigation class I have a bunch of methods that run in a specific order based alphabetical order.
Is it simply the case I should just have 1 method in each test class and just call the page classes methods(or any other pertinent class) to execute this test? If it is just 1 method inside each test class then wouldnt I have too many test classes each with a name like (for example) upload_valid_profile_picture with a method using the same name? and then another class with upload_invalid_profile_picture with it's method. I dont want to go down that path - how do I resolve that?
Also all my Pages class methods have to take WebDriver driver as a parameter is there any way around this - it is a lot of duplication.
If you could point me on the right track and let me know in it is ok to have the pages class methods as static it would be appreciated.
I guess I just want to know whether I am on the right track or going down the wrong route at this early stage.
#tarquin - you can find many articles on that #web, There are multiple ways to handle your code and work with it, my way is :
Create a objects repository in notepad or excel, from where you can pick/change/manage all your objects.
Create a class with all re-usable methods.
Create a class of your tests.
Thanks
Keshav
Related
I have a javafx application which has a few fields, like an anchorPane. In its .fxml file, that anchorPane has a few fields like these
How can I test these values? I'm sure that JUnit can test object values, so I was wondering if I can make something like
Assertions.assertThat(mainAnchorPane.getId()).isEqualTo("mainAnchorPane");
Not sure but that might be as simple as instantiating an entity class (lets name it Person) and do something like
Person person = new Person("Maria");
Assertions.assertThat(person.getName()).isEqualTo("Maria");
The point here is that I'm not sure how can I inject the object values from my class into the tests, assuring that Person (or AnchorPane) from my class has the same values in my test.
Any thoughts?
Thanks in advance!
I don't know if you already thought about this, but there is a test library called TestFX. It is made to test JavaFX applications easily. Maybe it can help you:
https://github.com/TestFX/TestFX/
For example you can proof the input of textfields or simulate mouse clicks. You can find more information on the given url.
These aren't the real classes but it's the best I can come up with that describes my struggle.
I'm using classes: Library, Book, Page.
The library class manages (adds/removes) all the books.
The book class contains a collection of pages. The book may be open at any time and the book knows which page is currently active.
The page class KNOWS when it has reached the end of the page, therefore, knowing when to turn to the next page. However, the turn page method is located in the Book class.
How can I accomplish this? How can the Page class communicate with the Book class? I feel like calling a method inside the Page class defeats the purpose. For example Page#turn would call Library#getBook#turnPage.
The page class is an abstract class because pages may be longer than a certain size and I am making it as flexible as possible for other people in the team to create pages and append them to a book:
Page Class
public abstract String getContent()
public abstract boolean hasReachedEnd()
What I've tried:
At first, I switched Page to be an inner class of Book. However, I had to revert the change. Consider SuperLongPage extends Book.Page. I must create a Book class in order to create a page. The idea was scrapped but I really liked how I was able to call Book#turnPage.
I also tried to make them both dependencies of each other (not sure what this term is called). Book has pages and Page has the book it is part of. In this way, I was able to invoke the Book#turnPage but it felt like I cheated and didn't feel right. Am I right by doing this or should I not do this?
I also tried calling a method Page#endReached that took the parameter of a Book class. The method would check if it was a part of the book class and then it would call book#turnPage inside this method.
What are the other suggestions?
EDIT: I solved this issue by using the Observer pattern as noted by #buettner123 in the comments.
I am involved in multiple projects in my company for manual testing. When we have so many test cases in the project we have to automate regression suite for those. Now problem is I have to have a portable framework that work for any project I move to. I simply import my java project(as existing maven project) and start executing selenium test cases after writing them. As of now, this is how I am doing but I don't know if this the optimum way or not.
I create a maven project, which gives, few source folders ready to use./myproject/src/main/java and /myproject/src/test/java.
In /myproject/src/test/java folder I create a class which has setup() and teardown() methods.
I create another class by the name "Define" where I define variables/string/class objects example:this class has WebDriver driver; or UserLogin userlogin = new UserLogin();
I create more classes in /myproject/src/test/java by the name of functionality let say "CreateZoo" and extend them with Define class. Later I use methods of these classes in classes inside /myproject/src/main/java, for example: A class of Main package would be "DailyTests" and I call methods here from classes inside /myproject/src/test/java
Apart from this I keep chromedriverexe, properties file, data.xls in main>>resources folder.
I also have CommonFunctions class extends Define in /myproject/src/test/java, here I have written common java functions that I use frequently like :
class CommonFunctions extends Define {
/*
*
* Click linktext, click partial, name,id,xpath,css, classname
*/
static class clik {
static void txt(String locator) {
new WebDriverWait(driver, 60).until(
ExpectedConditions.presenceOfElementLocated(By
.linkText(locator))).click();
}
and another common fucntions class for myproject like: I have written a long method for user login and I call it where ever I need it.
So, the way I am doing above is good or should I have classes by the name of each page, for example "LoginPage.java"
This class would've html elements defined using pagefactory(as of now I am not using page factory.)
I am a selenium2.0 aspirant , I don't have much experience on it. How to beautify code and create/maintain selenium projects?
Your code structure is fairly optimal.
But I do have some suggestions:-
In my opinion, maintainability of test code can be improved we you define classes based on pages instead of functionality.
Consider a scenario where you have to click on manage account>edit>change address. There can be a similar scenario where you have to click on manage account>edit>change username. In both the scenarios the first 2 steps are same. But they have to be written twice one in ChangeAddress Class and other in ChangeUserNameClass. If property of edit changes, we have to change the code in places. So less maintainability and redundant code.
This can be avoided by defining classes according to functionality. Class1 contains clickManageAccount(), Class2 contains clickEdit() and Class3 contains clickChangeAddress() and changeUserName().
So it is just a matter of assembling the methods above methods in a Junit class based on the functionality.
This will ensure each Test is modular and maintainable. Also page factory can be efficiently used in each class.
Please consider the following folder structure :-
/myproject/src/test/java/page - Contains all your page classes which extends define class
/myproject/src/test/java/common - Contains all common classes and define class
/myproject/src/test/java/scenarios - Contains JUnit test class with #Before[setUp()], #After[tearDown()] and #Test methods. #Test Methods use methods in page classes to assemble the required methods for a particular scenario.
/myproject/src/main/resources - Contains resources like chromedriverexe, properties file, data.xls
/myproject/src/main/java/ - Contains classes like DailyTests which use classes in /myproject/src/test/java/scenarios
This is just my thoughts. Please do revert back with your ideas on it.
I'd look at implementing cucumber (with Selenium): http://cukes.info/
It'll make your code OO, cleaner, and easier to maintain and read.
So I have an interesting conundrum I was curious to get some feedback from other Webdriver framework architects. Currently I follow a pretty standard execution model:
baseobject
pageobject (extends baseobject)
Junit testobject (references one or multiple pageobjects)
Within my pageobjects I chose to define my findBy UI mappings as variables, and in-turn reference them within the various methods I write for that pageobject. I find this works very well. However, one item I am waffling on is how to handle method design for pages (and their respective pageobject) when there exist potentially 50 separate hyperlinks.
My inclination and design thus far has been to create methods (I think of them as services really) for each link on most pageobjects I've created so that #Test I can simply call the method I want and be done with it. This eliminates the potential for test maintenance...standard practice I know. But I am now trying to decide...does it make sense to create 50 methods, one for each link for a page object, or do I go against my wishes and pass in linktext from the test itself, feeding into a single method that builds the findBy using that passed in parameter.
On one hand there is way less code within the pageobject, but on the other, tests become more brittle. There is potential for these links to be references in hundreds of tests.
Here is a brief example of my model:
classname extends baseobject{
By someLocator = By.linkText("some text");
By someOtherLocator = By.linkText("some other text");
By andAnotherLocator = By.id("someid");
public void someLinkMethod(){
driver.findElement(someLocator).click();
}
public void someOtherLinkMethod(){
driver.findElement(someOtherLocator).click();
}
public void someidMethod(){
driver.findElement(andAnotherLocator).click();
}
}
Thus we come to the end of the question. This model works great for test design. My services (methods) are insulated and easily maintainable. But what would I do if there were 50 UI mappings for links instead of 2 as I have shown above? I toyed with the following design, but really dislike it #Test:
public void selectFromLeftBar(String barItem){
driver.findElement(by.linkText(barItem)).click();
}
Any thoughts would be greatly appreciated!
Do it in your page object class. Here are the reasons:
What does your code do if your page changes the link text? You have to go into each test and change that text, even if the link does the same thing.
What happens if your page removes that link? You are stuck with the same problem, namely, having to find each time you call that link. If its a method...then you delete the method, and your IDE notifies you of each instance that you used it.
Finally, you are providing a standard interface for the test. If you make an exception here, what would stop you from passing other things into your page?
As a side note, I would recommend only mapping elements that you are going to use. I've found that if I map out every element I could possibly ever need then I end up with a massive class filled with fluff and less time on my hands.
OK, so before we start let me state that I have been googling and searching for an answer to my question for quite a while now and haven't been able to find a suitable one (the keywords are tricky since I keep getting unrelated posts and sites as results).
Now, moving on I have a Java class that contains a my main method and a number of other functions. I want to test these functions using JUnit but I can't instantiate a class that has main in it, if I simply try to call the function I get an error saying the function is outside the namespace even though both files are in the same package, and I get an error trying to import the file.
Is there anyway to test these functions using JUnit?
P.S. Yes I know that you can put them in a new class, but I don't think it is overkill to create a new class just for testing or to put in 2 functions that are for parsing user input, and there is still the issue of testing the main function itself (and it is not uncommon to write a main method just for testing).
So this is what happened. Since I don't use Java very often I ended up creating private data members in the class but treated them as I would globals in a C++ program. In consequence I initialized them in main and didn't think of making a constructor and hence the problem with instantiating the class. When that didn't work I tried the . form but since the methods referenced the private data members I would get an error without instantiating the class. Thanks to the guys that noticed the constructor thing.
You absolutely can create an instance of a class which contains a main method, so long as it has an accessible constructor of course.
Likewise you absolutely can call a static method directly, using MyClassName.myMethodName.
Having a main method in a class makes absolutely no difference to it in terms of the Java language itself - so you can test it just as you would any other class.
Very strange. I just wrote SomeClass with main inside and it's perfectly testable by SomeClassTest class.
Just a thought, did you declare constructors as private in the class with main method? It will help a lot if you can post some code snippet and exact error message you're getting.