The dead-code cleanup dropped 11 test files that were never wired into tests/__init__.py. Reviewing what they covered turned up real holes, so the worthwhile ones come back, rewritten against the current schema. Blacklists were the serious gap: product, supplier and category exclusions have absolute priority over product discovery and nothing exercised them. The old file had two separate defects. Its supplier fixtures wrote `main_seller_id` directly, but product_main_seller computes that field from `variant_seller_ids`, so the compute reset it to False and the blacklist had nothing to exclude; they now create real supplierinfo records. Worse, four whole classes asserted against `group_order.product_ids` -- the m2m *input* -- instead of the discovery result, so they set `category_ids` and then checked a field they never touched. Those go through `_get_products_for_group_order` now, and three tests that had no assertions at all got some. The remaining three failures were test bugs too, all Odoo 17->18 leftovers: * Date cases assumed `pickup_date` derives from `start_date`. The chain is cutoff -> pickup -> delivery, and a recurring order whose start date has passed rolls forward to the current cycle, so a 2024 order has no 2024 pickup. The new file anchors on future dates and finds the next 29 February dynamically, with a class documenting the roll-forward itself. * `/eskaera/labels` is `type="json"`; the old test hit it with a plain GET and read the resulting 400 as a bug. It is called over JSON-RPC now, and a test pins the 400 so nobody repeats it. Also `uom.uom.categ` -> `uom.category`. * `price_include` is computed in 18.0, so fixtures must set `price_include_override`. On top of that `_get_price` filters taxes by company and defaults to `env.company`, not the fixture's, which left the tax list empty -- `tax_included` was False for the wrong reason. Two of the portal tests were passing for the wrong reason as well: the access guard bounced them to /eskaera, which also answers 200. Membership has to be set from the member side with `is_group`, and a new test checks the final URL rather than the status alone. Each fixture that can silently build the wrong thing now carries a guard test. Left out on purpose: three files were unimplemented placeholders, and test_draft_persistence still deserves recovering (see the notes file). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
147 lines
6.8 KiB
Markdown
147 lines
6.8 KiB
Markdown
# Cobertura de tests — website_sale_aplicoop
|
|
|
|
Estado tras recuperar y reescribir los tests que se habían perdido con la limpieza
|
|
de código muerto (commit `b3999e2`).
|
|
|
|
La suite quedó en verde y creció en unos 90 tests respecto a los 270 que había
|
|
tras la limpieza.
|
|
|
|
Los ficheros originales, si alguna vez hacen falta:
|
|
|
|
```bash
|
|
git show b3999e2^:website_sale_aplicoop/tests/<fichero>.py
|
|
```
|
|
|
|
---
|
|
|
|
## Recuperado y arreglado
|
|
|
|
### 1. `test_product_discovery.py` — blacklists y descubrimiento (46 tests)
|
|
|
|
Era el hueco grave: **ningún test cubría las tres blacklists**, que son lógica viva
|
|
con "prioridad absoluta" sobre el descubrimiento
|
|
([group_order.py:571-627](models/group_order.py#L571-L627)).
|
|
|
|
Dos bugs distintos en el fichero original:
|
|
|
|
- **`TestSupplierBlacklist` (6 fallos)**: el fixture escribía `main_seller_id` en el
|
|
`create` del template, pero en el addon OCA `product_main_seller` ese campo es
|
|
*computed + store* derivado de `variant_seller_ids` — el compute lo pisaba a `False`,
|
|
los productos quedaban sin proveedor principal y la blacklist no tenía nada que
|
|
excluir. Arreglado creando `product.supplierinfo` de verdad, más un test-guarda
|
|
(`test_main_seller_is_computed_from_supplierinfo`) para que no vuelva a pasar en
|
|
silencio.
|
|
- **Cuatro clases enteras no probaban el descubrimiento**: hacían aserciones contra
|
|
`group_order.product_ids`, que es el campo m2m de *entrada*, no el resultado. Es
|
|
decir, asignaban `category_ids` y comprobaban `product_ids`, así que sólo podían
|
|
fallar; y algunas "pasaban" por el motivo equivocado (el campo estaba vacío de
|
|
todos modos). Tres tests no tenían ni una aserción. Todo reescrito contra
|
|
`_get_products_for_group_order`.
|
|
|
|
Añadido de paso: productos archivados, pedido sin ninguna fuente, id inexistente, y
|
|
el contrato de ordenación real (`is_out_of_stock`, `website_sequence`, nombre).
|
|
|
|
### 2. `test_date_edge_cases.py` — calendario (12 tests)
|
|
|
|
Sustituye al antiguo `test_edge_cases.py`. Los 4 fallos que había eran **del test**,
|
|
no de producción: daban por hecho que `pickup_date` se calcula desde `start_date`,
|
|
cuando en realidad la cadena es `cutoff_date` → `pickup_date` → `delivery_date`, y
|
|
para un pedido recurrente con `start_date` pasada la referencia pasa a ser **hoy**
|
|
(el ciclo avanza al actual). Un pedido de 2024 no tiene fecha de recogida en 2024.
|
|
|
|
Los nuevos anclan en fechas **futuras** para que el avance de ciclo no mueva el caso
|
|
bajo los pies, y buscan el próximo 29-F dinámicamente (no hay fechas quemadas que
|
|
caduquen). Cubren: recogida justo en 29-F, ciclo que cruza el 29-F, entrega el 1-M,
|
|
cruce de mes y de año, último día de mes, rejilla mensual desde un ancla de 31-E y
|
|
en febrero bisiesto. `TestRollForwardBehaviour` documenta el avance de ciclo, que es
|
|
justo lo que el test viejo malinterpretaba.
|
|
|
|
### 3. `test_portal_routes.py` — humo HTTP con usuario portal (8 tests)
|
|
|
|
Une los tres ficheros portal borrados. Los fallos eran del test:
|
|
|
|
- **`/eskaera/labels` devolvía 400**: la ruta es `type="json"` y el test la llamaba
|
|
con un GET plano. Odoo responde 400 correctamente. Ahora se llama por JSON-RPC
|
|
(`make_jsonrpc_request`), y hay un test que fija ese 400 del GET para que nadie
|
|
repita el error.
|
|
- **`uom.uom.categ` no existe** en Odoo 18 (es `uom.category`), y `factor_inv` →
|
|
`factor`.
|
|
- **La afiliación al grupo no se aplicaba**: hay que poner `is_group=True` en el
|
|
grupo y asignar `group_ids` desde el *miembro* (es el idioma que usa
|
|
`test_record_rules.py`). Sin eso el guard rebotaba a `/eskaera`.
|
|
|
|
Ojo con esto último: el smoke test original sólo miraba `status_code == 200`, y el
|
|
rebote a la lista **también** devuelve 200 — pasaba sin que el socio entrase nunca a
|
|
la tienda. Añadido `test_shop_page_is_not_bounced_to_the_list`, que comprueba la URL
|
|
final.
|
|
|
|
### 4. `test_price_with_taxes_included.py` — impuestos (14 tests)
|
|
|
|
Dos causas, ambas del test:
|
|
|
|
- **`price_include` es computed en Odoo 18**, derivado de `price_include_override`
|
|
(Selection `tax_included`/`tax_excluded`). El fixture escribía `price_include=True`
|
|
y se descartaba en silencio. Añadido `test_price_include_is_driven_by_the_override`
|
|
como guarda.
|
|
- **`_get_price` filtra los impuestos por compañía**, y su parámetro `company` cae
|
|
por defecto en `self.env.company`. Como el fixture crea una compañía propia, la
|
|
lista de impuestos salía **vacía** y `tax_included` era siempre `False`. Nótese que
|
|
`test_oca_get_price_returns_base_without_tax` pasaba por este motivo equivocado.
|
|
Ahora todas las llamadas van por un helper que pasa `company=self.company`.
|
|
|
|
---
|
|
|
|
## Sin recuperar (no había nada que rescatar)
|
|
|
|
Tres ficheros eran plantillas sin implementar — setUp seguido de métodos con
|
|
`# Placeholder: will be implemented...` y cero aserciones, o aserciones sobre
|
|
diccionarios simulados en vez de llamar al controlador:
|
|
|
|
- `test_endpoints.py`
|
|
- `test_helper_methods_phase1.py`
|
|
- `test_phase2_eskaera_shop.py`
|
|
|
|
---
|
|
|
|
## Pendiente
|
|
|
|
### `test_draft_persistence.py` — persistencia de borradores
|
|
|
|
Lo único de los 11 ficheros que aún no se ha rehecho. Cubría casos que hoy no cubre
|
|
nadie (`test_save_order_endpoints.py` y `test_group_order_status_endpoint.py` cubren
|
|
el guardado y el ciclo, no esto):
|
|
|
|
- **el precio del borrador es una foto fija**: cambiar `list_price` después no altera
|
|
el borrador ya guardado. El más valioso — es una garantía de negocio real (al socio
|
|
se le respeta el precio que vio) y ahora mismo nada la protege.
|
|
- borrador con producto archivado después de guardarlo
|
|
- borrador de un pedido ya cerrado / de hace 6 meses
|
|
- un borrador no es visible para otro usuario
|
|
- recuento de borradores por usuario
|
|
|
|
Sólo 2 de sus 14 tests fallaban, así que la recuperación debería ser barata.
|
|
|
|
### Huecos menores
|
|
|
|
- Transiciones de estado **ilegales** (draft→closed, cancelled→open). La suite cubre
|
|
las legales en `test_group_order.py`.
|
|
- `available_products_count` fuera del contexto de blacklists (dentro de ellas ya
|
|
está cubierto).
|
|
|
|
Nota: las constraints `_check_company_groups` y `_check_dates` **sí** están cubiertas
|
|
(`test_multi_company.py:147`, `test_group_order.py:66`) — no son hueco.
|
|
|
|
---
|
|
|
|
## Conclusión sobre los "posibles bugs de producción"
|
|
|
|
Los tres que quedaron marcados para investigar (fechas 29-F, `/eskaera/labels` 400,
|
|
`tax_included`) resultaron ser **todos bugs de los tests**, en su mayoría restos de la
|
|
migración 17→18: `is_supplier`, `main_seller_id`, `uom.uom.categ`, `factor_inv`,
|
|
`price_include`. No apareció ningún bug de producción.
|
|
|
|
Lo que sí apareció, y es más incómodo, son **tests que pasaban por el motivo
|
|
equivocado** — el smoke test del portal que se conformaba con el rebote, y
|
|
`test_oca_get_price_returns_base_without_tax` que verificaba `tax_included == False`
|
|
sobre una lista de impuestos vacía. Por eso cada arreglo lleva ahora un test-guarda
|
|
que falla si el fixture deja de construir lo que dice construir.
|