facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
227.37k stars 46.37k forks source link

[React 19] revive `react-test-renderer` #30551

Open AndyOGo opened 1 month ago

AndyOGo commented 1 month ago

Summary

Ideally react is shipped with official test utilities instead of relying o third-party vendors.

Unfortunately it was decided to deprecatereact-test-renderer.

As a consequence it isn't easy anymore to:

Regressions

@testing-library/react is an integration testing library, promotes testing anti-patterns and completely ditches unit tests. It is slow and requires a DOM or a mock like js-dom.

Please refer to these resources for a comprehensive understanding of why unit tests are of high value:

Other critical voices from the community

References

react-test-renderer is deprecated. A warning will fire whenever calling ReactTestRenderer.create() or ReactShallowRender.render(). The react-test-renderer package will remain available on NPM but will not be maintained and may break with new React features or changes to React’s internals. https://react.dev/warnings/react-test-renderer

react-test-renderer is deprecated and no longer maintained. It will be removed in a future version. As of React 19, you will see a console warning when invoking ReactTestRenderer.create(). https://www.npmjs.com/package/react-test-renderer/v/19.0.0-canary-8afa144bd-20240416?activeTab=readme#react-test-renderer-deprecated

Note: that affects any code using react-test-renderer https://github.com/search?q=repo%3Ajestjs%2Fjest%20react-test-renderer&type=code

lo1tuma commented 1 month ago

I fully agree with the points raised in this issue. The React thinking model, which emphasizes components, is widely praised for its effectiveness. It is only logical to continue this component-centric approach in unit testing as well. Usually I want to only test the public API of the component under test during unit tests. In my view, this API consists of props and context as inputs and the virtual DOM tree as the output.

I think we could imagine the DOM as an I/O device. Abstracting I/O devices has been a common practice for already a few decades because it hides device-specific quirks and allows us to focus on business logic. This is where react fits in perfectly. It abstracts the DOM and other renderers. I trust a renderer like react-dom-renderer to work correctly and do not see the need to re-test its behavior in my unit tests. Instead, I prefer to focus on testing the API at the component boundary, ensuring that my components interact with the renderer in the expected way.

Testability is a crucial feature for me, and it is one of the main reasons I choose React. In my experience, most other frameworks or rendering libraries present even greater challenges when it comes to testing. With the deprecation of react-test-renderer, I feel like React is losing its most valuable feature.

lo1tuma commented 2 weeks ago

As I understand the major issue with the current version of react-test-renderer is that it exposes the fiber data structures directly, but those data structures are target of frequent backwards-incompatible changes, right? So what if we could use something different? IMHO it doesn’t have to be fiber instances that react-test-renderer should expose. The only important thing is that it represents the rendered component tree.

I’m not really familiar with react internals and especially not with the DevTools, but from what I’ve seen while skimming recent PRs, there is a lot of things going on regarding DevTools. One interesting change was #30625 which introduces a shadow/virtual tree for the same reason, so DevTools are less dependent on fiber data structures. Wouldn’t it be possible to use the same approach for a test renderer? CC: @sebmarkbage.