🔍 Code Extractor

class TestUKValidator

Maturity: 50

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

File:
/tf/active/vicechatdev/invoice_extraction/tests/test_validators.py
Lines:
207 - 344
Complexity:
moderate

Purpose

This test class provides comprehensive test coverage for the UKValidator class, which validates UK-specific invoice extraction results. It tests validation of UK VAT numbers (GB prefix format), UK addresses, standard UK VAT rates (20%, 5%, 0%), UK banking details (sort codes and account numbers), GBP currency, and VAT calculation accuracy. The tests verify that UK-specific validation rules produce appropriate warnings for non-compliant data while maintaining overall validation success for non-critical issues.

Source Code

class TestUKValidator(unittest.TestCase):
    """Test cases for the UKValidator class."""
    
    def setUp(self):
        """Set up test environment before each test."""
        self.config = {
            'required_fields': {
                'invoice.number': 'critical',
                'vendor.name': 'critical',
                'amounts.total': 'critical'
            },
            'uk_vat_rates': [20, 5, 0]
        }
        self.validator = UKValidator(self.config)
        
        # Sample valid UK extraction result
        self.valid_uk_extraction = {
            'invoice': {
                'number': 'INV-12345',
                'issue_date': '2023-01-15',
                'due_date': '2023-02-15'
            },
            'vendor': {
                'name': 'UK Test Ltd',
                'address': '123 London Road, London, W1A 1AA, UK',
                'vat_number': 'GB123456789'
            },
            'amounts': {
                'subtotal': 500.00,
                'vat': 100.00,
                'total': 600.00,
                'vat_rate': 20,
                'currency': 'GBP'
            },
            'payment': {
                'sort_code': '12-34-56',
                'account_number': '12345678'
            }
        }
    
    def test_validate_uk_extraction(self):
        """Test validation of a valid UK extraction result."""
        result = self.validator.validate(self.valid_uk_extraction)
        self.assertTrue(result.is_valid)
        self.assertEqual(len(result.issues), 0)
    
    def test_validate_uk_vat_number(self):
        """Test validation of UK VAT number format."""
        # Test invalid VAT number format
        invalid_extraction = self.valid_uk_extraction.copy()
        invalid_extraction['vendor'] = {
            'name': 'UK Test Ltd',
            'address': '123 London Road, London, W1A 1AA, UK',
            'vat_number': '123456789'  # Missing GB prefix
        }
        
        result = self.validator.validate(invalid_extraction)
        self.assertTrue(result.is_valid)  # VAT format is a warning, not error
        self.assertGreaterEqual(len(result.warnings), 1)
        
        # Test completely wrong format
        invalid_extraction['vendor']['vat_number'] = 'INVALID-VAT'
        result = self.validator.validate(invalid_extraction)
        self.assertTrue(result.is_valid)  # VAT format is a warning, not error
        self.assertGreaterEqual(len(result.warnings), 1)
    
    def test_validate_uk_address(self):
        """Test validation of UK address."""
        # Test non-UK address
        invalid_extraction = self.valid_uk_extraction.copy()
        invalid_extraction['vendor'] = {
            'name': 'UK Test Ltd',
            'address': '123 Main St, New York, NY 10001, USA',  # Not UK address
            'vat_number': 'GB123456789'
        }
        
        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 UK VAT rates."""
        # Test invalid VAT rate
        invalid_extraction = self.valid_uk_extraction.copy()
        invalid_extraction['amounts']['vat_rate'] = 17  # Not a standard UK 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_uk_banking_details(self):
        """Test validation of UK banking details."""
        # Test invalid sort code
        invalid_extraction = self.valid_uk_extraction.copy()
        invalid_extraction['payment'] = {
            'sort_code': '1234-56',  # Wrong format
            'account_number': '12345678'
        }
        
        result = self.validator.validate(invalid_extraction)
        self.assertTrue(result.is_valid)  # Banking details are warnings, not errors
        self.assertGreaterEqual(len(result.warnings), 1)
        
        # Test invalid account number
        invalid_extraction['payment'] = {
            'sort_code': '12-34-56',
            'account_number': '123456'  # Too short
        }
        
        result = self.validator.validate(invalid_extraction)
        self.assertTrue(result.is_valid)  # Banking details are warnings, not errors
        self.assertGreaterEqual(len(result.warnings), 1)
    
    def test_validate_uk_currency(self):
        """Test validation of UK currency."""
        # Test non-UK currency
        invalid_extraction = self.valid_uk_extraction.copy()
        invalid_extraction['amounts']['currency'] = 'EUR'  # Not GBP
        
        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_vat_calculation(self):
        """Test validation of VAT calculation."""
        # Test inconsistent VAT calculation
        invalid_extraction = self.valid_uk_extraction.copy()
        invalid_extraction['amounts'] = {
            'subtotal': 500.00,
            'vat': 120.00,  # Should be 100.00 (20% of 500)
            'total': 620.00,
            'vat_rate': 20,
            'currency': 'GBP'
        }
        
        result = self.validator.validate(invalid_extraction)
        self.assertTrue(result.is_valid)  # Calculation issues are warnings, not errors
        self.assertGreaterEqual(len(result.warnings), 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. Test methods validate that the UKValidator.validate() method returns ValidationResult objects with appropriate is_valid flags and warnings/issues lists.

Class Interface

Methods

setUp(self) -> None

Purpose: Initialize test environment before each test method runs, creating validator instance and sample data

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

test_validate_uk_extraction(self) -> None

Purpose: Test that a completely valid UK extraction result passes validation without issues

Returns: None - performs assertions on validation result

test_validate_uk_vat_number(self) -> None

Purpose: Test validation of UK VAT number format, verifying that invalid formats (missing GB prefix, completely wrong format) generate warnings

Returns: None - performs assertions on validation warnings

test_validate_uk_address(self) -> None

Purpose: Test validation of UK address format, verifying that non-UK addresses generate warnings

Returns: None - performs assertions on validation warnings

test_validate_vat_rate(self) -> None

Purpose: Test validation of UK VAT rates, verifying that non-standard rates (not 20%, 5%, or 0%) generate warnings

Returns: None - performs assertions on validation warnings

test_validate_uk_banking_details(self) -> None

Purpose: Test validation of UK banking details including sort code format (XX-XX-XX) and account number length (8 digits)

Returns: None - performs assertions on validation warnings for invalid sort codes and account numbers

test_validate_uk_currency(self) -> None

Purpose: Test validation of UK currency, verifying that non-GBP currencies generate warnings

Returns: None - performs assertions on validation warnings

test_validate_vat_calculation(self) -> None

Purpose: Test validation of VAT calculation accuracy, verifying that incorrect VAT amounts generate warnings

Returns: None - performs assertions on validation warnings for calculation mismatches

Attributes

Name Type Description Scope
config dict Configuration dictionary containing required_fields with criticality levels and uk_vat_rates list instance
validator UKValidator Instance of UKValidator class being tested, initialized with self.config instance
valid_uk_extraction dict Sample valid UK invoice extraction result containing invoice, vendor, amounts, and payment sections with UK-specific data formats instance

Dependencies

  • unittest
  • datetime
  • logging
  • validators.base_validator
  • validators.uk_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.uk_validator import UKValidator

Usage Example

import unittest
from validators.uk_validator import UKValidator
from tests.test_validators import TestUKValidator

# Run all tests in the class
suite = unittest.TestLoader().loadTestsFromTestCase(TestUKValidator)
runner = unittest.TextTestRunner(verbosity=2)
result = runner.run(suite)

# Run a specific test
test = TestUKValidator('test_validate_uk_extraction')
test.setUp()
test.test_validate_uk_extraction()

# Run tests from command line
# python -m unittest tests.test_validators.TestUKValidator
# python -m unittest tests.test_validators.TestUKValidator.test_validate_uk_vat_number

Best Practices

  • Each test method is independent and can run in isolation
  • setUp() method is called before each test to ensure clean state
  • Tests use deep copies of valid_uk_extraction to avoid state pollution between tests
  • Tests verify both positive cases (valid data) and negative cases (invalid data)
  • Tests check that UK-specific validation issues generate warnings rather than errors
  • All test methods should start with 'test_' prefix for test discovery
  • Use self.assertTrue(), self.assertEqual(), self.assertGreaterEqual() for assertions
  • Test data includes realistic UK-specific formats (GB VAT numbers, UK postcodes, sort codes)
  • Tests validate that non-critical issues (VAT format, address, currency) don't fail overall validation

Similar Components

AI-powered semantic similarity - components with related functionality:

  • class UKValidator 85.7% similar

    UK-specific invoice data validator that extends BaseValidator to implement validation rules specific to UK invoices including VAT number format, UK addresses, VAT rates, and banking details.

    From: /tf/active/vicechatdev/invoice_extraction/validators/uk_validator.py
  • class TestUKExtractor 83.2% similar

    Unit test class for testing the UKExtractor class, which extracts structured data from UK invoices including VAT numbers, dates, amounts, and line items.

    From: /tf/active/vicechatdev/invoice_extraction/tests/test_extractors.py
  • class TestAUValidator 78.5% 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
  • class TestBEValidator 78.3% similar

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

    From: /tf/active/vicechatdev/invoice_extraction/tests/test_validators.py
  • class TestBaseValidator 70.1% 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
← Back to Browse