Skip to content

Commit 03aef0a

Browse files
committed
[FIX] web: remove/update old QUnit documentation
This commit replaces the outdated QUnit documentation with links to the freshly written Hoot/web testing documentation. closes #14919 X-original-commit: 33d7058 Signed-off-by: Julien Mougenot (jum) <jum@odoo.com>
1 parent c450677 commit 03aef0a

File tree

3 files changed

+12
-252
lines changed

3 files changed

+12
-252
lines changed

content/developer/reference/backend/testing.rst

Lines changed: 7 additions & 244 deletions
Original file line numberDiff line numberDiff line change
@@ -281,252 +281,17 @@ Testing JS code
281281

282282
Testing a complex system is an important safeguard to prevent regressions and to
283283
guarantee that some basic functionality still works. Since Odoo has a non trivial
284-
codebase in Javascript, it is necessary to test it. In this section, we will
285-
discuss the practice of testing JS code in isolation: these tests stay in the
286-
browser, and are not supposed to reach the server.
284+
codebase in Javascript, it is necessary to test it.
287285

288-
.. _reference/testing/qunit:
286+
See the :doc:`Unit testing <../frontend/unit_testing>` to learn about the
287+
various aspect of the front-end testing framework, or jump directly to one of the
288+
sub-sections:
289289

290-
Qunit test suite
291-
----------------
290+
- :doc:`Hoot <../frontend/unit_testing/hoot>`
292291

293-
The Odoo framework uses the QUnit_ library testing framework as a test runner.
294-
QUnit defines the concepts of *tests* and *modules* (a set of related tests),
295-
and gives us a web based interface to execute the tests.
292+
- :doc:`Web test helpers <../frontend/unit_testing/web_helpers>`
296293

297-
For example, here is what a pyUtils test could look like:
298-
299-
.. code-block:: javascript
300-
301-
QUnit.module('py_utils');
302-
303-
QUnit.test('simple arithmetic', function (assert) {
304-
assert.expect(2);
305-
306-
var result = pyUtils.py_eval("1 + 2");
307-
assert.strictEqual(result, 3, "should properly evaluate sum");
308-
result = pyUtils.py_eval("42 % 5");
309-
assert.strictEqual(result, 2, "should properly evaluate modulo operator");
310-
});
311-
312-
The main way to run the test suite is to have a running Odoo server, then
313-
navigate a web browser to ``/web/tests``. The test suite will then be executed
314-
by the web browser Javascript engine.
315-
316-
.. image:: testing/tests.png
317-
:align: center
318-
319-
The web UI has many useful features: it can run only some submodules, or
320-
filter tests that match a string. It can show every assertions, failed or passed,
321-
rerun specific tests, ...
322-
323-
.. warning::
324-
325-
While the test suite is running, make sure that:
326-
327-
- your browser window is focused,
328-
- it is not zoomed in/out. It needs to have exactly 100% zoom level.
329-
330-
If this is not the case, some tests will fail, without a proper explanation.
331-
332-
Testing Infrastructure
333-
----------------------
334-
335-
Here is a high level overview of the most important parts of the testing
336-
infrastructure:
337-
338-
- there is an asset bundle named `web.qunit_suite`_. This bundle contains
339-
the main code (assets common + assets backend), some libraries, the QUnit test
340-
runner and the test bundles listed below.
341-
342-
- a bundle named `web.tests_assets`_ includes most of the assets and utils required
343-
by the test suite: custom QUnit asserts, test helpers, lazy loaded assets, etc.
344-
345-
- another asset bundle, `web.qunit_suite_tests`_, contains all the test scripts.
346-
This is typically where the test files are added to the suite.
347-
348-
- there is a `controller`_ in web, mapped to the route */web/tests*. This controller
349-
simply renders the *web.qunit_suite* template.
350-
351-
- to execute the tests, one can simply point its browser to the route */web/tests*.
352-
In that case, the browser will download all assets, and QUnit will take over.
353-
354-
- there is some code in `qunit_config.js`_ which logs in the console some
355-
information when a test passes or fails.
356-
357-
- we want the runbot to also run these tests, so there is a test (in `test_js.py`_)
358-
which simply spawns a browser and points it to the *web/tests* url. Note that
359-
the browser_js method spawns a Chrome headless instance.
360-
361-
362-
Modularity and testing
363-
----------------------
364-
365-
With the way Odoo is designed, any addon can modify the behaviour of other parts
366-
of the system. For example, the *voip* addon can modify the *FieldPhone* widget
367-
to use extra features. This is not really good from the perspective of the
368-
testing system, since this means that a test in the addon web will fail whenever
369-
the voip addon is installed (note that the runbot runs the tests with all addons
370-
installed).
371-
372-
At the same time, our testing system is good, because it can detect whenever
373-
another module breaks some core functionality. There is no complete solution to
374-
this issue. For now, we solve this on a case by case basis.
375-
376-
Usually, it is not a good idea to modify some other behaviour. For our voip
377-
example, it is certainly cleaner to add a new *FieldVOIPPhone* widget and
378-
modify the few views that needs it. This way, the *FieldPhone* widget is not
379-
impacted, and both can be tested.
380-
381-
Adding a new test case
382-
----------------------
383-
384-
Let us assume that we are maintaining an addon *my_addon*, and that we
385-
want to add a test for some javascript code (for example, some utility function
386-
myFunction, located in *my_addon.utils*). The process to add a new test case is
387-
the following:
388-
389-
1. create a new file *my_addon/static/tests/utils_tests.js*. This file contains the basic code to
390-
add a QUnit module *my_addon > utils*.
391-
392-
.. code-block:: javascript
393-
394-
odoo.define('my_addon.utils_tests', function (require) {
395-
"use strict";
396-
397-
var utils = require('my_addon.utils');
398-
399-
QUnit.module('my_addon', {}, function () {
400-
401-
QUnit.module('utils');
402-
403-
});
404-
});
405-
406-
407-
2. In *my_addon/assets.xml*, add the file to the main test assets:
408-
409-
.. code-block:: xml
410-
411-
<?xml version="1.0" encoding="utf-8"?>
412-
<odoo>
413-
<template id="qunit_suite_tests" name="my addon tests" inherit_id="web.qunit_suite_tests">
414-
<xpath expr="//script[last()]" position="after">
415-
<script type="text/javascript" src="/my_addon/static/tests/utils_tests.js"/>
416-
</xpath>
417-
</template>
418-
</odoo>
419-
420-
3. Restart the server and update *my_addon*, or do it from the interface (to
421-
make sure the new test file is loaded)
422-
423-
4. Add a test case after the definition of the *utils* sub test suite:
424-
425-
.. code-block:: javascript
426-
427-
QUnit.test("some test case that we want to test", function (assert) {
428-
assert.expect(1);
429-
430-
var result = utils.myFunction(someArgument);
431-
assert.strictEqual(result, expectedResult);
432-
});
433-
434-
5. Visit */web/tests/* to make sure the test is executed
435-
436-
Helper functions and specialized assertions
437-
-------------------------------------------
438-
439-
Without help, it is quite difficult to test some parts of Odoo. In particular,
440-
views are tricky, because they communicate with the server and may perform many
441-
rpcs, which needs to be mocked. This is why we developed some specialized
442-
helper functions, located in `test_utils.js`_.
443-
444-
- Mock test functions: these functions help setting up a test environment. The
445-
most important use case is mocking the answers given by the Odoo server. These
446-
functions use a `mock server`_. This is a javascript class that simulates
447-
answers to the most common model methods: read, search_read, nameget, ...
448-
449-
- DOM helpers: useful to simulate events/actions on some specific target. For
450-
example, testUtils.dom.click performs a click on a target. Note that it is
451-
safer than doing it manually, because it also checks that the target exists,
452-
and is visible.
453-
454-
- create helpers: they are probably the most important functions exported by
455-
`test_utils.js`_. These helpers are useful to create a widget, with a mock
456-
environment, and a lot of small detail to simulate as much as possible the
457-
real conditions. The most important is certainly `createView`_.
458-
459-
- `qunit assertions`_: QUnit can be extended with specialized assertions. For
460-
Odoo, we frequently test some DOM properties. This is why we made some
461-
assertions to help with that. For example, the *containsOnce* assertion takes
462-
a widget/jQuery/HtmlElement and a selector, then checks if the target contains
463-
exactly one match for the css selector.
464-
465-
For example, with these helpers, here is what a simple form test could look like:
466-
467-
.. code-block:: javascript
468-
469-
QUnit.test('simple group rendering', function (assert) {
470-
assert.expect(1);
471-
472-
var form = testUtils.createView({
473-
View: FormView,
474-
model: 'partner',
475-
data: this.data,
476-
arch: '<form string="Partners">' +
477-
'<group>' +
478-
'<field name="foo"/>' +
479-
'</group>' +
480-
'</form>',
481-
res_id: 1,
482-
});
483-
484-
assert.containsOnce(form, 'table.o_inner_group');
485-
486-
form.destroy();
487-
});
488-
489-
Notice the use of the testUtils.createView helper and of the containsOnce
490-
assertion. Also, the form controller was properly destroyed at the end of
491-
the test.
492-
493-
Best Practices
494-
--------------
495-
496-
In no particular order:
497-
498-
- all test files should be added in *some_addon/static/tests/*
499-
- for bug fixes, make sure that the test fails without the bug fix, and passes
500-
with it. This ensures that it actually works.
501-
- try to have the minimal amount of code necessary for the test to work.
502-
- usually, two small tests are better than one large test. A smaller test is
503-
easier to understand and to fix.
504-
- always cleanup after a test. For example, if your test instantiates a widget,
505-
it should destroy it at the end.
506-
- no need to have full and complete code coverage. But adding a few tests helps
507-
a lot: it makes sure that your code is not completely broken, and whenever a
508-
bug is fixed, it is really much easier to add a test to an existing test suite.
509-
- if you want to check some negative assertion (for example, that a HtmlElement
510-
does not have a specific css class), then try to add the positive assertion in
511-
the same test (for example, by doing an action that changes the state). This
512-
will help avoid the test to become dead in the future (for example, if the css
513-
class is changed).
514-
515-
Tips
516-
----
517-
518-
- running only one test: you can (temporarily!) change the *QUnit.test(...)*
519-
definition into *QUnit.only(...)*. This is useful to make sure that QUnit
520-
only runs this specific test.
521-
- debug flag: most create utility functions have a debug mode (activated by the
522-
debug: true parameter). In that case, the target widget will be put in the DOM
523-
instead of the hidden qunit specific fixture, and more information will be
524-
logged. For example, all mocked network communications will be available in the
525-
console.
526-
- when working on a failing test, it is common to add the debug flag, then
527-
comment the end of the test (in particular, the destroy call). With this, it
528-
is possible to see the state of the widget directly, and even better, to
529-
manipulate the widget by clicking/interacting with it.
294+
- :doc:`Mock server <../frontend/unit_testing/mock_server>`
530295

531296
.. _reference/testing/integration-testing:
532297

@@ -982,8 +747,6 @@ you can use the :meth:`~odoo.tests.BaseCase.assertQueryCount` method, integrated
982747
.. _qunit: https://qunitjs.com/
983748
.. _qunit_config.js: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/static/tests/helpers/qunit_config.js#L49
984749
.. _web.tests_assets: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/views/webclient_templates.xml#L594
985-
.. _web.qunit_suite: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/views/webclient_templates.xml#L660
986-
.. _web.qunit_suite_tests: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/views/webclient_templates.xml#L680
987750
.. _controller: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/controllers/main.py#L637
988751
.. _test_js.py: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/tests/test_js.py#L13
989752
.. _test_utils.js: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/static/tests/helpers/test_utils.js

content/developer/reference/frontend/assets.rst

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ like this:
7575
'web/static/src/js/webclient.js',
7676
'web/static/src/xml/webclient.xml',
7777
],
78-
'web.qunit_suite_tests': [
79-
'web/static/src/js/webclient_tests.js',
78+
'web.assets_unit_tests': [
79+
'web/static/src/js/webclient.test.js',
8080
],
8181
},
8282
@@ -94,10 +94,7 @@ know:
9494
- `web.assets_frontend`: this bundle is about all that is specific to the public
9595
website: ecommerce, portal, forum, blog, ...
9696

97-
- `web.qunit_suite_tests`: all javascript qunit testing code (tests, helpers, mocks)
98-
99-
- `web.qunit_mobile_suite_tests`: mobile specific qunit testing code
100-
97+
- `web.assets_unit_tests`: all javascript unit testing code (tests, helpers, mocks)
10198

10299
Operations
103100
----------

content/developer/reference/frontend/unit_testing/hoot.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ key features are:
1515

1616
As such, it has been integrated as a :file:`lib/` in the Odoo codebase and exports 2 main modules:
1717

18-
- :file:`@odoo/hoot-dom`: (can be used in production code) helpers to:
18+
- :file:`@odoo/hoot-dom`: (can be used in tours) helpers to:
1919

2020
- **interact** with the DOM, such as :js:meth:`click` and :js:meth:`press`;
2121
- **query** elements from the DOM, such as :js:meth:`queryAll` and :js:meth:`waitFor`;
2222

23-
- :file:`@odoo/hoot`: (only to be used in tests) all the test framework features:
23+
- :file:`@odoo/hoot`: (only to be used in unit tests) all the test framework features:
2424

2525
- `test`, `describe` and `expect`
2626
- test hooks like `after` and `afterEach`

0 commit comments

Comments
 (0)