The name "Payment Acquirer Test" of the acquirer bundled with the module
`payment_test` is confusing. It is actually the only acquirer that
doesn't connect to a test API, and its purpose is not to make test
transactions but to showcase the integration of other apps (Accounting,
Sales, eCommerce, Subscriptions) with demo payments.
Hence, the module is renamed to `payment_demo` along with its data and
technical keys to better make the distinction between acquirers' test
environment and demo payments.
task-2853481
closesodoo/odoo#99397
Related: odoo/upgrade#3846
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
The unconditional setting made a lot of sense before the new test
tags (95b4f2ab4b) when the test module
was a test tag: filtering the module out of the existing tags would be
difficult.
However since then the tags should only contain "actual" tags,
therefore inheriting tags (and tagging mixins or Common cases) should
not be an issue anymore.
Part-of: odoo/odoo#98814
When profiling an HTTPCase the only result will be the starting of the
browser and the ready/ok code. All requests are in other thread
and are not profiled.
HTTPCase profiler will now patch the _get_profiler_context_manager
in order to enable profiler on all requests during this time
closesodoo/odoo#99119
X-original-commit: 77d110de242c8b8e9b0f09dcecad25c203f32535
Signed-off-by: Julien Castiaux <juc@odoo.com>
Some tests are randomly failling because /web takes more than 10 seconds
to load. A future pr will speedup /web but waiting for that a small
bump of the timeout should help.
closesodoo/odoo#99198
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
The qunit loading is now arroud 15 seconds, breaking sometimes because
of the 15 seconds timeout.
A quick and dirty fix increases the timeout to 20 (freeze time)
An deeper investigation is needed to speed up this page.
Pregeneration of assets bundle may help
closesodoo/odoo#99163
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
Currently e.g. syntax errors during the import are logged as
exceptions but they don't fail the loading / testing.
Update the loading using more modern loading APIs, in order to not
catch them at all (let them bubble up normally), and instead just
find *IF* a module has a tests submodule before trying to load
in (LBYL).
Fixes#80198closesodoo/odoo#97957
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
When test are skipped, we don't have any information of why.
It seems important to log also the reason, it can help
developers to find the source of issues (example: when your chrome
doesn't the devtools active: you just know that test is skipped, but
don't know why)
closesodoo/odoo#97481
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Since 54ea956490 the form view has an
"urgentSave" fallback when the page is unloaded (tab closed, page
navigated away from, ...).
In tours, this translates to new network requests being performed
during the browser cleanup, possibly chaining further into more
network events.
Flag these tours as incorrect (by making them fail if we find a form
in edition mode after receiving `"test successful"`).
Adjust testing of http cases because I've added an empty line between
the signal and the actual message for better readability on complex
error messages.
Also provide opt-out, as for some tours it's difficult to impossible to
truly fix them: the `allow_end_on_form` class attribute can be set to
`True` in order to disable the new behaviour.
To implement this, update the browser runner receive the test class
directly (rather than just the test class' name) for more
introspection flexibility.
Part-of: odoo/odoo#96517
Currently, when enabling watch mode on a tour the tour's timeout does
not change. This is usually an issue because:
- watch mode makes tours a bit slower, so they can timeout even
without doing anything
- trying to diagnose what's wrong, it's common to add check steps with
a long timeout or even a `debugger` statement, which trips the
python-side timeout and kills the tour
To avoid needing to remember to update the timeouts (then revert them
afterwards), just bump the timeout to 1h by default, or 10x the
original time for very long tours (e.g. qweb test suite, which
currently has a 30mn timeout).
While at it, forward the watch mode status to the client via the QS,
so we can eventually make use of it for one reason or an other.
closesodoo/odoo#96994
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Auto retry can be usefull to avoid breaking a build because of a
small tour or query count, but for long tests like qunit, this can be
painfull when a real error is triggered.
This commit proposes to disable autoretry on demand for some tests
to solve this issue.
This may be applied on all tests longer than a few seconds.
closesodoo/odoo#95440
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Before this commit Chrome's "touch mode" was enabled in both desktop and
mobile-like tests suite (when run headless).
To better match real usecases, this commit adds an option to
enable "touch mode" only in mobile tests suites; keeping it disabled in
desktop ones.
Part-of: odoo/odoo#95924
Uses a dedicated logger (for easier filtering / silencing) for
results output, and provides rough (module-level) stats in INFO but
detailed (test-level) in DEBUG.
Also updates the global query counter (`odoo.sql_db.query_counter`) to
update after each query rather than on close: with test cursors the
actual underlying counter is only rarely flushed.
closesodoo/odoo#95420
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Previously, the test runner would evaluate an expression to check if the
browser test that is about to be run is ready, but before the test is
ready, this expression may be invalid as the variables used in the
expression may not be defined yet, causing a ReferenceError to be thrown
by Chrome.
In Chrome >=102, errors that are thrown when writing code in the console
or by using Runtime.evaluate over CDP are thrown in the context of the
current tab, which means that they trip registered error handlers in
that tab. In Odoo, this means that we show error dialogs with the
traceback.
In the tour manager, when we are looking for an element to trigger, we
only look for that element inside dialogs if there are any dialogs open
(unless the in_dialog option is false on that specific step). This means
that if an error dialog is open, most tours will fail (which is actually
what we want).
In order to avoid opening a bunch of error dialogs while waiting for the
tour to be ready, we simply wrap the ready expression in a try catch so
that it doesn't throw an error, and simply returns a undefined until the
tour is ready instead of throwing a ReferenceError.
closesodoo/odoo#95635
X-original-commit: 3872dbd63233d4c6d961a3cd896b84e4301a1f84
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Signed-off-by: Samuel Degueldre <sad@odoo.com>
In the web client, in a real use case, it's not possible
to write on fields which are invisible,
as it's not possible to write on fields which are readonly.
This is a first step in the goal to change the behavior
of the `groups=` attribute in the back-end views,
to remove them for the view instead of making them invisible.
This is mainly to reduce the diff of the revision that will introduce
the mentioned above behavior change.
As nodes with `groups=` will be removed from the view
when the user doesn't have the group, it's no longer possible
to set a value on a field having a `groups=` the user doesn't have
in the `Form` test class, as the field will no longer be at all in the
view.
However, these unit tests shouldn't have been able to set values
on invisible fields in the first place.
This revision therefore aims to correct the unit tests setting value
on fields which were invisible because the user executing the
test was not part of the required group(s) for these fields
to be visible in the view.
closesodoo/odoo#94337
Related: odoo/enterprise#28936
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
Since #91909, the settings form view is tested with different levels
of access rights, post install.
But when the test is run with only the base module, it crashes because
the settings view specified in base is empty, without any field.
On save, the test form reads the view fields, but read fallbacks on
all fields if no field is specified, and it breaks when we try to
compare the read results to the fields requested (empty).
This commit skips the read when no fields is present in the view.
closesodoo/odoo#95340
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
In module mail, invalidating 'message_ids' on a mail thread also
invalidates its inverse field 'res_id' on messages. If you haven't
flushed it before, your cache will be inconsistent, as shown by the test
/mail:TestMailgateway.test_message_process_bounce_records_channel.
In module purchase_stock, add depends on report.stock.quantity. This
ensures that when the model is queried after changes in other models,
the data on which the SQL view depends is flushed to the database before
querying that model's table.
closesodoo/odoo#66938
Related: odoo/enterprise#16722
Signed-off-by: Raphael Collet <rco@odoo.com>
Co-authored-by: Vincent Schippefilt <vsc@odoo.com>
Using `./odoo-bin` to start Odoo, the addons path can contain a `~`, eg
`~/Documents/whatever`.
Those `~` are accepted and work both with the `--addons-path` passed as
the command argument, or in the `.odoorc` config file.
The `@standalone` tests (launched with `./test_module_operations.py`)
however did not work with that `~` as the path was not "normalized".
Neither a `~` in the config file or in the `--addons-path` argument were
working.
While it is not very critical, it is a nice to have to have the same
behavior as the `./odoo-bin` as this made me lose quite some time
figuring why I couldn't use my usual `design-themes` repo addons path.
closesodoo/odoo#94953
X-original-commit: e633092a5932f24eda840e1decca92ed238a3a29
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
Co-authored-by: Xavier-Do <xdo@odoo.com>
When browser_js tests, especially tours, it can sometimes be useful to connect to
chrome devtools in order to follow test execution. This can be tricky since we need to
find the `devtools_port`, browse 127.0.0.1/:`devtools_port` and clic on the link opening the
devtools from a remote adress with a specific version using the devtools websocket adress to
observe the test.
This commit adds an additionnal browser_js parameter, `watch` enabeling to automatically open
a new chrome window/tab with this specific url.
closesodoo/odoo#66769
Related: odoo/documentation#2305
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
When instrumenting the Chrome Browser and asking to navigate to a
location, it happens that the 10 seconds timeout is exceeded.
This happens particularly when executing qunit tests by navigating to
`/web/tests`. This route has an average loading time around 7 seconds
but when the runbot is loaded, it can exceed 10 seconds.
With this commit, the timeout is set to 15s. It would be better to split
the qunit tests by module in order to avoid the huge assets bundle
generation.
closesodoo/odoo#92699
X-original-commit: 6c0fa6b72bf5d15e8323b81cf930a01d4c0f3291
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
When retrying a test, if a deprecation warning has been emitted the
first time, it will not be re-emitted the second time, and will
therefore not be shown in logs. Use warnings.catch_warnings() to reset
the "emission counter" of the warnings.
Part-of: odoo/odoo#92411
This provides a new API for those operations, in order to make the
distinction between the use cases more explicit. The former API was
using obscure parameter combinations to correspond to various cases.
In the summary below, `fnames` is an iterable of field names. If the
parameter is not given, it means "all fields" in the given context.
Note that method recompute() is now mostly private, as it should not be
used in business code.
# process pending computations and updates
records.env.flush_all() # all fields of all models
records.flush_model(fnames) # the fields of all records of the model
records.flush_recordset(fnames) # the fields of the given records
# process pending computations, became non-public methods
records.env._recompute_all() # all fields of all models
records._recompute_model(fnames) # the fields of all records of the model
records._recompute_recordset(fnames) # the fields of the given records
# invalidate the cache of fields
records.env.invalidate_all() # all fields of all models
records.invalidate_model(fnames) # the fields of all records of the model
records.invalidate_recordset(fnames) # the fields of the given records
Part-of: odoo/odoo#87527
When a subtest fails, the failure or error is taken into account and even if
the subtest was silenced the test itself logs an ERROR with the count of
failures.
With this commit, at the first try, the subtest result is not taken into
account.
closesodoo/odoo#91974
X-original-commit: 96ca5bb6d7aeb54dfb8d5453edaf04b2ea903d41
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Refactor the `load_views` API so it no longer sends multiple times the same
fields description.
e.g.
When `load_views` is called to get the kanban, tree and form views,
the list of fields of the model was sent 4 times:
- Once for each view, with only the fields used in the view,
in `['fields_views']['kanban']['fields']` for instance
- Once globally, with all the fields of the model, in `['fields']`
The goal of this revision is to change that so it sends the list of all fields
only once.
In addition, if a view contains x2many fields,
the fields description of the comodel is also sent.
It was sent in the `views` key of the view fields dict.
e.g.
When calling `load_views` of `res.partner` to get the kanban,
tree and form views,
the `res.partner` fields description was actually sent 6 times:
- Once for each view
- Once globally
- Once for each view of the many2many field `child_ids` of the form view, in
- `['fields_views']['form']['fields']['child_ids']['views']['kanban']['fields']`
- `['fields_views']['form']['fields']['child_ids']['views']['form']['fields']`
The change suggested in this revision is to:
- Remove the fields description for each view in `['fields_views']`.
As it no longer contains the fields,
the key becomes `['views']` instead of `['fields_views']`.
- Replace the dict key `['fields']` by `['models']`,
which is a dict with as key the model name and as values
the model fields description. It contains the fields description
for all models implied in the view:
the model of the main view and the model of all one2many and many2many fields.
With this change, the fields description will only be sent once by model
implied in the view.
In addition, the web client was getting the information about the fields
sometimes in the global fields description list (e.g. `['fields']`),
sometimes in the fields description list of the view type
(e.g. `['fields_views']['form']['fields']`),
making it a pain to try to make changes / performance gain
in these field description dictionaries, because you never knew in which dict
the web client was getting its info.
Now, as there is only one place to get the fields description from,
it's clearer and cleaner.
- one2many and many2many fields views are passed directly in the main view
architecture rather than being put in the `views` key
of the field description.
This is actually easier to treat by the web client,
and this will allow in a future work to cache an entire view in one block
of text rather than having to combine multiple cached blocks of text
to return one view.
- one2many and many2many fields which do not have directly embedded views
have their views directly injected in the architecture,
so the web client doesn't have to do RPC calls to `load_views`
for each one2many and many2many fields not having embedded views.
For instance, this allow to reduce the number of RPC calls to `load_views`
from 8 to 1 when loading the form of `product.product`.
Currently, this behavior is limited to 1 level deep but we consider making it
go all the way down in future works. We did not do it for the moment because
in certain cases it rises the processing time and the size (bytes) too much.
e.g. the sale.order view can be 5 levels deep,
meaning you can reach 4 dialogs on top the main view.
```
sale.order form > order_line > sale.order.line form > invoice_lines >
account.move.line form > asset_ids > account.asset form >
depreciation_move_ids > account.move form.
```
This will also benefit in future works to cache an entire view in one block
of text rather to having to combine multiple cached block of text
to get one view.
- `fields_view_get` becomes `get_view`.
As it no longer returns the fields description,
keeping the `fields` in the name `fields_view_get` no longer makes sense.
Hence removing `fields` from the method name, it becomes `view_get`.
As it gets renamed anyway, we take the opportunity to rename it `get_view`,
which is more in line with the general getter/setter guidelines
in the model object world.
- `_fields_view_get` becomes `_get_view`. For the same reasons than above.
- `load_views` becomes `get_views`.
This is not mandatory, there is no technical reason to rename `load_views` as
it practically sends the same info as before,
the view architectures and their fields description. Just in another way.
We just take the opportunity of this pull request to suggest a cleaner API:
`_get_view`, `get_view` and `get_views`.
- Arguments `toolbar=False, submenu=False` fo the methods
`_fields_view_get` and `fields_view_get` are converted to a kwargs `**options`
in `_get_view` and `get_view`.
The rationale is that submenu was already no longer used (deprecated)
and the mobile options is introduced.
The mobile options is necessary to tell the server to send the mobile views
for x2many fields (kanban instead of tree).
Instead of adding a new argument each time we add a new option to
`fields_view_get`, it seems wiser to have a kwargs `**options` to avoid
to re-write all overrides each time a new option is introduced.
- `_fields_view_get` returned a dict containing the arch in text and some of the
view information. Now, `get_view` returns a tuple with the view architecture
as an `etree` node, and the view as a browse record. The rationale is that all
overrides of `_fields_view_get` were about modifying the arch only
(e.g. changing the address format/re-organizing the address related field
nodes of the partner according to the company country).
To do so, all these overrides were doing `etree.fromstring` to parse the arch
which was sent in text to convert it to an `etree`,
then operations were done on the `etree`,
and then `etree.tostring` was called to convert back the arch to string.
With this change of signature to send the arch as an `etree`,
all these back and forth `etree.fromstring` -> `etree.tostring` are avoided,
allowing some performance gain and less code in the end.
- A cleanup of the keys returned in the dict of `fields_view_get`
has been performed in `get_view`:
- `fields` is removed, as explained above,
- `view_id` is renamed `id`,
- `name` is removed, it was unused by the web client,
- `type` is removed, it was unused by the web client,
- `field_parent` is removed, it was unused by the web client,
- `base_model` is removed, it was unused by the web client.
- `filters` is moved from the global dict returned by `load_views`
(now `get_views`) to the dict returned by `fields_view_get` (now `get_view`)
as it applies only to the `search` view type.
- Retro-compatible methods for the 3 methods
`fields_view_get`, `_fields_view_get` and `load_views` are provided,
with deprecation warnings in them.
- The web client could cache the model fields description
(as it already caches the views),
so it doesn't need to fetch them again if it asks for another view of a model
for which he already has the fields description.
If we do so, `get_views` could return only the list of models used by
the views, without the fields description as of now,
and the web client would then call `fields_get` independently only for
the models for which it doesn't have yet the fields description.
This would avoid the server to return the fields description
and to call `fields_get`, which is costly, for each `get_views`,
therefore gaining performances.
- Inject the views of the one2many and many2many fields all the way down,
unlimited depth level, as explained above.
- Cache with `ormcache` the architecture of back-end views.
This is already done for qweb views, it's not done for back-end views.
Therefore the postprocessing of the views is performed for each `get_views`,
which is costly, while the view architecture doesn't change for users
belonging to the same groups, according to the groups implied by the view.
This pull request is co-authored by
Aaron Bohy (aab) for the web client part and
Denis Ledoux (dle) for the server part.
Part-of: odoo/odoo#87522
Before this commit, since https://github.com/odoo/odoo/pull/83574,
attempting to join a call through the channel guest page while being
logged as a portal user would give an acess error.
This commit fixes this issue
closesodoo/odoo#87995
X-original-commit: e6a637dc1d4e024c67b946fbe26a1b1e0dd144f3
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Because the `savepoint` and `clear` calls are nested inside the
`assertRaises` context, if one of them happens to throw *the exception
we're looking for* the interpreter will jump back to the `with`, the
`assertRaises` will swallow the exception (and count it as a success)
and the function will end having not gone through a `yield`.
This is rather frustrating to debug as it's easy to forget that a
`with` is a control flow structure, leading to a seemingly impossible
error.
We can fix this by initializing and `__enter__`-ing the savepoint
first, but doing this by hand is a bit iffy and not really
future-proof as the addition of more fallible steps during the
initialization phase of `_assertRaises` could lead to the savepoint
not being properly disposed of. Furthermore once in the scope of the
"actual" assertRaises we want the savepoint to unwind first (otherwise
the savepoint won't be rolled back when the exception *we are
expecting* gets raised).
As it turns out `ExitStack` offers the solution to our woes though
it's a bit tricky at first glance: while modifying the cleanup queue
in-place is haram, `pop_all` allows moving cleanup callbacks from one
queue to the next.
This means we can first add the savepoint to one stack and get its
errors (if any) correctly reported, cover the rest of the
initialization, then move the savepoint from one stack to an other, in
order to correctly order the coverage of the `yield` (and the userland
code).
closesodoo/odoo#87733
X-original-commit: b1cd4e4e3c918b4b08d27b30b1017fc898d4b08a
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
For payment_buckaroo and payment_sips (at least) running with a
non-standard port is an issue to the `test_redirect_form_value` tests:
while the form and test will use respectively the base_url and the
configuration port, both check a response signature which is
predicated upon a base url of `http://127.0.0.1:8069`.
This means the test does not pass when run with a different port, and
may not pass if the database was installed with a different port
either (because this may have caused the `web.base_url` to be set to
the installation port).
The other payment modules don't seem to have such signature
verification and thus apparently don't mind running with non-default
port.
Update in 15.2: `test_webhook_notification_confirms_transaction` also
broke but differently, because the payment utils would fetch (and use)
the `web.base.url` they get confused if a db is installed using one
port then the tests are run using an other (or something along those
lines), despite `HttpCase` trying to set the `web.base.url` (could be
an ordering thing).
Anyway a working solution seems to be to *remove* the bespoke code
from `PaymentTestUtils` and fix `HttpCase.base_url()` so it uses the
right port (apparently that'd never been fixed). This does require
adapting the patch being forward-ported as `base_url` is now a
callable, not an attribute.
Also re-remove the attractive nuisance of the odoo.tests.common.PORT
constant which does not work: it is evaluated before the configuration
has been loaded and is thus always set to the default (8069).
closesodoo/odoo#86068
X-original-commit: c28c99f7399da91e1a6176d6f97d4fc947013cae
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is the 14th commit of a comprehensive refactor of our HTTP
framework. See odoo/odoo#78857 for complete historic, discussions and
rationnals.
* `request.uid = x` => `request.update_env(user=x)`.
* `request.context = x` => `request.update_env(context=x)`.
* `request.context = dict(request.context, x=y)`
=> `request.update_context(x=y)`.
* `request.cr = None` => `request.cr.close()`.
* `http.mono_db()` => `request.db`.
* `http.dispatch_rpc()` => `service.dispatch_rpc()`.
* `@service.model.check` => `service.model.retrying()`.
* `request.endpoint`
=> `env['ir.http']._match(request.httprequest.path)[0].endpoint`.
* `request.routing_iteration `=> `removed`.
* `request.jsonrequest` => `request.dispatcher.jsonrequest`.
Note that `request.params` is now set much later in the process. If you
are in a situation where you values from the query string or the
http body you can use `request.get_http_params()`.
Note that using the new `request.future_response`, it is possible to
add headers and cookies on the response object before the response
object is initialized. Please note that headers/cookies saved on
the future response will NOT be injected in case of error.
PR: odoo#78857
Task: 2571224
When a test fails and asks for a screenshot, it seems that in some
conditions, the browser has already navigated to the blank page when
capturing the screenshot, resulting in a useless blank screenshot.
With this commit, all the futures are awaited to avoid this race
condition.
closesodoo/odoo#84566
X-original-commit: 37a7b81c28a7ad7c4f225e1463df96bbaf2d5c8f
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Before this, running Chrome was only supported on POSIX-type OS.
This commit adds support for running Chrome on Windows, by swapping
fork()/exec() with `subprocess.Popen`, which is
cross-platform. Linux-specific fixups are implemented via a
`preexec_fn`.
Also fixes the JSON path generation: the url path separator is `/`,
not `os.path.sep`.
closesodoo/odoo#83209
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Backport from the master-httpocalypse-juc test suite in order to observe
the perf of the master branch and to compare them with the httpocalypse.
closesodoo/odoo#84156
Task: 2571224
Signed-off-by: Raphael Collet <rco@odoo.com>
This commit brings the ability to use some feature detection
mechanism used in Odoo. The jquery.touchSwipe library
implementation requires the browser to get ontouch* events from
the window to be available to assert that the browser has touch.
The switch will make the mechanism to work as expected, and
allow tests to use touch events while being correctly executed
because the library expects such events.
closesodoo/odoo#83588
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
HttpCase.base_url() was introduced with ded278b9c2 but many tests were
using the name attribute already. The tests have been adapted to use the
new method.
closesodoo/odoo#82910
Signed-off-by: Julien Castiaux <juc@odoo.com>
Since auto-retry, real errors will lead to doubled errors on runbot.
This can be noisy and hard to understand.
This commit will help with this by using a lower log level on the first
execution. Log 25 are kepts.
closesodoo/odoo#80378
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
When running test tours logging a message to console.error causes the
test tour to fail. Only one such message can cause the tour to fail, if
other message are written on the console they are simply logged in the
odoo logs. The offending message, however, is only shown at the end of
run, as part of the failing test logs. Arguably, it is better to
include it in the browser logs as well.
closesodoo/odoo#75197
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
The http.addons_manifest is a map {module: manifest_dict} that is
populated upon the first http request. This map is basically a module
manifest cache with an extra `addons_path` key, the path of the module
on the file-system. This cache is eagerly populated upon the first http
request, the map is empty in non-http contextes (e.g. cron) which have
been a source of bugs (e.g. 50c8eb1).
A manifest cache is necessary because reading and parsing python files
from the file-system is not that cheap but there is no reason that cache
is located in `odoo.http`. A thin cache layer now wraps
`load_information_from_description_file()`/`load_manifest()` and is
lazily populated.
The `http.addons_manifest` have been removed. The extra `addons_path`
key is now present in the "normal" manifest. The `read_manifest()` was
hardly used so it has been deprecated. The only way to retrieve a
manifest is now `load_information_from_description_file()` which was
renamed `load_manifest()` (no cache) and `get_manifest()` (cache).
Side note about performances, the cache is necessary. Addons manifest
are read-only and reading + parsing python files from the file system is
not a cheap operation. Running the e-commerce tour
`@website_sale.test_04_admin_website_sale_tour` without cache on
`load_manifest()` requires 68,29 secs to complete on my laptop,
exceeding the default 1-minute time frame allowed in tests. Using a
cache the time is down to 36,53 secs. The performance impact is huge.
Part-of: odoo/odoo#79977
* add configuration for `flake8[flake8-rst-docstring]`
* enable docstring-related checks
* fix invalid docstrings in odoo's core & `base`
* fix a few more bits (mostly missing or incorrect `:param:` info
fields) are out of scope for the lint but my editor catches
closesodoo/odoo#74604
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
When Chrome is spawned, the `DevToolsActivePort`file is awaited to read
the port. Sometimes the file is read but is still empty, resulting in a
ValueError when trying to cast into integer. This happens when Chrome
did not have time yet to write into file.
With this commit, we expect the file to contain at least 5 bytes which
is enough to contain the max port number.
closesodoo/odoo#80791
X-original-commit: aab53fbb4e02461e0f23cf202d393e30a73fbc92
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Since #77735 the chrome runner uses a receiver thread to better handle the
full-duplex nature of Chrome's websocket communication.
However that thread was missing the `dbname` threadlocal, leading to some of
the logging and reporting to be mis-configured, and thus the filtering on CI
(runbot) to exlude any logging message emitted from the receiver thread, such
as the screenshot notifications.
Fix by passing the current `dbname` to the receiver thread when spawning it,
and having said receiver start by setting up the threadlocal.
closesodoo/odoo#79808
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
The current system uses an imperative request/response model to a
communication which is full-duplex and thus (hopefully) more suited to
a reactive approach.
This updates the Chrome runner to:
* use a separate thread for reading from Chrome, which limits stalling
/ buffering
* uses futures for request/response cycles
* uses a callbacks system for events (unrequested messages from
chrome)
The test end (success / failure) is also signaled via a future.
This requires a bit more cleanup as the browser is reused for all
tests of a *class*, so e.g. the results future must be reset between
tests.
Also for convenience add debug logging of WS requests / responses,
it's convenient for looking at a test / tour's traffic.
Part-of: odoo/odoo#77735
Explicit flushing of the cursor had been implemented in the "legacy"
`url_open` helper, but it was missing when going through `requests`
directly (via the `opener`), or when performing XML-RPC calls.
Fix that:
* extend `requests.Session` and `xmlrpc.client.Transport` so they take
a cursor
* move the setup of the XML-RPC clients to `setUp` so they can *get*
the cursor
* move the rest of `HttpCase.__init__` to `setUpClass` and drop the
override entirely
* remove the now-redundant flush in `url_open` (as it's done by the
`opener`)
closesodoo/odoo#77359
X-original-commit: c7bdae34690f31960d1fa95b5c3b4052540f5d07
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Jinja as a templating engine was problematic in differents respect:
- introduce external dependency to Odoo (less controll)
- add another templating mechanism in the stack
- specific feature in qweb cannot be reused
- difficulty in rendering easily editable templates
- more knowledge required with no betterment
By replacing jinja with qweb we can now build tools to edit a qweb
that will work with the previously jinja encoded document
(essentially `mail.template` records).
There is a catch however. Some email fields (eg. email_to) used jinja
syntax for rendering dynamic variables (ie. ${object.something} and
${object.something_that_should_not_be_escaped | safe}).
We still want user to use dynamic variables for some char fields (eg.
subject, from, to, ...). We made a new rendering engine called
"inline_template" that will render an expression enclosed by `{{` and
`}}`.
To be able to edit the templates from the backend interface, a
plugin to the Odoo editor has been made for seamlessly edit the
document.
This qweb plugin includes:
- make dynamic variables (eg. `<t t-out="variable"/>`) not editable
(for preventing the user to shoot himself in the foot)
- group and hide related logical branching (ie. t-if, t-elif, and t-else)
in order to see only one at once
- a floating select input to switch visibility of a particular logical
branching
Task-27033
X-original-commit: odoo/odoo@68182baff4
Part-of: odoo/odoo#77377
This pr proposes an auto retry mechanism for tests. This shouldn't
impact normal testing: tests are not supposed to fail, but the growing
number of tests and pull requests can lead to some bottleneck when a
staging fails because of a random error. This mechanism should help to
reduce splits/the need to retry a failed pr.
This branch have been tested with the nightly multi build, creating 40
identical build without test-tags to disable know random errors.
This multi build is used to detect test failing randomly, this is an
excellent candidate to detect the effect of the retry.
On average, with the current base of this pull request, there is between
10 en 15 failures over 40 build.
With the auto retry mechanism, only 1 build failed over 40 builds since
the same error was triggered twice.
This is simply because with the retry mechanism, an error that has a
probability of p to fail randomly will still have a probability of p² to
fail with the retry mechanism. A error that occurs 10% of the time
should only appear 1% of the time with one retry. In most of the case,
the retry is sucessfull: https://runbot.odoo.com/runbot/build/10053257
The current solution to allow to enable this mechanism only in some
cases (staging) is to check an environment variable
"ODOO_TEST_FAILURE_RETRIES" that defines a number of retry.
This will allow to retry more than once if an error still occurs to ofen
with the autoretry.
The mechanism will run multiple time the same test on the same
test_case, meaning that some modification on self may impact the second
execution. The following code is an example of how this could be
problematic, but also a good example to test the auto-retry mechanism.
```python
class TestRetry(HttpCase):
def test_fail(self):
self.t = getattr(self, 't', 0) + 1
if True or self.t == 1:
import logging
_logger = logging.getLogger('test_a')
with self.assertLogs(level="ERROR"):
_logger.error("This shouldn't be log at all")
with mute_logger('test_a'):
_logger.error("This shouldn't be logged (mute)")
_logger.error("This should be log")
```
As we can see here the error logs are also managed, and emit at a lower level the first time, butany log higher than 25 will make the test "failed" and the autoretry mechanism will be triggered. The second time, everything is logged normally. We also need to replace Traceback by _Traceback to avoid being catched by runbot Traceback detection regexes.
The inspiration here commes from the assertLogs, that replace all handlers. The mute_logger had to be adapted to use the same strategy, so that quite_logger won't detect logs catched by mute_logger or assertLogs.
closesodoo/odoo#76336
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>