docs: update CLAUDE.md with BDD fixture pattern and troubleshooting

Added section 6.2 note about pytest-bdd requiring odoo_env fixture wrapper
instead of direct pytest-odoo env fixture. Updated fixture example to use
odoo_env parameter throughout. Added troubleshooting entry for 'fixture
odoo_env not found' error with reference to the fixture wrapper solution.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Nicholas Riegel 2026-05-30 00:38:12 -04:00
parent d53c1b38eb
commit d1346642be

View file

@ -312,18 +312,25 @@ from pytest_bdd import scenarios, given, when, then, parsers
scenarios('../features/loyalty_discount.feature') scenarios('../features/loyalty_discount.feature')
# CRITICAL: pytest-bdd scenarios expect 'odoo_env' fixture, not pytest-odoo's 'env'.
# Add this fixture to re-export pytest-odoo's env as odoo_env:
@pytest.fixture
def odoo_env(env):
"""pytest-odoo's env fixture, re-exported for BDD step access."""
return env
@pytest.fixture @pytest.fixture
def ctx(): def ctx():
return {} return {}
@given(parsers.parse('a customer with loyalty tier "{tier}"'), target_fixture='customer') @given(parsers.parse('a customer with loyalty tier "{tier}"'), target_fixture='customer')
def make_customer(env, tier): def make_customer(odoo_env, tier):
return env['res.partner'].create({'name': f'BDD-{tier}', 'loyalty_tier': tier}) return odoo_env['res.partner'].create({'name': f'BDD-{tier}', 'loyalty_tier': tier})
@when(parsers.parse('I create a sale order with {qty:d} Widget')) @when(parsers.parse('I create a sale order with {qty:d} Widget'))
def create_order(env, customer, qty, ctx): def create_order(odoo_env, customer, qty, ctx):
product = env['product.product'].search([('name', '=', 'Widget')], limit=1) product = odoo_env['product.product'].search([('name', '=', 'Widget')], limit=1)
ctx['order'] = env['sale.order'].create({ ctx['order'] = odoo_env['sale.order'].create({
'partner_id': customer.id, 'partner_id': customer.id,
'order_line': [(0, 0, {'product_id': product.id, 'product_uom_qty': qty})], 'order_line': [(0, 0, {'product_id': product.id, 'product_uom_qty': qty})],
}) })
@ -802,6 +809,7 @@ post = self.env['blog.post'].sudo().create({
| Test: TransactionCase gets `InFailedSqlTransaction` in subsequent tests | Previous test called `self.env.cr.commit()` breaking savepoint chain | Replace `commit()` with `flush_all()` in code being tested; `commit()` is only allowed in non-test code in production | | Test: TransactionCase gets `InFailedSqlTransaction` in subsequent tests | Previous test called `self.env.cr.commit()` breaking savepoint chain | Replace `commit()` with `flush_all()` in code being tested; `commit()` is only allowed in non-test code in production |
| Test: Mock response returns HTML but code expects JSON | Mock return values must match the data format expected by code under test | Create helper function to generate mocks with correct structure (e.g., JSON string in `.text` field for LLM routers) | | Test: Mock response returns HTML but code expects JSON | Mock return values must match the data format expected by code under test | Create helper function to generate mocks with correct structure (e.g., JSON string in `.text` field for LLM routers) |
| Test: Calling mocked service with wrong parameter name | Test uses different parameter name than actual service signature | Match test calls to actual method signatures (e.g., `topic=` not `prompt=` for LLMRouter.generate()) | | Test: Calling mocked service with wrong parameter name | Test uses different parameter name than actual service signature | Match test calls to actual method signatures (e.g., `topic=` not `prompt=` for LLMRouter.generate()) |
| BDD test: `fixture 'odoo_env' not found` | pytest-bdd scenarios do not automatically map pytest-odoo's `env` fixture | Add `@pytest.fixture def odoo_env(env): return env` wrapper in conftest or test file (section 6.2) |
--- ---