-
Notifications
You must be signed in to change notification settings - Fork 472
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
getByRole("progressbar") is pretty slow #552
Comments
Since you actually remove the element from the DOM you can ignore the additional a11y tree checks and go with On slow machines these additional checks can starve your CPU and you should increase the polling interval with And last but not least: What version of For us: I think we should make the perf impact of |
Thanks for the quick reply! I've just tested the I'm using version 25.2.7 of Jest. |
Have you tried increasing the interval? Would be helpful if you could provide a full repro. Otherwise it's unclear what makes this test so slow.
It's unclear where this difference is coming from. Could just be the |
Increasing the interval didn't help either. I'm preparing a demo with my real use case :) |
I've updated the demo with a more complex form and here's the result: Sandbox: https://codesandbox.io/s/musing-gauss-e1ynf?file=/src/DemoForm.js I've removed the |
Great. I think this is somewhat expected with the current implementation. ByTestId takes 130ms while ByRole takes 200ms. This is 50% slower. Might be nice to experiment with different implementations that don't loop over all nodes but convert the role directly to a selector and use that directly. |
I've dug in the (transpiled) code and try to see where it was spending the most time. Surprisingly, this is not in dom-testing-library/src/query-helpers.js Line 62 in ca1b608
Especially, the call to |
Digging even more, I'm landing on this line: https://github.com/testing-library/dom-testing-library/blob/master/src/queries/role.js#L116 However, I'm using 7.3.0 and seeing that you changed the implementation in 7.4.0. Thus, I need to check if it has changed the behaviour. 🙂 |
Still the same behavior on 7.5.1. I'm now checking this line: dom-testing-library/src/role-helpers.js Line 134 in 429de04
|
Funnily, if I do |
Hi @ValentinH! Thanks for all this digging. I believe that |
Yes, I'm trying to see what part of it is the slowest part :) |
Not a big surprise, but most of the time is spent on window.getComputedStyle(element).display |
Using the same caching mechanism than in dom-testing-library/src/queries/role.js Lines 42 to 49 in 752ff66
They are still 5-6 times slower than One idea I have is: do we really need to build the whole "role" error message when using
|
I could make it even faster by using the same cache idea but for the const getComputedStyleCache = new WeakMap()
function cachedGetComputedStyle(element) {
if (!getComputedStyleCache.has(element)) {
getComputedStyleCache.set(element, window.getComputedStyle(element))
}
return getComputedStyleCache.get(element)
} As this is used both in |
Oh right. I had it backwards. But I think it would be a good idea to skip the error helpers when running in a |
I don't see a way to skip the error in this case without explicitly passing a (new) option to |
I ran into this today while trying to debug why a mocked network request was so slow. I'll try to put together a minimal reproduction but the Cliffs Notes is: My app code was making a network request and on success would navigate to another route. I was waiting for the new route to load with The only real difference between the tests seems to be the route change. I'll try to put together a minimal reproduction this weekend to narrow it down. |
If I understand correctly were determining the accessibility of everything before matching. Is that right? If so... What if we find the match first and then determine if it's accessible? |
Pretty sure this is what we do already. |
We could flip a global variable and then do something like |
What I understand is that we are searching for all the roles in the container tree in order to explain why the role that was requested was not found. |
@eps1lon is there already a similar pattern in the existing codebase, if yes I can work on a PR to implement the light error message when run within a Actually, I think it should only be for |
I guess I can use the |
I think we really need to be careful here. I want to give it a little bit of extra thought... |
Yes this would be quite hacky and just a workaround for a deeper issue: |
If you decide that we can go this way, I'm ready to make a PR for the 2 following things:
|
Ok, so I think the simplest solution is to default Because this is a breaking change, we should do this in two phases.
Anyone want to work on phase 1? |
@eps1lon I've setup the repro repo, i've kept as much as possible in because i did not want to remove the problem in some way ( you have a pending collaborator access invite). I've left where to look in the readme ;) |
@eps1lon Any update on this issue ? |
🎉 This issue has been resolved in version 7.6.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
This doesn't actually improve the performance of getByRole though does it? Just when using with waitFor. I was not using waitFor and getByRole was still unusably slow in a complex form component. |
Please open a new issue (since this issue was concerned about ByRole in waitFor) and fill out the template. Having a repro like the one @tommarien provided helps a lot. |
I've just update testing-library/dom in the reproduction repo and see times go from 280ms on average to 38ms ;), so thanks a lot 👍 . If next release of testing-libs dom dependency to > 7.6.0 than everyone can benefit from this :). @eps1lon Thanks and i'll remove the repro repo today |
I am also seeing very slow times in a large complex DOM (>800ms/getByRole). @domarmstrong Did you open a new issue already? |
Hi @ctoppel, I'll just echo what @eps1lon said earlier:
Thanks! |
Hey guys I don't know if anybody else opened a new issue but today I had this exact issue, one of my test suite started to have systematic timeouts after updating to new version of testing library and updating my queries to getByRole Let's say I have an Input component similar to this
In my tests I'm running this:
Those are my results before without
Those are the results after
In general for me getByRole is slower it's 1 / 2 sec vs 5ms with the other queries |
eps1lon/dom-accessibility-api#323 |
Same for me, more than 2 sec in some cases, depends of test, and component implementation. Even if I don't consider it really important, difference is there, it's a fact. I'm just worried about this sentence in the documentation clearly stating that getByRole ...should be your top preference for just about everything. There's not much you can't get with this (if you can't, it's possible your UI is inaccessible). I have been more than once in the position of seen MRs get rejected, or at least, heavily commented, about wrong query usage on RTL, without any real performance consideration (mainly because some developers don't take the time to test this). It's possible to make this difference noted in the doc, at least until its get improved @kentcdodds? Can save some time of internal discussions for some teams. |
I personally think a PR to the docs is warranted. Something like: "NOTE: some have experienced poor performance with the role query, learn more: link" |
The usage of getAllbyRole().filter seemed to have a cumulative timeout effect where the tests would pass when run in isolation with .only, but when run as part of the full test suite would then timeout and fail. The solution was to use within() to narrow down the search space of the test function, making the test run faster and preventing the timeout issue. More info on this here: testing-library/dom-testing-library#552
Were the docs ever updated to reflect performance impact of |
@arahansen I didn't take the task at the end, because I'm not sure about how useful is going to be. Even if benchmarks here have some point, after a few more talks about it, turns out that small sized teams or alone individuals are probably going to assume that the doc is talking about a huge performance impact (even if you used the right wording there, or even if you provide the link), and they're going to do it maybe without any real performance assessment on the test stages. That means, final result could be people opting-out of getByRole (and all that implies) for not a really outstanding practical reason. |
I came here after realizing there's a huge performance difference between getByRole and other query methods. Using getByText immediately makes my tests run 8x faster. I understand the reasons for recommending getByRole but that much additional time spent waiting for tests adds up fast for a large project. I think the docs should be up front about this so people can make their informed decisions about what method to use. |
For those who use import { ReactNode } from 'react'
import { StyleSheetManager, StylisPlugin } from 'styled-components'
const ALLOWED_RULES = ['display', 'visibility', 'pointer-events']
const simplifiedStylesPlugin: StylisPlugin = (context, content) => {
if (context === 1) {
if (!ALLOWED_RULES.some(rule => content.toString().startsWith(`${rule}:`))) {
return ''
}
}
return undefined
}
export const withSimplifiedStyles = (component: ReactNode) => (
<StyleSheetManager stylisPlugins={[simplifiedStylesPlugin]} disableVendorPrefixes>
{component}
</StyleSheetManager>
) |
React Testing Library can be slow and some tests time out on CI. It's a tradeoff between testing by user interaction/accessibility and speed. This optimizes the performance in places that I consider reasonable by - Replacing `getByRole` with `getByText` - Replacing `userEvent.type` with `userEvent.paste` testing-library/dom-testing-library#552 (comment) testing-library/dom-testing-library#820 testing-library/user-event#577
React Testing Library
version: 10.0.4 (I'm using/react
not/dom
but I'm posting here asgetByRole
is implemented here)node
version: 🤷 (codesandbox)npm
(oryarn
) version: 🤷 (codesandbox)I've noticed that some of my tests were pretty slow to run (more than 2 seconds). After investigating, I've noticed that the following pattern was to source of the slowness:
If I add a
data-testid
to my loader and switch to:it's much faster.
Relevant code or config:
I'm sometimes displayed a
CircularProgress
frommaterial-ui
while fetching some data and I use this pattern to wait for it to be removed.example of implementation
What happened:
Here are 2 tests outputs where I only change the pattern mentioned above.
getByRole

getByTestId:

Reproduction:
I've create the following Sandbox: https://codesandbox.io/s/musing-gauss-e1ynf?file=/src/Demo.js
The numbers are much smaller but when running the tests several times we can see that the
getByRole
is slower when used on theCircularProgress
.Problem description:
I think that
is the best pattern to test that a loader is displayed on screen. However, the slowness prevents us from using in all our tests as it quickly gets slow.
The text was updated successfully, but these errors were encountered: