# -*- coding: utf-8 -*- from odoo.tests.common import TransactionCase from odoo.exceptions import ValidationError from psycopg2 import IntegrityError class TestModelConstraints(TransactionCase): """Test cases for model constraints and validation.""" def setUp(self): """Set up test data.""" super().setUp() self.Model = self.env['model.name'] # Set up minimal test data self.partner = self.env['res.partner'].search([], limit=1) if not self.partner: self.skipTest("No partner available for testing") def test_01_python_constraint_positive_value(self): """Test Python constraint for positive values.""" record = self.Model.create({ 'name': 'Test Record', 'partner_id': self.partner.id, 'amount': 100.0, }) # Test valid positive value record.write({'amount': 50.0}) self.assertEqual(record.amount, 50.0) # Test that negative value raises ValidationError with self.assertRaises(ValidationError) as context: record.write({'amount': -10.0}) self.assertIn('must be positive', str(context.exception).lower()) def test_02_sql_constraint_unique(self): """Test SQL constraint for unique values.""" # Create first record self.Model.create({ 'name': 'Test Record', 'code': 'UNIQUE001', 'partner_id': self.partner.id, }) # Try to create duplicate with self.assertRaises(IntegrityError): with self.cr.savepoint(): self.Model.create({ 'name': 'Test Record 2', 'code': 'UNIQUE001', # Duplicate code 'partner_id': self.partner.id, }) def test_03_required_field_validation(self): """Test that required fields are enforced.""" # Test missing required field raises ValidationError with self.assertRaises(ValidationError): self.Model.create({ 'name': 'Test Record', # Missing required 'partner_id' }) def test_04_field_domain_constraint(self): """Test field domain constraints.""" record = self.Model.create({ 'name': 'Test Record', 'partner_id': self.partner.id, 'state': 'draft', }) # Test valid state record.write({'state': 'confirmed'}) self.assertEqual(record.state, 'confirmed') # Test invalid state raises ValidationError with self.assertRaises(ValidationError): record.write({'state': 'invalid_state'}) def test_05_dependent_field_constraint(self): """Test constraints that depend on multiple fields.""" # Test that start_date must be before end_date with self.assertRaises(ValidationError) as context: self.Model.create({ 'name': 'Test Record', 'partner_id': self.partner.id, 'start_date': '2024-12-31', 'end_date': '2024-01-01', # End before start }) self.assertIn('end date', str(context.exception).lower()) self.assertIn('start date', str(context.exception).lower()) def test_06_conditional_constraint(self): """Test constraints that apply conditionally.""" # Create record in state where constraint doesn't apply record = self.Model.create({ 'name': 'Test Record', 'partner_id': self.partner.id, 'state': 'draft', 'approval_required': False, }) # Confirm - now constraint should apply record.write({'state': 'confirmed', 'approval_required': True}) # Test that missing approval raises error with self.assertRaises(ValidationError) as context: record.write({'approved_by': False}) # Clear approval self.assertIn('approval', str(context.exception).lower()) def test_07_cascading_constraint(self): """Test constraints that cascade to related records.""" parent = self.Model.create({ 'name': 'Parent Record', 'partner_id': self.partner.id, }) child = self.Model.create({ 'name': 'Child Record', 'parent_id': parent.id, 'partner_id': self.partner.id, }) # Test that deleting parent with children raises error with self.assertRaises(ValidationError) as context: parent.unlink() self.assertIn('child', str(context.exception).lower()) def test_08_constraint_bypass_with_context(self): """Test bypassing constraints with context (if applicable).""" # Some constraints can be bypassed with special context record = self.Model.with_context(skip_validation=True).create({ 'name': 'Test Record', 'partner_id': self.partner.id, 'amount': -100.0, # Normally not allowed }) self.assertEqual(record.amount, -100.0)