Selenium - difference between @FindBy and WebElement.findElement()

22,541

Solution 1

First of all, you cannot use such a convoluted xpath, that kills the readability of your page objects. Your selectors should be as much concise as possible. Secondly, you should not use XPATH and use CSS selector. Now coming back to your question,

 @FindBy(css="span[class*='ui-icon-triangle-1-n']")
 WebElement b;

or try

 @FindBy(css="span[class*='ui-button-text']>span[class*='ui-icon-triangle-1-n']")
 WebElement b;

Solution 2

EDIT: You have two XPath selectors of //a[contains(@class, 'ui-spinner-up')][1] in your first example, but only one in your second...that may be causing your problem.

Share:
22,541
joshi737
Author by

joshi737

Updated on July 09, 2022

Comments

  • joshi737
    joshi737 almost 2 years

    I am using Selenium to Test my User Interface.

    I am trying to use the @FindBy-Annotation. The following piece of code works fine:

    @FindBy(how=How.XPATH, xpath ="//input[contains(@id,'idOfInputField')]")
        private WebElement someWebElement;
    
    private void someMethod(){
        WebElement a = someWebElement.findElement(By.xpath("//a[contains(@class, 'ui-spinner-up')][1]"));
        WebElement span1 = a.findElement(By.xpath("//a[contains(@class, 'ui-spinner-up')][1]"));
        WebElement span2 = span1.findElement(By.xpath("//span[contains(@class, 'ui-button-text')][1]"));
        WebElement b = span2.findElement(By.xpath("//span[contains(@class,'ui-icon ui-icon-triangle-1-n')]"));
        b.click();
    }
    

    I would like to use the following code, because it is Annotation-based, but it doesnt work, although I think it is exactly the same:

    @FindBy(how=How.XPATH, xpath ="//input[contains(@id,'idOfInputField')]"
            + "//a[contains(@class, 'ui-spinner-up')][1]"
            + "//a[contains(@class, 'ui-spinner-up')][1]"
            + "//span[contains(@class, 'ui-button-text')][1]"
            + "//span[contains(@class,'ui-icon ui-icon-triangle-1-n')]")
    private WebElement someWebElement;
    
    pivate void someMethod(){
        someWebElement.click();
    }
    

    What I get is the following exception:

      java.lang.RuntimeException: Cannot invoke click on element null. Cannot find it.
        Cause: org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"xpath","selector":"//input[contains(@id,'idOfInputField')]//a[contains(@class, 'ui-spinner-up')][1]//span[contains(@class, 'ui-button-text')][1]//span[contains(@class,'ui-icon ui-icon-triangle-1-n')]"}
        Command duration or timeout: 14 milliseconds
        For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
        Build info: version: '2.32.0', revision: '6c40c187d01409a5dc3b7f8251859150c8af0bcb', time: '2013-04-09 10:39:28'
        System info: os.name: 'Linux', os.arch: 'amd64', os.version: '3.5.0-28-generic', java.version: '1.7.0_21'
        Session ID: 92f605a1-0a63-4ba0-b290-ca724b3c6386
        Driver info: org.openqa.selenium.firefox.FirefoxDriver
        Capabilities [{platform=LINUX, databaseEnabled=true, cssSelectorsEnabled=true, javascriptEnabled=true, acceptSslCerts=true, handlesAlerts=true, browserName=firefox, browserConnectionEnabled=true, nativeEvents=false, webStorageEnabled=true, rotatable=false, locationContextEnabled=true, applicationCacheEnabled=true, takesScreenshot=true, version=20.0}]
            at path.to.package.utils.StaleReferenceAwareFieldDecorator$StaleReferenceAwareElementLocator.in
    
        voke(StaleReferenceAwareFieldDecorator.java:86)
                at com.sun.proxy.$Proxy9.click(Unknown Source)
                at 
        ....
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
                at  
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:601)
            at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
            at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
            at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
            at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
            at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
            at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
            at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
            at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
            at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
            at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
            at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
            at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
            at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
            at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
            at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
            at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
            at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
            at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
            at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
            at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
            at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
    

    Can some body explain whats the reason for this behavious or if there is actually a difference between those two pieces of code?