🔍 Code Extractor

class TestBEValidator

Maturity: 50

Unit test class for validating the BEValidator class, which validates Belgian invoice extraction results including VAT numbers, addresses, IBAN, currency, and legal requirements.

File:
/tf/active/vicechatdev/invoice_extraction/tests/test_validators.py
Lines:
347 - 482
Complexity:
moderate

Purpose

This test class provides comprehensive test coverage for the BEValidator class, ensuring it correctly validates Belgian-specific invoice data including VAT number format (BE prefix), Belgian addresses, standard VAT rates (21%, 12%, 6%, 0%), IBAN format, EUR currency, and mandatory legal requirements like invoice dates. It tests both valid and invalid scenarios, verifying that critical errors fail validation while warnings allow validation to pass.

Source Code

class TestBEValidator(unittest.TestCase):
    """Test cases for the BEValidator class."""
    
    def setUp(self):
        """Set up test environment before each test."""
        self.config = {
            'required_fields': {
                'invoice.number': 'critical',
                'vendor.name': 'critical',
                'amounts.total': 'critical'
            },
            'be_vat_rates': [21, 12, 6, 0]
        }
        self.validator = BEValidator(self.config)
        
        # Sample valid Belgian extraction result
        self.valid_be_extraction = {
            'invoice': {
                'number': 'FACT-12345',
                'issue_date': '2023-01-15',
                'due_date': '2023-02-15'
            },
            'vendor': {
                'name': 'Belgian Test SPRL',
                'address': '123 Rue de Bruxelles, 1000 Bruxelles, Belgique',
                'vat_number': 'BE0123.456.789'
            },
            'amounts': {
                'subtotal': 500.00,
                'vat': 105.00,
                'total': 605.00,
                'vat_rate': 21,
                'currency': 'EUR'
            },
            'payment': {
                'iban': 'BE68 5390 0754 7034',
                'bic': 'KREDBEBB'
            }
        }
    
    def test_validate_be_extraction(self):
        """Test validation of a valid Belgian extraction result."""
        result = self.validator.validate(self.valid_be_extraction)
        self.assertTrue(result.is_valid)
        self.assertEqual(len(result.issues), 0)
    
    def test_validate_be_vat_number(self):
        """Test validation of Belgian VAT number format."""
        # Test invalid VAT number format
        invalid_extraction = self.valid_be_extraction.copy()
        invalid_extraction['vendor'] = {
            'name': 'Belgian Test SPRL',
            'address': '123 Rue de Bruxelles, 1000 Bruxelles, Belgique',
            'vat_number': '0123456789'  # Missing BE prefix
        }
        
        result = self.validator.validate(invalid_extraction)
        self.assertFalse(result.is_valid)  # Belgian VAT format is critical
        self.assertGreaterEqual(len(result.issues), 1)
        
        # Test completely wrong format
        invalid_extraction['vendor']['vat_number'] = 'INVALID-VAT'
        result = self.validator.validate(invalid_extraction)
        self.assertFalse(result.is_valid)
        self.assertGreaterEqual(len(result.issues), 1)
    
    def test_validate_be_address(self):
        """Test validation of Belgian address."""
        # Test non-Belgian address
        invalid_extraction = self.valid_be_extraction.copy()
        invalid_extraction['vendor'] = {
            'name': 'Belgian Test SPRL',
            'address': '123 Main St, Berlin, 10115, Germany',  # Not Belgian address
            'vat_number': 'BE0123.456.789'
        }
        
        result = self.validator.validate(invalid_extraction)
        self.assertTrue(result.is_valid)  # Address is a warning, not error
        self.assertGreaterEqual(len(result.warnings), 1)
    
    def test_validate_vat_rate(self):
        """Test validation of Belgian VAT rates."""
        # Test invalid VAT rate
        invalid_extraction = self.valid_be_extraction.copy()
        invalid_extraction['amounts']['vat_rate'] = 18  # Not a standard Belgian rate
        
        result = self.validator.validate(invalid_extraction)
        self.assertTrue(result.is_valid)  # VAT rate is a warning, not error
        self.assertGreaterEqual(len(result.warnings), 1)
    
    def test_validate_be_iban(self):
        """Test validation of Belgian IBAN."""
        # Test invalid IBAN
        invalid_extraction = self.valid_be_extraction.copy()
        invalid_extraction['payment'] = {
            'iban': 'FR76 3000 6000 0112 3456 7890 189',  # French IBAN
            'bic': 'KREDBEBB'
        }
        
        result = self.validator.validate(invalid_extraction)
        self.assertTrue(result.is_valid)  # IBAN issues are warnings, not errors
        self.assertGreaterEqual(len(result.warnings), 1)
        
        # Test malformatted IBAN
        invalid_extraction['payment'] = {
            'iban': 'BE12345',  # Too short
            'bic': 'KREDBEBB'
        }
        
        result = self.validator.validate(invalid_extraction)
        self.assertTrue(result.is_valid)  # IBAN issues are warnings, not errors
        self.assertGreaterEqual(len(result.warnings), 1)
    
    def test_validate_be_currency(self):
        """Test validation of Belgian currency."""
        # Test non-Euro currency
        invalid_extraction = self.valid_be_extraction.copy()
        invalid_extraction['amounts']['currency'] = 'USD'  # Not EUR
        
        result = self.validator.validate(invalid_extraction)
        self.assertTrue(result.is_valid)  # Currency is a warning, not error
        self.assertGreaterEqual(len(result.warnings), 1)
    
    def test_validate_be_legal_requirements(self):
        """Test validation of Belgian legal invoice requirements."""
        # Test missing invoice date (mandatory in Belgium)
        invalid_extraction = self.valid_be_extraction.copy()
        invalid_extraction['invoice'] = {
            'number': 'FACT-12345',
            # Missing issue_date
            'due_date': '2023-02-15'
        }
        
        result = self.validator.validate(invalid_extraction)
        self.assertFalse(result.is_valid)
        self.assertGreaterEqual(len(result.issues), 1)

Parameters

Name Type Default Kind
bases unittest.TestCase -

Parameter Details

bases: Inherits from unittest.TestCase to provide testing framework functionality including assertions, test discovery, and test execution capabilities

Return Value

As a test class, it does not return values directly. Each test method performs assertions that either pass or fail. The setUp method initializes test fixtures including a BEValidator instance and sample valid Belgian extraction data. Test methods validate different aspects and return None, with pass/fail determined by assertions.

Class Interface

Methods

setUp(self) -> None

Purpose: Initialize test fixtures before each test method runs, creating a BEValidator instance and sample valid Belgian extraction data

Returns: None - sets up instance attributes self.config, self.validator, and self.valid_be_extraction

test_validate_be_extraction(self) -> None

Purpose: Test that a completely valid Belgian extraction result passes validation with no issues

Returns: None - asserts that validation result is valid with zero issues

test_validate_be_vat_number(self) -> None

Purpose: Test validation of Belgian VAT number format, ensuring invalid formats (missing BE prefix, completely wrong format) fail validation

Returns: None - asserts that invalid VAT numbers cause validation to fail with at least one issue

test_validate_be_address(self) -> None

Purpose: Test validation of Belgian addresses, verifying that non-Belgian addresses generate warnings but don't fail validation

Returns: None - asserts that non-Belgian addresses produce warnings but validation remains valid

test_validate_vat_rate(self) -> None

Purpose: Test validation of Belgian VAT rates (21%, 12%, 6%, 0%), ensuring non-standard rates generate warnings

Returns: None - asserts that invalid VAT rates produce warnings but validation remains valid

test_validate_be_iban(self) -> None

Purpose: Test validation of Belgian IBAN format, checking that non-Belgian IBANs and malformed IBANs generate warnings

Returns: None - asserts that IBAN issues produce warnings but validation remains valid

test_validate_be_currency(self) -> None

Purpose: Test validation of Belgian currency (EUR), ensuring non-Euro currencies generate warnings

Returns: None - asserts that non-EUR currency produces warnings but validation remains valid

test_validate_be_legal_requirements(self) -> None

Purpose: Test validation of Belgian legal invoice requirements, ensuring mandatory fields like issue_date cause validation failure when missing

Returns: None - asserts that missing mandatory fields cause validation to fail with at least one issue

Attributes

Name Type Description Scope
config dict Configuration dictionary containing required_fields with criticality levels and be_vat_rates list, used to initialize BEValidator instance
validator BEValidator Instance of BEValidator class being tested, initialized with self.config in setUp() instance
valid_be_extraction dict Sample valid Belgian invoice extraction result containing invoice, vendor, amounts, and payment information, used as baseline for test variations instance

Dependencies

  • unittest
  • datetime
  • logging
  • validators.base_validator
  • validators.be_validator

Required Imports

import unittest
from datetime import datetime
import logging
from validators.base_validator import BaseValidator
from validators.base_validator import ValidationResult
from validators.be_validator import BEValidator

Usage Example

import unittest
from validators.be_validator import BEValidator

# Run a single test
test = TestBEValidator()
test.setUp()
test.test_validate_be_extraction()

# Run all tests in the class
if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(TestBEValidator)
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

# Or use unittest discovery
# python -m unittest test_module.TestBEValidator

Best Practices

  • Each test method is independent and can run in isolation
  • setUp() is called before each test method to ensure clean state
  • Test data is created fresh in setUp() to avoid test interdependencies
  • Tests use deep copies of valid_be_extraction to avoid mutation affecting other tests
  • Tests verify both positive (valid data) and negative (invalid data) scenarios
  • Critical validation failures should set is_valid to False, while warnings should keep is_valid True
  • Each test focuses on a single aspect of validation (VAT number, address, IBAN, etc.)
  • Assertions check both the validation result and the presence of issues/warnings
  • Run tests using unittest discovery or test runner for proper execution

Similar Components

AI-powered semantic similarity - components with related functionality:

  • class BEValidator 86.5% similar

    Belgium-specific invoice data validator that extends BaseValidator to implement Belgian invoice validation rules including VAT number format, address verification, IBAN validation, and legal requirements.

    From: /tf/active/vicechatdev/invoice_extraction/validators/be_validator.py
  • class TestBEExtractor 84.6% similar

    Unit test class for testing the BEExtractor class, which extracts structured data from Belgian invoices using LLM-based extraction.

    From: /tf/active/vicechatdev/invoice_extraction/tests/test_extractors.py
  • class TestUKValidator 78.3% similar

    Unit test class for validating the UKValidator class functionality, testing UK-specific invoice validation rules including VAT numbers, addresses, banking details, and currency.

    From: /tf/active/vicechatdev/invoice_extraction/tests/test_validators.py
  • class TestBaseValidator 74.7% similar

    Unit test class for testing the BaseValidator class functionality, including validation of extraction results, field types, date consistency, amount consistency, and entity-specific validation rules.

    From: /tf/active/vicechatdev/invoice_extraction/tests/test_validators.py
  • class TestAUValidator 73.0% similar

    Unit test class for validating the AUValidator class, which validates Australian invoice extraction results including ABN, GST, banking details, and tax invoice requirements.

    From: /tf/active/vicechatdev/invoice_extraction/tests/test_validators.py
← Back to Browse