-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Add testing document [skip-ci] #53514
Conversation
745dd04
to
68bebce
Compare
This is not ready to merge quite yet, but I'm opening it for review / feedback on the general format. I would like to get this merged even before all of the different sections are filled out so that it can be useful sooner than later. The other sections can be filled out in other PRs. |
Pinging @elastic/kibana-platform (Team:Platform) |
src/core/TESTING.md
Outdated
In general, we recommend three tiers of tests: | ||
- Unit tests: small, fast, exhaustive, make heavy use of mocks for external dependencies | ||
- Integration tests: higher-level tests that verify API behavior through sending real HTTP requests to Kibana server | ||
- **TODO: what's the equivalent of integration tests for frontend code? Karma replacement?** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests for a public API without a UI-part. For example, license$ in licensing plugin, session control in the security plugin, etc.
|
||
#### HTTP Routes | ||
|
||
_How to test route handlers_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plugins can test their route handlers via FTR or existing test_utils. We can describe both ways until #51150
Can be done in follow-ups
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep that is the plan, to do in follow up PRs
|
||
These long-lived sessions make cleanup more important than before. It's entirely possible a user has a single browsing session open for weeks at a time, without ever doing a full-page refresh. Common things that need to be cleaned up (and tested!) when your application is unmounted: | ||
- Subscriptions and polling (eg. `uiSettings.get$()`) | ||
- Open connections (eg. a Websocket) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
global API calls as well. that a plugin doesn't redirect the app on a specific url on the mount, for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Core API calls is a good example. For instance, calling core.chrome.setIsVisible()
for a full-screen mode, but not unsetting it when unmounted if user is redirected to another app.
Could you explain this example more? "a plugin doesn't redirect the app on a specific url on the mount"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example is not possible to test. Probably to document it is enough.
setup(core: CoreStart, plugins: Deps) {
// this logic would affect the whole Kibana
plugins.licensing$.subscribe(async license => {
if(!license.iAvailable) {
window.href = ..
});
});
};
src/core/TESTING.md
Outdated
// Unmount UI | ||
ReactDOM.unmountComponentAtNode(element); | ||
// Close any subscriptions | ||
settings$.complete(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well. If a plugin doesn't subscribe manually, it needn't to unsubscribe. We must explain this in the manual.
Given your example.
settings$
is Observable. A plugin cannot complete it. It will be completed if the unsubscription is implemented in the useObservable
hook correctly.
The better example could be if a plugin implements polling for a every new settings$ value and implements a subscription manually.
const renderApp = (params: AppMountParameters, core: CoreStart): AppUnmount => {
const settings$ = core.uiSettings.get$<string>('mysetting1');
const pollingSubscription = settings$.subscribe(async url => {
const value = await core.http.fetch(url);
// ..
});
return function cleanup() {
pollingSubscription.unsubscribe();
};
};
...
describe('renderApp', () => {
it('mounts and unmounts UI', () => {
const params = { element: document.createElement('div'), appBasePath: '/fake/base/path' };
const core = coreMock.createStart();
const settings$ = new Rx.Subject<any>();
core.uiSettings.get$.mockReturnValue(settings$);
const unmount = renderApp(params, core);
// Verify some expected DOM element is rendered into the element
expect(params.element.querySelector('.some-app-class')).not.toBeUndefined();
// Verify that subscribed to settings$
expect(settings$.observers.length).toBeGreaterThan(0);
unmount();
// Verify the element is empty after unmounting
expect(params.element.innerHTML).toEqual('');
// Verify that unsubscribed correctly
expect(settings$.observers.length).toBe(0);
});
});
We can extract some of this logic in a custom matcher to be able to write something like this:
expect(settings$).toHaveNoSubscriptions();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the input here, Subjects make this much easier / possible. I think we should encourage this pattern for more fine-grained results but rely on something like drool to make this foolproof.
|
||
## Plugin Integrations | ||
|
||
_How to test against specific plugin APIs (eg. data plugin)_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imho it makes sense to draw the line between API tests and plugin contract tests. With the NP we should encourage plugins to interacts via interfaces instead of API. It means a significant shift in testing as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some guidelines on what this section should detail in the future, let me know if that lines up with what you're thinking.
The Kibana Platform introduces new concepts that legacy plugins did not have concern themselves with. Namely: | ||
- **Lifecycles**: plugins now have explicit lifecycle methods that must interop with Core APIs and other plugins. | ||
- **Shared runtime**: plugins now all run in the same process at the same time. On the frontend, this is different behavior than the legacy plugins. Developers should take care not to break other plugins when interacting with their enviornment (Node.js or Browser). | ||
- **Single page application**: Kibana's frontend is now a single-page application where all plugins are running, but only one application is mounted at a time. Plugins need to handle mounting and unmounting, cleanup, and avoid overriding global browser behaviors in this shared space. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably we should introduce autotests for memory leak detection. just a handful for the most critical parts https://github.com/samccone/drool and friends
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using drool to verify app unmounting cleaning would be interesting for sure. It appears we could have a single mechanism that tests each application automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should I create an issue to investigate this option? it's not a critical problem right now, can be done later
68bebce
to
3bb4c0c
Compare
3bb4c0c
to
3987242
Compare
Some updates pushed based on first round of feedback. |
|
||
_How to test your plugin's exposed API_ | ||
|
||
Guidelines: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it shouldn't be hidden in Testing docs and deserves a separate file https://github.com/elastic/kibana/pull/53866/files
Currently there are some karma tests doing visual regression testing (e.g. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's merge as-is. We can update the remaining options in follow-ups.
Summary
Relates to #53135
Adds a new documentation file to cover testing recommendations.
TODO:
Checklist
Use
strikethroughsto remove checklist items you don't feel are applicable to this PR.For maintainers