bobcat
bobcat copied to clipboard
Support for Applitools Eyes
Hi Bobcat stars,
Am looking to integrate to Applitools for UI comparison...
can some one point me on which class I need to instantiate the webDriver as per Applitools example code below ?
-
I tried to do it within my projects like ` @Inject private Eyes eyes; @Inject private WebDriver webDriver;
public LandingPage open() { eyes.setApiKey("cR99frVt2NBrYG3NYaS9Xasasasas100N20CId5JI110"); eyes.open(webDriver, "Hello World!", "My first Appli Selenium Java test!", new RectangleSize(800, 600)); webDriver.get("http://www.bbc.co.uk/");`
But got error
cucumber.runtime.CucumberException: Failed to instantiate public cucumber.runtime.java.JavaBackend(cucumber.runtime.io.ResourceLoader) with [cucumber.runtime.io.MultiLoader@13d9b21f]
Looks like I need it to be added at bobcat level rather than my project , so please if you could direct me as you may have done POC already
Below the hello world example that works non-bobcat plain selenium
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import com.applitools.eyes.selenium.Eyes;
import com.applitools.eyes.RectangleSize;
public class HelloWorld {
public static void main(String[] args) {
// Open a Chrome browser.
WebDriver driver = new ChromeDriver();
// Initialize the eyes SDK and set your private API key.
Eyes eyes = new Eyes();
eyes.setApiKey("YOUR_API_KEY");
try{
// Start the test and set the browser's viewport size to 800x600.
eyes.open(driver, "Hello World!", "My first Selenium Java test!",
new RectangleSize(800, 600));
// Navigate the browser to the "hello world!" web-site.
driver.get("https://applitools.com/helloworld");
// Visual checkpoint #1.
eyes.checkWindow("Hello!");
// Click the "Click me!" button.
driver.findElement(By.tagName("button")).click();
// Visual checkpoint #2.
eyes.checkWindow("Click!");
// End the test.
eyes.close();
} finally {
// Close the browser.
driver.quit();
// If the test was aborted before eyes.close was called, ends the test as aborted.
eyes.abortIfNotClosed();
}
}
}
Further info !
I just tried only adding a dependency
<dependency>
<groupId>com.applitools</groupId>
<artifactId>eyes-selenium-java3</artifactId>
<version>3.1</version>
</dependency>
To my project , and with out doing any code change what so ever existing bobcat scenarios don't run ... It was only just simply adding a dependency that breaks existing scenarios that run fine before it as added! the error message is again same as below!
hope that is a clue , can some one help why ?
cucumber.runtime.CucumberException: Failed to instantiate public cucumber.runtime.java.JavaBackend(cucumber.runtime.io.ResourceLoader) with [cucumber.runtime.io.MultiLoader@28ec166e]
at cucumber.runtime.Reflections.newInstance(Reflections.java:44)
at cucumber.runtime.Reflections.instantiateSubclasses(Reflections.java:30)
at cucumber.runtime.Runtime.loadBackends(Runtime.java:98)
at cucumber.runtime.Runtime.<init>(Runtime.java:65)
at cucumber.api.junit.Cucumber.createRuntime(Cucumber.java:78)
at cucumber.api.junit.Cucumber.<init>(Cucumber.java:58)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at cucumber.runtime.Reflections.newInstance(Reflections.java:41)
... 19 more
Caused by: cucumber.runtime.CucumberException: Failed to instantiate public cucumber.runtime.java.guice.impl.GuiceFactory() throws java.io.IOException with []
at cucumber.runtime.Reflections.newInstance(Reflections.java:44)
at cucumber.runtime.Reflections.instantiateSubclasses(Reflections.java:30)
at cucumber.runtime.Reflections.instantiateExactlyOneSubclass(Reflections.java:16)
at cucumber.runtime.java.ObjectFactoryLoader.loadObjectFactory(ObjectFactoryLoader.java:28)
at cucumber.runtime.java.JavaBackend.<init>(JavaBackend.java:65)
... 24 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at cucumber.runtime.Reflections.newInstance(Reflections.java:41)
... 28 more
Caused by: java.lang.NoClassDefFoundError: io/appium/java_client/TouchShortcuts
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
at java.lang.Class.getDeclaredConstructors(Class.java:2020)
at com.google.inject.spi.InjectionPoint.forConstructorOf(InjectionPoint.java:243)
at com.google.inject.internal.ConstructorBindingImpl.create(ConstructorBindingImpl.java:96)
at com.google.inject.internal.InjectorImpl.createUninitializedBinding(InjectorImpl.java:629)
at com.google.inject.internal.InjectorImpl.createJustInTimeBinding(InjectorImpl.java:845)
at com.google.inject.internal.InjectorImpl.createJustInTimeBindingRecursive(InjectorImpl.java:772)
at com.google.inject.internal.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:256)
at com.google.inject.internal.InjectorImpl.getBindingOrThrow(InjectorImpl.java:205)
at com.google.inject.internal.InjectorImpl.getInternalFactory(InjectorImpl.java:853)
at com.google.inject.internal.BoundProviderFactory.notify(BoundProviderFactory.java:44)
at com.google.inject.internal.ProcessedBindingData.runCreationListeners(ProcessedBindingData.java:50)
at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:133)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:106)
at com.google.inject.Guice.createInjector(Guice.java:95)
at com.google.inject.Guice.createInjector(Guice.java:72)
at com.google.inject.Guice.createInjector(Guice.java:62)
at com.rx.automation.CucumberInjectorSource.getInjector(CucumberInjectorSource.java:13)
at cucumber.runtime.java.guice.impl.GuiceFactory.<init>(GuiceFactory.java:22)
... 33 more
Caused by: java.lang.ClassNotFoundException: io.appium.java_client.TouchShortcuts
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 77 more
Hi, @yohannesalazar!
Regarding your error, it seems like a problem with Appium dependencies: java.lang.ClassNotFoundException: io.appium.java_client.TouchShortcuts. I guess you have Appium added hooked up to your project? Taking a look at dependencies in Eyes, you can see that they are also including it, the RELEASE version actually - you would need to exclude that dependency.
I've integrated Applitools Eyes with Bobcat couple months ago as part of a PoC, though I was using version 1 of their SDK, which required using wrapped WebDriver instance. To achieve that, we actually improved Bobcat to be more extendable - as one of the steps, you had to implement WebDriverModifier interface (link).
Since then, I see they have released two additional SDK versions and from what I've read here this is not the case anymore - which actually could simplify some issues I have encountered using version 1 :).
Let us know if the above will solve your problems. I'm more than happy to help you out in integrating Eyes with our cat ;)
Hi Michał ,
Thanks for that and will give it a go based on your advise and will let you know how it goes:)
Hi Michał,
I had some time today to look at this , and thanks removing the dependency was one step foreword..
The error I am getting now is something like
com.applitools.eyes.EyesException: Driver is not a RemoteWebDriver (com.cognifide.qa.bb.provider.selenium.webdriver.close.ClosingAwareWebDriverWrapper)
at com.applitools.eyes.selenium.Eyes.open(Eyes.java:292)
at com.applitools.eyes.selenium.Eyes.open(Eyes.java:242)
then I tried to add
webDriver = new ChromeDriver();
this also has error
org.openqa.selenium.TimeoutException: Expected condition failed: waiting for com.cognifide.qa.bb.provider.selenium.BobcatWebDriverWait$$Lambda$44/156127720@70730db (tried for 30 second(s) with 500 MILLISECONDS interval)
at org.openqa.selenium.support.ui.WebDriverWait.timeoutException(WebDriverWait.java:80)
at org.openqa.selenium.support.ui.FluentWait.until(FluentWait.java:232)
at com.cognifide.qa.bb.provider.selenium.BobcatWebDriverWait.until(BobcatWebDriverWait.java:70)
at com.rx.automation.pageobjects.sitevisitorpage.LandingPage.acceptCookies(LandingPage.java:122)
at com.cognifide.qa.bb.loadable.hierarchy.PageObjectInterceptor.invoke(PageObjectInterceptor.java:42)
My code looks like
public LandingPage open() {
//it need to be a remoteWebdriver
//webDriver = new ChromeDriver();
Eyes eyes = new Eyes();
eyes.setApiKey("cR99frVt2NBXXXXXXXXXXXXXXXXXXXX5JI110");
webDriver = eyes.open(webDriver, "Applitools", "Test Web Page", new RectangleSize(1024, 768));
webDriver.get(publishUrl);
webDriver.manage().deleteAllCookies();
return this;
}
What it does is open two browsers , one with blank url only "data:," on url as selenium opens the page and the other have publishUrl but does not do anything , it looks like both bobcat and eye are opening one browser each ????
Hi Bobcat star .. any update on this question ?
Hi @yohannesalazar, sorry for late response!
I've investigated the issue and the problem is that Eyes require a RemoteWebDriver to be passed to the open() method (as you can see here: Eyes.java; similar issue: link). Bobcat wraps the WebDriver instance with CloseAwareWebdriver which leads to the instanceof failing.
Fortunately, we can instantiate Eyes before the wrapping is done (this capability was actually introduced as a result of the previous Eyes POC :)). The following is an example of how can this be achieved using WebDriverModifier:
public class EyesModifier implements WebDriverModifier {
@Inject
private Eyes eyes;
@Override
public boolean shouldModify() {
return true;
}
@Override
public WebDriver modify(WebDriver webDriver) {
return eyes.open(webDriver, "APP_NAME", "TEST_NAME");
}
}
and for providing the Eyes itself:
@ThreadScoped
public class EyesProvider implements Provider<Eyes> {
private static final String API_KEY = "YOUR_API_KEY"; //or better, use properties for this
private Eyes cachedEyes;
@Override
public Eyes get() {
if (cachedEyes == null) {
cachedEyes = new Eyes();
}
return cachedEyes;
}
private Eyes create() {
Eyes eyes = new Eyes();
eyes.setApiKey(API_KEY);
//here you can apply other settings for Eyes
return eyes;
}
}
The above classes require following changes in your project's Guice module:
Multibinder<WebDriverModifier> webDriverModifiers = Multibinder.newSetBinder(binder(), WebDriverModifier.class);
webDriverModifiers.addBinding().to(EyesModifier.class);
bind(Eyes.class).toProvider(EyesProvider.class);
Unfortunately, this leaves you with a problem that I've encountered during that initial POC: obtaining/generating the test name so it can be used during initialization.
Hi Michał,
I have changed my project for a few sprints and back on my this project again , sorry did not see that you have responded to this issue on appliTools ... I will be looking at it soon and follow your advice and solution ... Many Thanks and will let you know when this task is picked..
@mkrzyzanowski Can you pl prioritize this PR. We are planning to do a POC on Applitools in this quarter.
@mkrzyzanowski Any ETA to merge the Aplitools module?
@mkrzyzanowski Any ETA to merge the Aplitools module?