next-right-now icon indicating copy to clipboard operation
next-right-now copied to clipboard

Pages Unit Test

Open samuelcastro opened this issue 3 years ago • 21 comments

It'd be great to add pages tests, we could use: https://testing-library.com/docs/react-testing-library/intro

samuelcastro avatar Sep 04 '20 23:09 samuelcastro

It would be great to know what you mean by "page tests". If you mean integration testing and navigation workflows, then it's better to use Cypress to perform those. (partly because recording of videos and screenshots helps debugging failing tests)

It really comes down to what the pages do, if they are used to display static information, there is not much point testing those, a simple test about checking a random part of the page should suffice to know whether the whole page works or not. For pages with complex navigation workflow, Cypress seems better suited. For pages with complex internal workflow (lots of actions, states), they can be tested by testing the underlying components one by one (component unit tests). Testing the thing as a whole can also be done, Cypress that help with that too.

The problem with automated testing is that "add pages tests" is way too vague and must be really thought of, writing tests takes quite a lot of time, maintaining them is a burden too. Only important stuff should be tested.

For the record, we already have some tests that test several pages using Cypress, including the homepage (which is the most important, IMHO) and those tests are executed automatically using GH Actions upon deployment.

Vadorequest avatar Sep 06 '20 09:09 Vadorequest

I think @samuelcastro may be referring to your quote

For pages with complex internal workflow (lots of actions, states), they can be tested by testing the underlying components one by one (component unit tests).

Correct me if I am wrong, but I believe for frontend, you only have Cypress for end-to-end frontend testing use case? react-testing-library would be a good library to perform the test you mentioned ^.

Maybe you have some other thoughts on testing ^?

smblee avatar Sep 07 '20 19:09 smblee

Actually, Cypress is meant to test user workflows (like, navigation).

We also have UI component testing, using react-test-renderer. But only a few components are actually being tested ATM.

https://github.com/UnlyEd/next-right-now/blob/fc357f165abf9ae6d9c452d09d931a907126c5e6/src/components/i18n/I18nLink.test.tsx#L9

With those, I believe we've got enough tooling for testing UI components. Now, it's more a matter of writing the actual tests.

Also, the react-testing-library didn't exist when I chose the tools for UI component testing, maybe it offers more features? I haven't been limited by react-test-renderer so far.

Vadorequest avatar Sep 07 '20 20:09 Vadorequest

It would be great to know what you mean by "page tests". If you mean integration testing and navigation workflows, then it's better to use Cypress to perform those. (partly because recording of videos and screenshots helps debugging failing tests)

I meant unit tests of DOM elements of the pages and their components, I know we have cypress for e2e/integration and I know it's great for general navigation and the experience as a whole, however, unit testing the elements will give us a better spectrum of testing improving the project quality and reliability, react-testing-library's goal is to unit test components at a lower level, making sure your components work as expected.

Also cypress has a limitation on its free tier price, so as the project grows up, you'll need to pay more.

The best approach for me would be work with both.

react-testing-library uses the simulation of a real DOM through js-dom to find and test elements while react-test-renderer works with pure JavaScript objects, without depending on the DOM, so it gives react-testing-library a lot more power of capabilities. However react-testing-library was not meant to replace react-test-renderer they kind of complete each other, it's a great replacement for Enzyme though which we're not using here anyway.

Also, the react-testing-library didn't exist when I chose the tools for UI component testing, maybe it offers more features? I haven't been limited by react-test-renderer so far.

I don't know when you set it up but the first release of React Testing Library was in March, 2018, it's not a new library.

samuelcastro avatar Sep 08 '20 17:09 samuelcastro

Thanks for the thorough explanation.

What's the testing use case here? What would you like to test using react-testing-library that cannot be tested by react-test-renderer?

One thing to keep in mind is that the latter in more lightweight, it does less, so that makes sense.

I'm all for adding react-testing-library, once I understand exactly how it will benefit the project. 😉 Adding more lib for the sake of adding more lib/capabilities is pointless if it doesn't help achieve something better. And it makes the project more complicated to understand and maintain too. (I just spent a full day on upgrading dependencies 😢)

Vadorequest avatar Sep 08 '20 17:09 Vadorequest

react-testing-library is intended for unit/integration/e2e testing directly from the DOM's perspective. It uses React renderer and ReactTestUtils internally, requires real DOM because it's component's output that is asserted in tests, not internals.

react-test-renderer contain a subset of functionality, react-testing-library was built upon it. API is scarce and requires to write boilerplate code or custom utility functions for full-grown testing. React officially promotes react-testing-library as better alternatives.

From the official react page I quote:

We recommend using React Testing Library which is designed to enable and encourage writing tests that use your components as the end users do.

Also read the intro to understand the problem and the solution they propose.

samuelcastro avatar Sep 08 '20 18:09 samuelcastro

Thanks. I guess we'll add it once we have an actual use case for it.

Vadorequest avatar Sep 08 '20 19:09 Vadorequest

Btw, we already have many cases that we can use it.

samuelcastro avatar Sep 09 '20 16:09 samuelcastro

That's true, there are components that could use a few tests. Maybe we should put together a list of those we wish to test and what's to be tested? I don't have time to write too many tests myself, I try to focus on the most important components so far.

Vadorequest avatar Sep 11 '20 07:09 Vadorequest

Looks like a good plan, I think appBootstrap and pageLayout are the most important ones at this point, I don't think we should test all pages since they're just example pages.

samuelcastro avatar Sep 11 '20 15:09 samuelcastro

Example pages are already tested, 1 of each (SSG, SSR, etc.) to avoid undetected regression depending on the rendering mode.

SSG with revalidate could also be tested actually, I don't think it is, currently.

The app bootstrap part is definitely a critical bit. Maybe a bit hard to mock, though. Especially the part around the "Component" being passed down by the Next.js framework itself.

Vadorequest avatar Sep 13 '20 19:09 Vadorequest

Just came across https://www.cypress.io/blog/2020/06/11/introducing-the-cypress-real-world-app/ which is a very useful resource. I hope I find the time to play around and might implement my findings in NRN afterwards.

Vadorequest avatar Nov 29 '20 23:11 Vadorequest

Great resource indeed.

samuelcastro avatar Nov 30 '20 18:11 samuelcastro

Cypress has been updated to v6 and now theoretically supports Component testing. (I haven't tried it myself yet)

Vadorequest avatar Dec 20 '20 21:12 Vadorequest

I've been using react-testing-library for everything but e2e, and have been looking into cypress to fill in that gap. Been looking at this project to hopefully be my "how to" guide of doing this well in nextjs. (No pressure lol).

In any case since this issue caught my eye, with v7 and cypress' component test runner, I feel like that would move the needle toward cypress for everything. I have yet to see a good breakdown article of anyone trying to pit that and react-testing-library head to head but I'm sure the results would be interesting..

CopyJosh avatar Jun 16 '21 00:06 CopyJosh

Interesting, I don't have much feedback to give on Cypress "as a replacement for react-testing-library", I haven't used it for that purpose and I don't know the pros/cons.

Cypress is moving towards "one engine for all tests", or at least it tries to be the test runner not only for E2E but for components as well. Definitely sounds interesting, although it'd be great to have a "good breakdown article" about the benefits/differences, as you stated.

Cypress 7 brought Component testing, there are a few related issues:

  • https://github.com/UnlyEd/next-right-now/issues/351
  • https://github.com/UnlyEd/next-right-now/issues/326
    • I'll ask someone of the Cypress community there if they about good articles/resources on that matter!

Vadorequest avatar Jun 16 '21 06:06 Vadorequest

Hello @CopyJosh! I'll try to answer your questions about Cypress and Testing Library. FYI: I work on Cypress and I maintain Testing Library's Vue integration, so I don't really have a bias either way.

Testing Library provides:

  • a way to mount your component (render)
  • what I call a "driver" to interact with your components (findByText, fireEvent), etc

As for the rest, you need to bring your own:

  • test runner (Jest is popular)
  • environment (usually jsdom)

Cypress provides:

  • a way to mount (cy.mount for component testing)
  • driver (cy.click, cy.get, etc)
  • pre-configured test runner (mocha + chai combo)
  • network layer stub/mocks
  • environment (we just use whatever browsers you have installed)

You can also switch our the driver part, interestingly enough. More info. Then you can write cy.findByText, for example - using the Testing Library driver, but the test of the Cypress infrastructure (test runner, browser, etc). This is useful if you like the idea of Cypress (see your tests in a browser as they run) but like the testing library driver better.

A summary:

  • Cypress is a pre-configured tool with render functionality, driver, runner, and environment.
  • Testing Library is just the render and driver part. You need to bring the rest yourself.
  • Cypress runs in a real browser by default. You can see what's happening! No more console.log(document.body) or debug()
  • Testing Library can run in a browser, but most common is used in a jsdom environment.

The main thing that enjoy about Cypress is you can see what's going on:

image

Obviously this very useful when building a UI component (similar to Storybook, but you can actually make assertions).

I recorded a video about the different frameworks available for component testing, you might find it useful.

lmiller1990 avatar Jun 17 '21 01:06 lmiller1990

@lmiller1990 wow what an incredibly thorough response. I sincerely appreciate this break down. I suppose that is why there aren’t a lot of head to head comparisons, it is really the kitchen sink vs the entire kitchen we’re talking about here. I can’t wait to get started!

CopyJosh avatar Jun 17 '21 02:06 CopyJosh

Let me know if you get stuck on anything - initial configuration can be a little challenging (depending on your stack). I'm around most days to help out :)

lmiller1990 avatar Jun 17 '21 06:06 lmiller1990

Thanks @lmiller1990, really useful to split the responsabilities of each tool, it wasn't clear to me until now!

You mentioned "Cypress runs in a real browser", which made me think about a recent discussion I had with a professional tester. he said to me he didn't want to use Cypress, because of how it's designed. I don't remember the technicals (it has to do with "running in a browser" thing), but he stated Cypress isn't suited for complex E2E, because it cannot leave the current page, meaning it's not usable for testing multi-pages workflow, like testing payments (checkout page > payment page > confirmation code (3DS) > checkout page). I'm not sure how much of that is true, and it's not really the question at hand, but I'd love to learn more about the Cypress limitations.

He compared Cypress to Playwright, basically stating Playwright can do those things, while Cypress cannot, and it has to do with how they were designed in the first place.

Vadorequest avatar Jun 17 '21 08:06 Vadorequest

For the record because it has't been quoted in this discussion: https://github.com/toomuchdesign/next-page-tester This is not for unit testing but integration testing, as it will also trigger data fetching methods. I intend to set this up in my apps later on, and I am digging right now how to use a similar approach in storybook.

Cypress is more often relevant for those test but Jest tends to be faster if you want to unit test a page. Typical use case is checking how query parameters are handled, because this is a responsibility of the page.

eric-burel avatar Aug 19 '21 09:08 eric-burel