Component Testing
In testplane, experimental support for component testing and unit tests running in the browser has been added.
Almost all modern web interfaces are built using frameworks (React, Vue, Svelte, ...) to simplify the creation and reuse of components. It is important to test such components in isolation from each other to ensure that each component correctly performs its function. Just as we write unit tests separately from integration tests. Testplane already supports screenshot testing of components using Storybook, but this tool is not relevant for all projects. Therefore, we developed another option for component testing that does not require the use of Storybook.
This feature can be useful if your project uses React components. At the same time, there are no tests at all or only heavy integration tests are used (i.e., entire pages containing many components are checked). According to the testing pyramid, there should be fewer integration tests because they are more prone to "flaps" and often redundant. Many scenarios can be checked using component tests, thereby reducing test execution time in CI and improving their stability.
Component Testing Implementation Options
Component testing is a type of testing where the logic of a web component is checked in isolation from the web page in which it is used. To perform such a test, you need to be able to correctly render the component. Often, JSDom (used in Jest) is used for this task, which renders web components using virtual rendering in Node.js, i.e., without using a real browser. On the one hand, this works faster (the browser is not launched), but on the other hand, it is less stable because the checks are not performed in a real browser. The second popular solution is to use a very fast dev server Vite, which supports many frameworks (React, Vue, Svelte, ...) and is responsible for rendering components in isolation.
We chose the option of using Vite because this approach provides testing of the page closer to reality (as if it were opened by a user). At the same time, the tests themselves run a little longer than in jsdom. But for us, the most important thing is the stability and reproducibility of test results, so the choice was obvious.
Brief information on how this is implemented
- when specifying the
testRunEnv: 'browser'
option in the Testplane config, a browser runner will be used, which launches Vite on localhost with a random free port (the user can set the required port in the Vite config). It is on this launched server that all user components will be rendered and all necessary commands/checks will be performed (i.e., directly inside the browser); - then the tests are read in Node.js, i.e., as it is done for integration tests. This is necessary for all plugins to work correctly (we are talking about event triggers when reading tests), as well as to be able to run tests from one file in parallel. If the test were read only in the browser context, it would be necessary to run absolutely all tests inside one file, and a critical failure in one of them would lead to the stopping of all subsequent ones. That is, at this stage, we understand which tests need to be run;
- after that, as usual, the necessary browsers are launched, and the tests are run in them. Each test, before executing user code, navigates to the launched Vite server. When such a request is made, a special index.html is generated, into which all necessary libraries are loaded:
- mocha — for reading tests;
- webdriverio — for using the browser instance inside the browser itself;
- expect — for performing checks;
- and other internal modules necessary for correct operation.
- when opening index.html from Vite, the browser establishes a websocket connection with the Testplane master process to exchange the necessary data. For example, if the construct
await browser.$("body").assertView("plain", "body")
is called in the browser, it is obvious that it cannot be executed in the browser itself, as access to the file system is required insideassertView
. Therefore, the execution of this command is sent to the Testplane master, which in turn sends it to the worker in which this test is running. And it is the worker that executes the command passed to it. When the result is obtained, it is sent back to the browser in the same way. All communication is implemented using the socket.io library; - after that, the specified test begins to run in the browser, which returns the result to the Node.js process upon completion.
How to use?
Read more about it in our documentation Component Testing.
Conclusion
This functionality provides our users with new capabilities:
- isolated testing of React components in a real browser;
- stability and reproducibility of test results compared to JSDom;
- HMR support;
- access to browser/expect instances in the browser's DevTools for convenient debugging;
- log display in the terminal to enhance comfort and speed up development.
Switch to Testplane and try the new feature yourself. If you encounter any problems, come to the issue github — we will definitely help you!