When I was using Java + selenium I was used to create interfaces for Page Objects and then I use for example Spring to bind specific implementation to abstract interface.
My files could look like this:
src\main\pageobjects\MyPageInterface
src\main\pageobjects\MyPageWebImpl
src\main\pageobjects\MyPageMobileImpl
src\test\Test
So I was able to wite one test and run it against two different implementations (in this case one for desktop and one for mobile).
How I can do this in Geb using Geb page object http://www.gebish.org/manual/current/#pages?
Spock's data driven tests should be be able to run the same spec against different implementations.
http://spockframework.org/spock/docs/1.0/data_driven_testing.html
Related
Does it wrap around Selenium and provide a simpler or different method of invoking the functionality of Selenium?
I looked it up on Google and the best information I could find was this one https://www.ontestautomation.com/using-wrapper-methods-for-better-error-handling-in-selenium/.
This doesn't explicitly explain what a Selenium wrapper is but gives enough information to help understand what it is.
One of the definitions of a "wrapper" is:
In the context of software engineering, a wrapper is defined as an entity that encapsulates and hides the underlying complexity of another entity by means of well-defined interfaces.
So, any custom code you might use that implements Selenium code could be understood as a wrapper.
For example, Katalon Studio is a testing tool that uses Selenium under the hood i.e. Katalon's WebUI class methods are a wrapper around Selenium methods. The following two pieces of code are equivalent - they do the same thing:
Selenium (and Java)
WebElement element = driver.findElement(By.cssSelector("css-selector-of-the-element"));
element.click();
Katalon
WebUI.click(testObject) //testObject defined elsewhere
This is just a simple example, but it shows how can you hide complexity behind simpler commands.
I know this question has already been answered but I can see it was never accepted as an answer. Now, the answer above explains exactly what a wrapper is : encapsulation. Which in itself means also that it hides the underlying complexity of another entity (Selenium classes in this case).
But let me elaborate and give you an actual example.
I've built a Framework around Selenium and made a nuget package out of it internal to my company. But this is one example on how to wrap Selenium By class. Using a delegate, you can simplify a lot of the calling methods :
private delegate void ValidationMethodDelegate(By locator, int timeout = ELEM_TIMEOUT);
//This method actions a delegate for regularly used methods with a By locator parameter,
//the value of the selector and the selector type which is a built-in framework enum
private void ActionMethod(ValidationMethodDelegate delegateMethod, string selectorValue, SelectorType selectorType)
{
if (!string.IsNullOrWhiteSpace(selectorValue))
{
switch (selectorType)
{
case SelectorType.Id:
delegateMethod(By.Id(selectorValue));
break;
case SelectorType.Xpath:
delegateMethod(By.XPath(selectorValue));
break;
case SelectorType.TagName:
delegateMethod(By.TagName(selectorValue));
break;
case SelectorType.CssSelector:
delegateMethod(By.CssSelector(selectorValue));
break;
case SelectorType.ClassName:
delegateMethod(By.ClassName(selectorValue));
break;
case SelectorType.LinkText:
delegateMethod(By.LinkText(selectorValue));
break;
case SelectorType.PartialLinkText:
delegateMethod(By.PartialLinkText(selectorValue));
break;
default:
break;
}
}
else
{
throw new AssertionException($"{this.GetType().Name}::{MethodBase.GetCurrentMethod().Name}():: Selector Value : '{selectorValue}' cannot be null or empty.");
}
}
//Example on how the delegate is used
public void Click(string selectorValue, SelectorType selectorType)
{
ActionMethod(PageHelper.Click, selectorValue, selectorType);
}
The PageHelper is a static class that implements internally to the framework most of Selenium's methods with assertions and waiting implementations. I have several layers of complexity in my framework. But you can make it simple too. The method click for me is wrapped also in another class that implements two methods one that finds the element by and the other than waits for an element to appear on screen. Both are other wrappers around Selenium methods and assertions.
If you are only doing tests for one application and won't have further use of Selenium then a framework is not a solution for you. Also wrappers would be kind of redundant outside your test solution.
I would say that wrappers would only be useful in the context where you are making multiple use for it (like the click or find element, etc.)
"Wrapper" is more like a software development design pattern, which developers use in the codebase when it is necessary.
You can read more in the book:
https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_2?dchild=1&keywords=software+development+patterns&qid=1605187094&sr=8-2
In scope of automated testing, there are other terms. I will explain for mobile automation.
Driver (Espresso, UIAutomator, Robotium, XCUITest) - receive commands from test and send them to app specialized interface in understandable way
You sent a command to press a button to the GUI driver - it accepts it via API and sends to the app (and we see a tap on the button in GUI).
Another app (which is over driver, let's call it superstructure in this context) that interacts with the app under test via one or more drivers (increasing usability or increasing possibilities) like Appium, Calabash.
Frameworks (JUnit, TestNG, Cucumber) - app that allows us to prepare, launch and gather all info regarding test executions
It will look like this:
Framework -> Our tests -> Superstructure -> Driver -> GUI in our application
User guide contains following:
Usually, an extension is instantiated only once.
It's not very clear when extension can be instantiated many times? I'm supporting test suite with multiple extensions and every extension stores it's state in class fields. Everything works fine, but can I rely on this or should I refactor this code to use ExtensionContext.Store?
Usually, an extension is instantiated only once. So the question becomes relevant: How do you keep the state from one invocation of an extension to the next?
I think this sentence shall highlight that the same instance of an extension might be re-used for multiple tests. I doubt that the instance might be replaced in the middle of a test.
Multiple instances of an extension might be instantiated when a test uses programmatic extension registration (with #RegisterExtension). In such case, the test class creates its own instance of the extension. JUnit cannot reuse this instance in other test classes. But an instance created by declarative extension registration (with #ExtendWith) might be used for multiple test classes.
Some tests require running a database, for instance, using Test Containers Library. It obviously takes time to boot it up.
Is there a way to do this only once per entire Spek suite which spans across multiple files? The docs don't say anything about this.
Anyone knows why this has not been implemented?
This answer is not Spek-specific, but Testcontainers objects expose a simple start() and stop() method, meaning that you don't have to rely on the test framework to control your container lifecycle if you don't want to. You can create a container in a static object that is separate from your test classes, and then access it across all tests if you like.
Please see an example here (Java example snippet below):
static {
GenericContainer redis = new GenericContainer("redis:3-alpine")
.withExposedPorts(6379);
redis.start();
}
I would imagine an equivalent in Kotlin should be quite easy as an object (or similar).
I use JPype to build a SOAP client in my python based test platform. However, I need to extend a Java class to make a call like this:
Like
void process(Context parameter)
The type Context here is a class and to give an implementation, I need to extend Context in python using JPype.
class MyContext extends Context { //override the methods}
With JProxy functionality (in JPype), I'm able to "implement" java interfaces.
But I want to extend a class not an interface. Any help is appreciated.
This very much a limitation. JPype does not allow sub-classing.
sourceforge link
Changed the SOAP method to accept an interface in the API contract.
JPype is an effort to allow Python programs full access to Java class libraries. This is achieved not through re-implementing Python, as Jython/JPython has done, but rather through interfacing at the native level in both virtual machines.
Eventually, it should be possible to replace Java with Python in many, though not all, situations. JSP, Servlets, RMI servers and IDE plugins are all good candidates.
Once this integration is achieved, a second phase will be started to separate the Java logic from the Python logic, eventually allowing the bridging technology to be used in other environments, i.e. Ruby, Perl, COM, etc ..
I have an SWT project, where are several custom GUI elements, and i try to find a way, to build some kind of proxy on top of them, like the default ones built on top of Labels, Texts, etc. Is there a way to do this? It would be really convenient, to create a custom GuiTestObject subclass, and use it (make RFT use it?) to identify these custom GUI elements, like KTable for example, because now these controls are handled by the best class known by RFT, like Composite or ScrolledComposite, so it's impossible to expose the custom properties of these classes for testing, and the best way to test these elements is by image comparison.
If this is not possible, then is there a way, to somehow get a reference to the actual ui component from a GuiTestObject? I tried in debug mode, but it looks like, that the reference is intentionally hidden somehow. Is there a way, to bypass this, and somehow access the reference? (I couldn't see the actual ui element neither using the debugger, nor using reflection).
Any help is greatly appreciated!
The TestObject that you have available in the script should represent the actual object in the AUT.
As you said the methods exposed to the script would be limited to what is provided by the TestObject however RFT has API called "invoke" that you can use to invoke some method directly on the control.
You should find more info on invoke here: Using Invoke in RFT
Second , you should be able to extend an Existing proxy using the Proxy SDK of RFT where you can add custom behavior for the proxies
You can get more info aobut proxy SDK here:
Proxy SDK in RFT