The NoSuchElementException
is an unchecked exception in Java that can be thrown by various accessor methods to indicate that the element being requested does not exist.
Since the NoSuchElementException
is thrown at runtime, it does not need to be declared in the throws
clause of a method or constructor.
What Causes NoSuchElementException
The NoSuchElementException
can be thrown by various classes or interfaces in Java such as Iterator
, Enumerator
, Scanner
or StringTokenizer
.
If an element is requested using the accessor methods of these classes or interfaces, and the underlying data structure does not contain the element, the NoSuchElementException
is thrown.
This can occur if the data structure is empty or if its next element is requested after reaching the end of the structure.
NoSuchElementException Example
Here is an example of a NoSuchElementException
thrown when trying to access an element of an empty ArrayList
using an accessor method of the Iterator
interface:
public class NoSuchElementExceptionExample {
public static void main(String args[]) {
List<Integer> list = new ArrayList<Integer>();
Iterator<Integer> it = list.iterator();
System.out.println(it.next());
}
}
In the above example, an element of the ArrayList
list
is requested using the Iterator.next()
accessor method. However, since list
is empty, the element requested does not exist and the operation throws a NoSuchElementException:
Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:970)
at NoSuchElementExceptionExample.main(NoSuchElementExceptionExample.java:9)
How to Fix NoSuchElementException
To fix the NoSuchElementException
, it should be ensured that the underlying object contains more elements before using accessor methods that can throw the exception. The classes or interfaces that contain these accessor methods usually have a corresponding method to check whether the object contains more elements or not.
For example, the Iterator
interface contains the hasNext()
method, which should be called before calling Iterator.next()
to ensure that the underlying object contains more elements. The Iterator.next()
method should only be called if Iterator.hasNext()
returns true
.
In the earlier example, the exception can be resolved by implementing the above:
public class NoSuchElementExceptionExample {
public static void main(String args[]) {
List<Integer> list = new ArrayList<Integer>();
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println("Continuing execution...");
}
}
Running the above code produces the correct output as expected:
Continuing execution...
Track, Analyze and Manage Errors With Rollbar
Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!
Issue
After opening up a webpage, webdriver can’t find the «name» element?
Traceback (most recent call last):
File "main.py", line 19, in <module>
driver.find_element(By.NAME,"nickname").send_keys(username+Keys.ENTER)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 1244, in find_element
return self.execute(Command.FIND_ELEMENT, {
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 424, in execute
self.error_handler.check_response(response)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/selenium/webdriver/remote/errorhandler.py", line 247, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[name="nickname"]"}
(Session info: chrome=)
Stacktrace:
#0 0x5574d3a05919 <unknown>
Here’s the HTML source I used:
<input name="nickname" type="text" placeholder="Nickname" maxlength="15" id="nickname" data-functional-selector="username-input" class="sc-gTgzIj eFnEAY" autocomplete="off" value="" aria-expanded="false">
Solution
Aan <inpt>
element is a clickable element and ideally to locate any clickable element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
-
Using CSS_SELECTOR:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input#nickname[name='nickname'][placeholder='Nickname'][data-functional-selector='username-input']")))
-
Using XPATH:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@id='nickname' and @name='nickname'][@placeholder='Nickname' and @data-functional-selector='username-input']")))
-
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC
References
You can find a couple of relevant discussions on NoSuchElementException in:
- selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
- selenium in python : NoSuchElementException: Message: no such element: Unable to locate element
Answered By — undetected Selenium
Solving problem is about exposing yourself to as many situations as possible like selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium and practice these strategies over and over. With time, it becomes second nature and a natural way you approach any problems in general. Big or small, always start with a plan, use other strategies mentioned here till you are confident and ready to code the solution.
In this post, my aim is to share an overview the topic about selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium, which can be followed any time. Take easy to follow this discuss.
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
So Im trying to I click the next button using selenium, I’ve tried with the code below, but it ends in error.
The element
<input type="submit" name="submitNext" value="Next">
My code
driver.find_element_by_name("submitNext").click()
But then it outputs these errors
Traceback (most recent call last):
File "C:/Users/thomas/PycharmProjects/test/mainapp/main.py", line 194, in
<module>
visa()
File "C:/Users/thomas/PycharmProjects/test/mainapp/main.py", line 174, in visa
driver.find_element_by_name("submitNext").click()
File "C:UsersthomasPycharmProjectsBudgetMainvenvlibsite-packagesseleniumwebdriverremotewebdriver.py", line 487, in find_element_by_name
return self.find_element(by=By.NAME, value=name)
File "C:UsersthomasPycharmProjectsBudgetMainvenvlibsite-packagesseleniumwebdriverremotewebdriver.py", line 955, in find_element
'value': value})['value']
File "C:UsersthomasPycharmProjectsBudgetMainvenvlibsite-packagesseleniumwebdriverremotewebdriver.py", line 312, in execute
self.error_handler.check_response(response)
File "C:UsersthomasPycharmProjectsBudgetMainvenvlibsite-packagesseleniumwebdriverremoteerrorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"name","selector":"submitNext"}
(Session info: chrome=66.0.3359.170)
(Driver info: chromedriver=2.36.540470 (e522d04694c7ebea4ba8821272dbef4f9b818c91),platform=Windows NT 10.0.16299 x86_64)
Anyone have any ideas as to how to click that button without errors?
Answer #1:
This error message…
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"name","selector":"submitNext"}
(Session info: chrome=66.0.3359.170)
(Driver info: chromedriver=2.36.540470)
…implies that the ChromeDriver was unable to locate the desired element.
Locating the desired element
As per the HTML you have shared to click on the element you can use either of the following Locator Strategies :
-
css_selector
:driver.find_element_by_css_selector("input[name='submitNext'][value='Next']").click()
-
xpath
:driver.find_element_by_xpath("//input[@name='submitNext' and @value='Next']").click()
However your main issue is the version compatibility between the binaries you are using as follows :
- You are using chromedriver=2.36
- Release Notes of chromedriver=2.36 clearly mentions the following :
Supports Chrome v63-65
- You are using chrome=66.0
- Release Notes of ChromeDriver v2.38 clearly mentions the following :
Supports Chrome v65-67
- Your Selenium Client version is unknown to us.
So there is a clear mismatch between the ChromeDriver v2.36 and the Chrome Browser v66.0
Solution
- Upgrade Selenium to current levels Version 3.11.0.
- Upgrade ChromeDriver to current ChromeDriver v2.38 level.
- Keep Chrome version at Chrome v66.x levels. (as per ChromeDriver v2.38 release notes)
- Clean your Project Workspace through your IDE and Rebuild your project with required dependencies only.
- Use CCleaner tool to wipe off all the OS chores before and after the execution of your test Suite.
- If your base Web Client version is too old, then uninstall it through Revo Uninstaller and install a recent GA and released version of Web Client.
- Take a System Reboot.
- Execute your
@Test
.
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.
Already on GitHub?
Sign in
to your account
Assignees
Comments
The Problem:
If it is tried to select a not listed option, then I want to handle the occuring error.
The stack trace says the problem is «Caused by: NoSuchElementException». I know, that I have to catch the «org.openqa.selenium.NoSuchElementException», but both are not catched, nor even «Exception» is catched.
I see that selenide calls throwElementNotFound()
.
The Workaround:
I have to catch «ElementNotFound» to handle this.
The Code:
SelenideElement select = $(By.name("domainsetId")); try { select.selectOption("ERROR"); } catch (org.openqa.selenium.NoSuchElementException | NoSuchElementException ex) { System.out.println("Not found"); return false; }
The failure trace:
Element not found {by text: ERROR}
Expected: visible
Screenshot: file:/home/XXX/git/selenium/Screenshots/1441620116678.0.png
Timeout: 4 s.
Caused by: NoSuchElementException: no such element
at com.codeborne.selenide.impl.AbstractSelenideElement.throwElementNotFound(AbstractSelenideElement.java:601)
at com.codeborne.selenide.impl.WaitingSelenideElement.throwElementNotFound(WaitingSelenideElement.java:75)
at com.codeborne.selenide.impl.AbstractSelenideElement.waitUntil(AbstractSelenideElement.java:593)
at com.codeborne.selenide.impl.AbstractSelenideElement.should(AbstractSelenideElement.java:411)
at com.codeborne.selenide.impl.AbstractSelenideElement.should(AbstractSelenideElement.java:406)
at com.codeborne.selenide.impl.AbstractSelenideElement.invokeShould(AbstractSelenideElement.java:243)
at com.codeborne.selenide.impl.AbstractSelenideElement.dispatch(AbstractSelenideElement.java:120)
at com.codeborne.selenide.impl.AbstractSelenideElement.invoke(AbstractSelenideElement.java:55)
at com.codeborne.selenide.impl.WaitingSelenideElement.invoke(WaitingSelenideElement.java:19)
at com.sun.proxy.$Proxy4.shouldBe(Unknown Source)
at com.codeborne.selenide.impl.AbstractSelenideElement.selectOptionByText(AbstractSelenideElement.java:488)
at com.codeborne.selenide.impl.AbstractSelenideElement.dispatch(AbstractSelenideElement.java:169)
at com.codeborne.selenide.impl.AbstractSelenideElement.invoke(AbstractSelenideElement.java:55)
at com.codeborne.selenide.impl.WaitingSelenideElement.invoke(WaitingSelenideElement.java:19)
at com.sun.proxy.$Proxy4.selectOption(Unknown Source)
at com.COMPANY.qm.smgw.MessengerManager.selectMandator(MessengerManager.java:129)
at com.COMPANY.qm.smgw.msg.MessengerManagerTest.test_selectMandator(MessengerManagerTest.java:81)
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:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
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:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
@crocodilechris So, what’s the problem?
Selenide throws ElementNotFound
exception, because it wraps the original NoSuchElementException
adding more details to it (like screenshot and timeout). It’s by design.
Actually you don’t need to catch it. Or why do you?
The problem is, as described, that I get a NoSuchElementException
, as you can see in the failure trace, but can’t catch it, because selenide throw an ElementNotFound
by hand and its ElementNotFound
does not inherit from NoSuchElementException
and so can’t be caught as such.
It’s annoying to always investigate which exception has to be catched, because the failure trace is not meaningful.
I have to catch it, to handle the case the item is not listed in the dropdown list and then I log that event.
@crocodilechris Once more, you do not need to catch exceptions in tests!
It’s something basically broken with test design. There should not be any if
, catch
, for
operators in tests.
Your test should look like:
public void unauthorizedUserShouldSeeLoginButton() { open("http://localhost:8080/"); $("#login").shouldBe(visible); } public void authorizedUserShouldNotSeeLoginButton() { open("http://localhost:8080/fakeLogin?as=john"); $("#login").shouldNotBe(visible); }
In other words: every test must always exactly know how software should behave, and test exactly that behaviour.
I don’t just write tests with selenide to test the web page. I also use it to configure the settings in the web frontend to run other tests affected by these settings. For latter I need to catch the Exceptions.
@crocodilechris Ok, then can you just if
instead of should*
?
Like this:
if ($("#id").isDisplayed()) { $("#id").click(); } if ($("#id").exists()) { $("#id").click(); } if ($("#id").is(empty)) { $("#id").click(); }
No problems here with should
. And no bigger problems at all.
The only annoying thing is, that I get a NoSuchElementException
, but must catch a ElementNotFound
.
In addition the ElementNotFound
inherits from
java.lang.Error -> java.lang.AssertionError -> com.codeborne.selenide.ex.UIAssertionError
, which is far away from what NoSuchElementException
inherits from:
java.lang.Exception -> java.lang.RuntimeException -> org.openqa.selenium.WebDriverException -> org.openqa.selenium.NotFoundException
The only thing I wanted to report, was the mismatch between the thrown ElementNotFound
Error and the reported NoSuchElementException
in the failure trace. I just wanted the output to be corrected.
@crocodilechris Ok, now I have got your problem.
Actually I cannot reproduce the problem. I try to call $("select").selectOption("xxx")
, and it throws ElementNotFound
exception.
In other words, this test is green:
@Test(expected = ElementNotFound.class) public void throwsElementNotFound() { $(By.xpath("//select[@name='domain']")).selectOption("unexisting-option"); }
asolntsev
added a commit
that referenced
this issue
Sep 19, 2015
Yeah, that’s right: it throws an ElementNotFound
. I always said that.
But the failure trace is suggesting a NoSuchElementException
. Look at the failure trace you get!
If you ran into the error for the first time, the message is suggesting you, that you have to expect, and therefore catch, a NoSuchElementException
.
That’s the problem: You see the failure trace and think you have to catch a NoSuchElementException
. And then you wonder that the Exception is not caught.
@crocodilechris What means «But the failure trace is suggesting a NoSuchElementException»?
Do you mean this line: Caused by: NoSuchElementException: no such element
?
It’s common practice in Java stack traces: exception A can be caused by exception B, which can be caused by exception C etc.
In our case, we have:
ElementNotFound bla-bla Caused by: NoSuchElementException: bla-bla
Here is no any problems. Works as expected.
Normally the name of the exception/error is mentioned plus a descriptive text:
Exception in thread "main" com.pany.ExampleMissingException: No example given at ... Caused by: com.pany.ShortExampleException at ...
Maybe you can modify the text, so that it’s more clear?
Error in thread "main" ElementNotFound: Element not found {By.id: containerHeader} Expected: exist Screenshot: file:/tests/002_Station/Screenshots/1443439614244.3.html Timeout: 4 s. Caused by: ...
We can do it. But is it really reasonable?
Look, this is just a duplication of text: «ElementNotFound: Element not
found»
Actually I intentionally cleaned up name of exception in order to make
error message readable in plain human language.
It seems that your need is corner-case. When running tests and reading test
reports, people hardly need to see exact name of exception.
Andrei Solntsev
2015-09-29 9:30 GMT+03:00 crocodilechris notifications@github.com:
Normally the name of the exception/error is mentioned plus a descriptive
text:Exception in thread «main» com.pany.ExampleMissingException: No example given
at …Caused by: com.pany.ShortExampleException
at …Maybe you can modify the text, so that it’s more clear?
Error in thread «main» ElementNotFound: Element not found {By.id: containerHeader}
Expected: exist
Screenshot: file:/tests/002_Station/Screenshots/1443439614244.3.html
Timeout: 4 s.
Caused by: …—
Reply to this email directly or view it on GitHub
#218 (comment).
I guess the issue can be closed?
@asolntsev I can relate also to the report of @crocodilechris
It’s not necessarily a bug, but it’s just that ElementNotFound
is not shown in the stacktrace upfront; thus, those who want to catch the Exception (whether it’s a good practice or not) end up thinking that they should be catching NoSuchElementException
(as appearing in the stack trace). However, that catch block will never be activated as it is being wrapped by ElementNotFound
.
@kenston Exactly! This is not a good practice. Nobody should catch ElementNotFound
in tests. WHY??? This is just crazy!
Let me rephrase:
- As a rule, people should not catch exceptions in tests. Especially
ElementNotFound
. - If somebody still believes he must catch
ElementNotFound
, he should have a very, very good reason for that. - If somebody doesn’t understand that he has to catch
ElementNotFound
, notNoSuchElementException
, then he is not qualified enough to state that he has very good reason (described in p.2).
@asoIntsev: There is no reason to always point to your opinion not to catch exceptions. That’s irrelevant!
As you can see / read there is a neat to catch them sometimes. Especially in the case where selenide is «misused» for steering purposes instead of pure testing.
And it’s a fact that the stack trace is confusing. No matter of catching exceptions is bad or not.
@asolntsev It seems that this is going to be an intentional design here serving to somehow make users doing try-catch to think twice. If someone couldn’t find out up front why they couldn’t catch the exception, they might give up and not do the try-catch at all.
I have this use case where I find it safer to do a try-catch. Let’s say a page w/ ajax loading will display a spinner in some of it’s page’s boxes/parts (rather than a floating/always-visible indicator) to indicate an on-going loading. Before I can continue with other interactions, I need to wait for the loading to finish. At this point, there’s no problem at all, as I can just use something like:
loadElement.waitUntil(disappear, 120000);
No try-catch needed at all. However, I also plan to do loadElement.scrollTo();
prior to the waitUntil
line above. This is to explicitly show to the watching user (during a live demo) that we’re waiting for something by scrolling to the spinner image (can be at the bottom of the page).
It is possible that the element has disappeared by the time we want to scroll to that element. I did place a loadElement.isDisplayed()
check first, but it’s possible (although a very slim chance, probably 0.01%) that an element is displayed at the time of that check, but not after passing through the check.
A try-catch over loadElement.scrollTo();
is one way to ensure an error won’t happen for such case. Scrolling to an element is not really essential in this test execution; thus, I feel that it’s ok to do a try-catch on something that we don’t implicitly validate/assert. In non-interactive mode (e.g., running from Jenkins), we don’t even have to perform this scrolling as no user is watching the demo run.
@crocodilechris , I found this page via google search and read thru the recommendations. In brief, the Throwable could be captured where we trigger the Proxy to really find elements, usually when accessing the properties of WebElement. Verified in web clawer stuffs.
I had this problem when I needed to catch all exceptions but I couldn’t catch an element not found (throwable) because I use an automation framework and not just selenide alone, It allows me to log only what’s necessary for me to know what went wrong.
I have to do the following:
try { $("xxx").click(); } catch(ElementNotFound | Exception ex) { fail(ex); }
@espaciomore Sorry, I haven’t got your point. Why it’s needed? Method fail(ex)
in your code throws AssertionError
. If you remove try/catch, method click()
still throws subclass of AssertionError
. Nothing really changes. So, why do you need try/catch?
@asolntsev
I take that back, the best design for an automated test is to check the element’s existence and visibility beforehand If one thinks it might be gone when an action is sent to it.
@espaciomore Sorry, I am not sure I understand your answer. My question is very practical. You can write either 1 line of code or 5, in both cases getting the same result. Why do you want to write more lines? I don’t see any practical reason.
Sometimes I need to do more operations when some operation like click fails. For instance, it might be OK that a click fails for an element that is not visible so the test can continue.
@asolntsev, at my new job developers have introduced a popup that sometimes does not appear (and they don’t want to fix that flakiness) so our test uses a try/catch.
At first I tried to catch a NoSuchElementException mentioned in «Caused by: NoSuchElementException: no such element: Unable to locate element:» , as I didn’t realize that the «Element not found» a few lines before means the Selenide exception ElementNotFound.
Luckily googling showed me this 218 selenide issue, otherwise I would have never known that I would have to catch an ElementNotFound (and not a NoSuchElementException).
@DieterRogiest, if you know that your test works with flaky elements, which is of course not very good, so why don’t you just add some check for this element not to get exceptions
if( myFlakyElement.isDisplayed() ) {
processPopup()
}
@evgeny-tumashchick, we have to wait with a waitUntil till the popup appears and if it doesn’t that waitUntil throws the exception:
getPopupCloseButton().waitUntil(Condition.visible, 15000);
getPopupCloseButton().click();
Update: now 2 days later our devs have disabled the annoying popups on our dev environment (and at the next sprint change the other env will be without them too). It’s probably rare in web app development that elements can sometimes fail at random to be present, but maybe it might be useful to have a Selenide waitUntil that doesn’t halt the program when it throws an ElementNotFound exception and that also outputs to console the exception ,like my catch statement did:
} catch (ElementNotFound e){
System.out.println(«exception: » + e.toString());
I just came across this thread because — surprise — I just need to catch the exception in selenide. I need to take care of tests I didn’t write…
All, watch out as this is going to be strong opinion from my side about what I read here, especially at the beginning.
I must say I am just shocked with your ignorance @asolntsev and your incompetency with regards to automated testing. Few polite people here were explaining the problem about the exceptions and you constantly and stubbornly say «you don’t need it, you don’t need it». You have no idea about real automation. Of course you think the opposite but the truth is sad. What is more sad you don’t listen to people.
Just to give you few facts for you to think of in case you change your mind in the future and start listening to people with more experience on the subject:
- tests in the company are not run on local browser as you most probably do — they are run on the selenium grid
- tests mostly do not automate web pages but complex application interface
- there are many tests which are run at the same time — also on the same machine which hosts selenium
- all this makes automated action damn slow, just to give the numbers iterating over 50 rows of the table to assert all the cells in my app lasts few seconds locally but about 40 seconds via the grid
- there are additional things like vanishing pop ups, automatically refreshed pages and pages parts etc
- thus when there are many tests, if I do not catch exception I will get staleElement or noSuchElementException every run at some place even though all the elements are checked for visibility!
- last general note: no, the tests should not be written like you say @asolntsev, but they should be written in domain language either external like Cucumber or internal crafted from e.g. Java to clearly state what they setup, run and assert; selenium/selenide is good for dsl backend only; actually test cases should even not be written but generated from model into executable sets of testcases automatically, but that’s a rocket science isn’t it?
If you don’t change your attitude maybe you should consider creating framework/application for other group — for sure not for QA engineers then.
I must once more emphasize I wrote all this because I am shocked about the way the author of testing framework thinks about automation.
@grzegorzgrzegorz
When Henry Ford suggested people to use cars, they were shocked with his ignorance and incompetency with regards to horses.
This is a joke. And now seriously:
- First of all, I don’t see a problem here. The initial question («why I cannot catch
NoSuchElementException
«) was answered in the question itself («catchElementNotFound
instead»). So, my immediate reaction or fix was not needed. No problems to solve. - I asked why he needs to catch the exception, he described his need and I suggested a better option. Why do you call it ignorance? I call it discussion.
- They agreed that there were «no bigger problems at all». And we only discussed a minor question about wording of the exception. Few polite people suggested that it could include name of Java class
ElementNotFound
, and I answered that it was intentionally replaced by human-readable text. Thousands of people are used to it and find it really readable. It’s much more than «few polite people» with «no bigger problems at all». So, where do you see a problem?
@grzegorzgrzegorz Thank you for sharing your knowledge about test automation. Of course I know that people use Selenium grid and automate complex applications which can be slow. But it doesn’t really change anything.
- To fetch data from 50+ table rows with many cells, I recommend to use more sophisticated approach instead if plain iteration (which is really slow). See http://barancev.github.io/read-data-from-web-page/ (it’s in Russian, but Google Translate should help).
- Yes, I agree with you that you need to try/catch to handle automatically refreshed pages etc with pure Selenium. But not with Selenide! Selenide does it out-of-the-box. With Selenide, you generally don’t need try/catch.
- When you say «they should be written in domain language» without a context and reasoning, isn’t it ignorance? I believe it’s not always needed. It depends.
- In most cases, «generated test cases» is really questionable idea. No, it’s not a rocket science. It’s an unneeded complexity. Tests (and code, and everything in the world) must be as simple as possible. KISS principle. Of course, sometimes we have to grow complexity, but there should be a very good reason for that.
- By the way, Cucumber is not a domain language.
P.S. This is the funniest quote:
If you don’t change your attitude maybe you should consider creating framework/application for other group — for sure not for QA engineers then.
Ironically, I never said that I created a framework for QA engineers.
I am developer, and initially created a library for developers.
- Later QA engineers started using it (probably because it’s easy, stable, convenient, fast?)
- Later I started adding new features asked by QA engineers which were not needed for developers (probably because …. I am … ignorant…?)
@asolntsev
short comment to the 1. post:
- Catching this exception is counter intuitive and this is the problem with your ElementNotFound as @crocodilechris was pointing it out
- Count how many times you said «you don’t need to catch exceptions». This was not a discussion.
- I do not really care about the quality of the Selenide, I was just shocked with the «tests do need to catch exceptions» lecture
and the 2. one: - No worries, I already solved the problem. I need to have solutions which are working when the real application is under the test. Yes, I read the source which is just the table source in my case and then process it in memory. Sometimes convert it back to the WebElement if further action is needed.
- To successfully read the table I need to catch exception. Any non-atomic operation (any chain) in Selenide will hit Staleness problem. This is how it works. You just will never see it on your local browser using static page. And funniest thing is you cannot see it when looking at your own code…
- It is just the general note on large/heavy tests — but I wrote it already…
- It seems like you know more about model based test case generation than me. So I will put a DOT here.
- it’s just a shortcut
And the last thing explains the situation then. Let the developers do the heavy tests with Selenide and we all will be happy.
The rest is the silence.
@grzegorzgrzegorz
This is not true:
Any non-atomic operation (any chain) in Selenide will hit Staleness problem.
Selenide will retry few times if the first try was not successful. No matter if it was chaining.
No matter if it was static page or «real application». Man, I develop and test «real applications» for many years. Selenide was created for testing such slow and unstable applications.
Probably you need to learn how it actually works? Then the need for catching ElementNotFound just disappears.
P.S.
- Yes, I know that catching this exception is counter intuitive. It was intentional (as I stated in NoSuchElementException thrown, but ElementNotFound must be catched #218 (comment)).
- You are ignoring the fact that «you don’t need» was followed by argumentation. Statements with arguments is the best thing people invented ever. I call it discussion.
I don’t understand what you wanted to say about developers and «heavy tests». But I know that thousand of QA engineers and developers do use Selenide and find it useful for any kind of tests. «Heavy» and «easy» tests. «Fast» and «slow» applications. With any kind of applications. With JUnit and TestNG. With Cucumber and without. With DSL and without. There is no limitations.
@grzegorzgrzegorz
Thank you for your fight on this thread. I have the opinion, as you facing it out correctly, that this problem is still annoying.
But I gave up on this topic, because @asolntsev will never accept that there is thrown the wrong exception / error type.
It’s common sense, that if you expect an ElementNotFoundException you shouldn’t catch an ElementNotFound. Don’t keep on trying to get a correction. It’s wasted time. Live with it or start exploring other frameworks.
@crocodilechris Hold on. You said in #218 (comment):
And no bigger problems at all.
And now you said that the wrong exception is thrown.
Am I the only one who sees a contradiction here?
Let me emphasize: yes, I think that in good tests, it’s not needed to catchElementNotFound
, but well, it’s my personal opinion, and it does not affect design decisions here.
The real reason was described in #218 (comment):
Actually I intentionally cleaned up name of exception in order to make error message readable in plain human language.
It seems that your need is corner-case. When running tests and reading test
reports, people hardly need to see exact name of exception.
Nobody of you ever tried to discuss this argument.
As a maintainer of the framework, I have to take care of thousands of people who are used to the current format of ElementNotFound
and find in easy and human-readable. Should I make their lives harder because a few polite people could not quickly understand which exception to catch? Do you really think so?
@asolntsev
Yes, there was argumentation from your side that we as selenide users do not need to catch exceptions but it was wrong.
Your first mistake is because you are basing on ElementNotFound exception only while there are other exceptions like the one related to staleness which makes the statement «you do not need to catch exceptions» FALSE. You can design the test to defend from ElementNotFound but you cannot defend from StaleElementReferenceException. No retry will ever help with staleness:
$("xxx").click();
will throw StaleElementReferenceException once the page gets refreshed after xxx was found but before it gets clicked.
The real smashing feature would be framework which would be smart enough to catch the staleness and repeat the whole command starting with finding xxx again. But this is not the case with selenide.
Your second mistake is you are so identified with your code that you refuse to make simple change so that user can easily find which exception should they catch. Even if this is bad test design (or better say «specific») users have right to write their tests in their own way. You also do not respect this right.
To sum up: the real trigger of my activity here is your ignorance about the real life testing expressed by your false mantra «you don’t need to catch exceptions». Either the test design or specific application under test cause the neccesity of catching the exceptions. DOT.
@crocodilechris
I must say I am not trying to get any result here. Actually the guy has a right not to change anything and we are free to switch to other framework as you say. I was just pissed off with the «discussion» and my only goal was to kick his ankle so that the guy maybe wakes up. However, I really do not care if he does.
No retry will ever help with staleness:
$(«xxx»).click();
will throw StaleElementReferenceException once the page gets refreshed after xxx was found but before it gets clicked.
@grzegorzgrzegorz
Can you provide reproducable example for this? I have never seen StaleElementReferenceException
with selenide tests.
@grzegorzgrzegorz it’s just not true:
$("xxx").click()
will throw StaleElementReferenceException once the page gets refreshed after xxx was found but before it gets clicked.
It’s not true. Selenide will retry to find element and click it (retry several times if needed).
The real smashing feature would be framework which would be smart enough to catch the staleness and repeat the whole command starting with finding xxx again.
Funny. Selenide does exactly that.
But this is not the case with selenide.
Why do you think so?
If you can reproduce the case when Selenide does not retry to find element, please register a bug in GitHub with code sample. This is a bug, and we need to fix it asap.
Ok, I can see we are going to be more specific. Your staleness defence doesn’t work so perfect then.
I do not have real life click button problem but something similar.
This code causes Staleness problem:
for (int index = 1; index <= 50; index++) {
try {
statuses.add($x("//processing-list//tbody/tr[" + index + "]//status-icon/*").shouldBe(visible)
.getAttribute("title"));
} catch (ElementShould | ElementNotFound e) {
logger.warn(e.getMessage());
}
}
ElementShould is thrown:
0 = {StackTraceElement@6159} "com.codeborne.selenide.impl.WebElementSource.checkCondition(WebElementSource.java:66)"
1 = {StackTraceElement@6160} "com.codeborne.selenide.commands.Should.should(Should.java:35)"
2 = {StackTraceElement@6161} "com.codeborne.selenide.commands.Should.execute(Should.java:29)"
3 = {StackTraceElement@6162} "com.codeborne.selenide.commands.Should.execute(Should.java:12)"
4 = {StackTraceElement@6163} "com.codeborne.selenide.commands.Commands.execute(Commands.java:144)"
5 = {StackTraceElement@6164} "com.codeborne.selenide.impl.SelenideElementProxy.dispatchAndRetry(SelenideElementProxy.java:90)"
6 = {StackTraceElement@6165} "com.codeborne.selenide.impl.SelenideElementProxy.invoke(SelenideElementProxy.java:65)"
7 = {StackTraceElement@6166} "com.sun.proxy.$Proxy29.shouldBe(Unknown Source)"
8 = {StackTraceElement@6167} --> I put manually line which is the cause here: statuses.add($x("//processing-list//tbody/tr[" + index + "]//status-icon/*").shouldBe(visible)
.getAttribute("title"));
and the message as returned by ((ElementShould) e).getMessage():
Element should be visible {By.xpath: //processing-list//tbody/tr[34]//status-icon/*}
Element: 'StaleElementReferenceException: stale element reference: element is not attached to the page document'
So finally you can observe StaleElementReferenceException
in selenide.
I also had different code snippets in which exceptions were thrown. But I am not going to report them. Actually this code sometimes throws ElementNotFound as well. This is because of the fact the table being queried is refreshed every 10 seconds and the tests are run through selenium grid infrastructure.
So I am sure you will not replicate it successfully. And if you cannot there is no defect there, is it?
Please do not give me tips about this code — this was legacy code and is now history as it was completely rerewritten by me so that offline processing of data is made.
I am writing this to show the problem but I am not going to report and take part in fixing this. I already used too much time on selenide.
To repeat for the last time: don’t be ignorant and be aware you need to catch exceptions in selenide sometimes and also respect the users right to code their tests as they wish to.
What does status.add()
do?
Actually, the problem could be because you mix Selenide calls with Selenium calls. getAttribute() call — which is inherited (unfortunately inherited, if you ask me) is not handled by Selenide waiting logic.
To write stable tests, please either don’t use getAttribute, isDisplayed, getText or be aware, that they are not «protected» by Selenide Library.
@grzegorzgrzegorz Yes, it’s always a good idea to be more specific.
Now I see your problem.
Staleness defence actually works. In your case, you are not getting StaleElementReferenceException
. You see StaleElementReferenceException
only in the description of element. It’s quite a rare case, and it typically can happen when page is constantly reloading.
Let’s look at this error message:
Element should be visible {By.xpath: //processing-list//tbody/tr[34]//status-icon/*}
Element: 'StaleElementReferenceException: stale element reference: element is not attached to the page document'
It means that Selenide tried to find element //processing-list//tbody/tr[34]//status-icon/*}
, but didn’t get it. Selenide re-tried it several times (up to 4 seconds by default) with some interval (100 ms by default), but every time the element was not found. Finally, after the timeout, Selenide decided to throw an error. Selenide adds a description of element to the error message (the line starting from "Element: "
). At this moment, element disappeared again, and Selenide had no better choice than just report this fact.
Selenide is not guilty here. Don’t blame us. It’s not possible to guarantee defence against constantly refreshing page. There is no framework in the universe which can do it. It’s always the easiest option to blame somebody and say «let’s choose another framework», but the problem is in your application (and your tests). You solved it with JavaScript — great, it seems to be the best solution here.
But the most important thing: try/catch would not help here.
P.S.
@vinogradoff No, the problem is not caused by getAttribute()
: stack trace clearly shows that the error was thrown from $.shouldBe(visible)
.
@asolntsev
Try catch did help here because originally after logger.warn there was next attempt to get title attribute.
It was terrible solution because of the performance but it was fixing at least some of the exception cases.
With the current solution even when hitting the page only once I need to catch the exception to make sure I always get the result even if the page refresh will occur to be able to retry.
So I completely disagree: the application is not problematic but hard to test. This is every day life of QA. It will not be simpler but even harder to test in the future. This example also shows how to actually defend against the page refresh — by using TRY CATCH.
Let it be useful example for other readers because white is black and black is white for you.
That’s it.
Yes, let’s call it «hard to test». I see that words «problematic application» and «bad tests» hurts you. Sorry for my english. Yes, it’s better to say «hard to test» and «tests with nuances» (or «legacy code»). I totally agree, it sounds better.
@grzegorzgrzegorz Man, please read once more #218 (comment). You clearly didn’t understand my description of try/catches in Selenide.
Let me rephrase:
- Selenide did N try/catches in loop. None of them succeeded.
- When you do your own try/catch, you just add one more catch to the N catches that Selenide already has done.
- Yes, it may happen to succeed, but it also may happen to fail (because the page is constantly reloading).
- Adding your own try/catch is effectively as good as making Selenide timeout a little bit bigger (say, 4s -> 5s). Then Selenide will perform N+1 try/catches.
So, this try-catch sometimes may help, but not always. The test remains flaky. Try/catch does not make test stable in this case.
This is pointless discussion. Finito.
In this tutorial, we will discuss about the java.util.nosuchelementexception in Java. This exception is thrown to indicate that there are no more elements in an enumeration.
This exception extends the RuntimeException
class and thus belongs to those exceptions that can be thrown during the operation of the Java Virtual Machine (JVM). It is an unchecked exception and thus, it does not need to be declared in a method’s or a constructor’s throws clause.
Finally, the java.util.nosuchelementexception existed since the first version of Java.
1. The Structure of NoSuchElementException
Constructors
NoSuchElementException()
Creates an instance of the NoSuchElementException
class, setting null
as its message.
NoSuchElementException(String s)
Creates an instance of the NoSuchElementException
class, using the specified string as message. The string argument indicates the name of the class that threw the error.
2. The java.util.nosuchelementexception Exception in Java
The NoSuchElementException
can be thrown by the following methods:
Enumeration::nextElement()
NamingEnumeration::next()
StringTokenizer::nextElement()
Iterator::next()
All the aforementioned methods try to return the next element of an enumeration and throw that exception, in order to indicate that no more elements exist. A sample example that throws a java.util.nosuchelementexception is the following:
import java.util.HashSet; import java.util.Hashtable; import java.util.Set; import java.util.StringTokenizer; public class NoSuchElementExceptionExample { public static void main(String[] args) { Set sampleSet = new HashSet(); Hashtable sampleTable = new Hashtable(); StringTokenizer tokenizer = new StringTokenizer("", ":,"); /* All following statements throw a NoSuchElementException. */ sampleSet.iterator().next(); sampleTable.elements().nextElement(); tokenizer.nextToken(); } }
A sample execution is shown below:
Exception in thread "main" java.util.NoSuchElementException at java.util.HashMap$HashIterator.nextNode(HashMap.java:1431) at java.util.HashMap$KeyIterator.next(HashMap.java:1453) at main.java.NoSuchElementExceptionExample.main(NoSuchElementExceptionExample.java:15)
3. How to deal with the java.util.nosuchelementexception
A very common error case is when a Java application tries to iterate over an empty Set
. In order to avoid this error, a Java application should call the hasNext
first. For example:
import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class MapIterationExample { private final static int TOTAL_ELEMENTS = 100; public static void main(String[] args) { Set sampleSet = new HashSet(TOTAL_ELEMENTS); Iterator ite = sampleSet.iterator(); while(ite.hasNext()) System.out.println(ite.next()); } }
Accordingly, if a Java application uses enumerations, the hasMoreElements
method shall be used:
import java.util.Enumeration; import java.util.Hashtable; public class EnumerationIterationExample { private final static int TOTAL_ELEMENTS = 100; public static void main(String[] args) { Hashtable sampleTable= new Hashtable(TOTAL_ELEMENTS); Enumeration tableEnum = sampleTable.elements(); while(tableEnum.hasMoreElements()) System.out.println(tableEnum.nextElement()); } }
Finally, a proper user of the StringTokenizer
is the following:
import java.util.StringTokenizer; public class StringTokenizerExample { public static void main(String[] args) { String str = "Hello:from:Java,Code:Geeks"; StringTokenizer tokenizer = new StringTokenizer(str, ":,"); while(tokenizer.hasMoreTokens()) System.out.println(tokenizer.nextToken()); } }
4. Download the Eclipse Project
This was a tutorial about the NoSuchElementException
in Java.
Last updated on Dec. 09th, 2021