Skip to content
This repository has been archived by the owner on Nov 23, 2021. It is now read-only.

Support for Applitools Eyes #174

Open
yohannesalazar opened this issue Apr 18, 2017 · 10 comments
Open

Support for Applitools Eyes #174

yohannesalazar opened this issue Apr 18, 2017 · 10 comments

Comments

@yohannesalazar
Copy link
Contributor

yohannesalazar commented Apr 18, 2017

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 ?

  1. 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();
       }

   }

}
@yohannesalazar
Copy link
Contributor Author

yohannesalazar commented Apr 18, 2017

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

@mkrzyzanowski
Copy link
Contributor

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 ;)

@yohannesalazar
Copy link
Contributor Author

Hi Michał ,

Thanks for that and will give it a go based on your advise and will let you know how it goes:)

@yohannesalazar
Copy link
Contributor Author

yohannesalazar commented Apr 25, 2017

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 ????

@yohannesalazar
Copy link
Contributor Author

Hi Bobcat star .. any update on this question ?

@mkrzyzanowski
Copy link
Contributor

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.

@yohannesalazar
Copy link
Contributor Author

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 mkrzyzanowski changed the title adding applitools? Support for Applitools Eyes Jan 8, 2018
mkrzyzanowski added a commit that referenced this issue Aug 20, 2018
@DeChrish
Copy link

DeChrish commented Jan 6, 2020

@mkrzyzanowski Can you pl prioritize this PR. We are planning to do a POC on Applitools in this quarter.

@DeChrish
Copy link

@mkrzyzanowski Any ETA to merge the Aplitools module?

1 similar comment
@DeChrish
Copy link

@mkrzyzanowski Any ETA to merge the Aplitools module?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants