Selenium/Selenide: test code refactor for presence of shadowroot - java

I'm working on an automated tests project, where I create UI tests with Selenium/Selenide in java for a web-based media player, that is then integrated in other products of my company. However, there was a UI for that Player (as a React component) in the application my team is developping before there was a UI for the Player itself, in standalone. So, basically, I have to redesign the code that I had for both the application and the standalone Player: the goal is to create the code in the Player package, to then import it to the application test project.
The problem here is that, in the standalone version, the Player HTML code contains a shadowroot, and the Player React component in the main application does not. This means that I have to use WebElements in the standalone version, whereas I am to continue using SelenideElements in the main application test code (to be able to deal with some particular interactions that occur in the main application and that are not possible in the standalone Player).
Normally, for each "part" of the Web page, I create a "Client" class that contains the methods to find the elements, and then to perform the interactions with them and/or verify their state. Since the two UIs have the differences I explained above, I imagine that I will have to have two different sets of Client classes. I was thinking of doing something like creating another class or an interface to try to find the shadowroot element, and, depending on whether it was found on the HTML code or not, initialising one of the two sets of clients.
So, my question is, how can I overall structure all of this in terms of classes/interfaces/methods, so I can have as little doubled code as possible in both Client sets?
Any help is welcome, even if it's just to show me that I'm thinking about this in the wrong way.

Whenever I hit such a case
Since the two UIs have the differences ... I will have to have two different sets of Client classes ... creating another class or an interface to try to find the shadowroot element, and, depending on whether it was found on the HTML code or not, initialising one of the two sets of clients.
and especially for as little doubled code as possible in both Client sets, in my experience Strategy provides quite suitable solution. It defines a family of algorithms, encapsulate each one, and make them interchangeable. Also lets the algorithm vary independently from clients that use it. So, you may think for the algorithms to be your test steps and the clients are the apps loaded.

Related

Best way of reusing Java classes across different projects?

I am currently writing Selenium WebDriver tests for a variety of websites each using the same proprietary framework.
Because of this, there are many test cases that can be quite similar across different websites. As such I have made my test classes as generic as possible and made it so that every XPath/CSS Selector/ID used to locate elements is defined in a Constants class, which is unique to every project.
But, in some cases, the code for the same test can be the same across different websites, since I wrote them generically.
In addition each test is a direct/indirect extension of a BasicTest class which contains code that is likely to be reused by different tests (ex: WebDriver instance declaration, etc)
The way I thought about setting my test structure was the following:
one generic project that is "reused" by each subsequent project;
one project per website with its own definition of the Constantsclass and a TestSuite class that it can use to run both generic tests and tests specific to itself.
This would allow me not to have copies of these generic tests in each of my test projects.
The problem is that I don't really know how to set this up. The GenericProject is going to contain tests that require variables from Constant, but it makes no sense to have generic Constants. Plus, will I be able to call those tests inside my website project-specific TestSuites? If I redefine Constants in each specific project, will those constants be used for the generic tests defined in GenericProject?
How can I even set it up so that I can reuse Project A's classes inside of Project B, C, D... etc?
Extract your constants to a properties file which exists in each module as src/test/resources/common.properties.
Use org.apache.commons:commons-configuration2 PropertiesConfiguration to read this file. It will handle nested properties just fine.
Common code can be shared by depending on your GenericModule. Official instructions for two models of doing this (extract common tests to a new module or use a test-jar) are here
In general in order to reuse code over projects you would create a library containing the reusable code. In order to do so you'd need to think about a suitable API for the library.
This contains decisions about:
How will functionality be called from dependent code
How will dependent code provide required data.
If you are using constants for e.g. CSS selectors, that are different but have the same semantics, e.g.
root frame
side panel
main area
...
you might want to define an interface that the dependent code can provide. This could look like:
interface CssSelectors {
String rootFrame();
String sidePanel();
//...
}
If you are building this for tests you might also want to use features of your test framework (e.g. Rules in JUnit).
When reusing code in tests you also should consider another aspect:
If s.o. reads the tests written with your library, will she be able to sufficiently understand what is happening behind the border of the library to understand what the test is all about? This is a lot more of a question when dealing with test code than with production code as for test coverage and validity of tests it often matters a lot more how a setup or verification is done than is the case for production code.

How to share entity between REST service between two microservices?

I have created two micro-services using java. I need to make a REST api call from service A to service B. The data sent will be in JSON format. Using jax-rs I need to create entity class in both the service.
Since both the entity class be same in both the projects. Do i
Create an common jar and use is for all my entity/domain objects? Does this make my microservice more tightly coupled?
Do i create the same class in both the microservice projects? This will just mean repeating the work in both the projects?
Is there a better way to communicate between the sevices?
In terms of having your two micro services independent and having them also independent in the future I would also duplicate the code. We had the exact same situation before. Several microservices seem to use some "common" classes that can be put to a seperate jar.
In the end we had following situation:
several (5+) services using the same JAR
turned out that classes that we thought are the same, seemed to have slightly different semantics in different services
a change on one of the classes more or less forced us to have a release on every microservice, when it came to releasing (no independency here anymore)
developers tend to see "common" behavior everywhere, so you most likely end up with some "Helper/Utility" classes there as well which is in the meanwhile considered a code smell in OOP
Long story short, in the meanwhile we switched to having the code duplicated, which gives us the freedom to handle our mircoservices really independently, as we only need to stick to the service contract. What happens internally is fully up to the service and we don't have to release all services in the end of an iteration. I'm not saying that the other option is wrong, but it turned out that it was not suitable for us. If you really see common classes between two services and you are sure you don't mess your common library up with other crap, your save to go.
EDIT
Maybe as follow up, we had the same discussion in regards of tests (unit and integration) having share test code in some common classes. In the end this was hell, as every slight change in code or acceptance criteria made 50% of tests fail. Meanwhile our strategy is to not share anything on test level and have everything right at the tests place. By that you are super fast in eliminating or changing tests. In the end the lesson for us was to keep business code as clean and elegante as suitable and the test code in a way to give us the least headache possible.
Edit2
Meanwhile, we define all our REST interface with open api specifications and create the actual DTO objects that are exchanged via the maven plugin openapi-generator. The spec resides in the project that implements the interface and it is published to artifactory. The project implementing the client pulls it and creates DTOs based on that. By that, you have a single point of truth and no need to write DTO boilerplate code.
I'd say it depends on the situation. If you use a shared package, this will introduce a coupling between the two projects. This makes sense, if both of the project build up on the same data classes and therefore will have the same dto objects to work with. Ideally you would have your own nexus which simplifies the usage of the shared artefact.
Otherwise, if only a few classes are redundant I probably would implement it in each sevice separately, which decouples them too.
I am afraid that you need to decide which one the right solution is for your project.
This is common situation where we as developer gets confused. I would suggest to have a common jar(shared) which can be used in both micro services (A and B). It is nothing but sharing a third resource as we use third-party libraries.
In my current project we were in the same situation and we found the best approach to have separate shared libraries(api-shared as name) and consuming it as jar in different micro-services.
In your second approach you ended up with redundant code and also difficult to maintain. Lets say if you have any changes in entity then you have to change in both the entities which is not quite a good way to synchronize the thing.
All in all I would suggest you to use shared jar for both micro services.
Regards
Techno

How should I structure the test automation code for two different versions of an application

The web app that I'm writing automated tests for (selenium + java) has two versions. Depending on the version there are different locators and also some layout differences like a pop-up in one version of the application and the lack of it in the other. Basically making another class with different locators won't suffice as there will be some new methods as well.
I'm thinking what the best approach to structure the code would be. Namely, should I create one abstract class and then extend it with two classes, one for each version of the app ? Or maybe make some if/else/switch statements in the methods where different implementation is needed ? What is the general approach in such cases ?
Managing different branches for same functionality leads to maintenance overhead in longer run. Prefer handling the situations conditionaly.

How can I split my Java Selenium tests into separate classes?

I'm currently working at my job to perform GUI testing of our web page using Selenium 2 via Java in Eclipse. I've been trying to program my tests in such a way that I maximize the amount of code I can reuse and as a consequence I now have a lot of helper methods that function almost like a framework. This has lead to my test class becoming fairly bloated with only one method used as the actual test and the rest being the implementation of the test.
Currently I just run the testing right from Eclipse with all my methods being static.
From what I understand there are a couple different ways I could try to separate things out:
One way would be to put all the methods into a class I use as a framework and extend it when writing an actual test, but I don't know if having a framework in a framework (Selenium) makes sense.
Another way would possibly be making my helper methods into an object where I can have one of these objects for each test. I don't know if this is good practice though, or if it will cause problems down the road. It would also mean I'd have to type more to do the same amount of testing.
My main questions are:
What's the best way to split up my testing class into test classes and an implementation class?
Is what I'm doing outside the intended usage of Selenium?
The best practice is that create a page object model for each web UI.That will help you to access the web element easily.selenium provide that feature and you also have to do some R&D things.
Home_Page.lnk_MyAccount(driver).click();
LogIn_Page.txtbx_UserName(driver).sendKeys("testuser_1");
LogIn_Page.txtbx_Password(driver).sendKeys("Test#123");
And put all selenium related actions into a one class.like Action.click(),Action.search(), or what ever your common set of actions.
Next thing is that reusable code implement via a function.let say login(usernName,Password) then handle the login code inside that.and you can reuse thease codes in your other places.always try to modularize your implementation.

How to manage a proper structure in a java project

I have encountered with this problem often. Couldn't think of a way to how to face this. Now I got this excellent forum!! I'm sure experts here will help me with this.
This is not a problem about a specific code segment like thing. I am capable (as I think) of doing some advance projects in java. It means, simply, I can finish the project to give the exact result.
But the problem is, though I can finish it some how, I'm not satisfied with the management of the classes etc. Actually I don't know how to properly manage it. I'll explain considering the project I'm currently working on (I'm not a professional coder, this will be for my self learning).
I'm working on a database management system (MySQL + Java). There I'm hoping to implement several features there. The flow will be, roughly, like this.
1. Login
2. Main window
Main window will be like this.
In the left panel you can select what you need to do.
Eg.
*. Add some entries to the database
*. Search database
*. Other..(will be add later)
Can some one please tell me how to manage all those things, two frames and several panels.
What I've done is like this.
I've written a managerClass which has the main method. Then It'll call loginFrame first. After validation, loginFrame calls a method in managerClass, to load mainFrame. But I keep a reference to the managerClass in all the frames, panels etc.. as I save all the required info in managerClass, like user name ect..
But when modifying and debugging, things become really really difficult. As I haven't done thing according to any specific rule. I'll have to modify almost all the classes to do a slight modification. I've though a lot and sea
From what I can understand of your application, your main issue is the coupling between your components and the different layers of the application (presentation, interaction control, domain logic). I would suggest using two design patterns (or styles) that may help here:
Model-View-Presenter: separates the Model/Domain logic from the presentation (View) from the logic of controlling user interactions. I've used it recently in a large application and I've found it really helps to separate concerns in a clean way and makes testing much more simple. Please don't confuse it with the Model-View-Controller model, which is close, but have many issues. There's a nice article by Martin Fowler describing these two patterns
Adopt an event based interaction between your components. Instead of the Login frame calling the Manager class, make it fire an event ("user authenticated"), which is handle by the interested components. For example, you may have a small user account details panel in the main window which is not displayed until this event is triggered. Unfortunately, I'm not aware of any event framework for plain Java (which I suspect if the what you are using for development) The one I use is for Google Web Toolkit.

Categories

Resources