"""Run with python verify.py [path-to-candidate.py]. No dependencies.""" import importlib.util import itertools import pathlib import sys import unittest path = pathlib.Path(sys.argv[1]) if len(sys.argv) > 1 else pathlib.Path(__file__).with_name('solution.py') spec = importlib.util.spec_from_file_location('candidate', path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) reconcile = module.reconcile def entry(i='a', account='main', amount='0.10'): return {'id': i, 'account': account, 'amount': amount} class LedgerChecks(unittest.TestCase): def test_exact_cents(self): self.assertEqual(reconcile([entry('a'), entry('b',amount='0.20')])['total'], '0.30') def test_signed_amounts(self): self.assertEqual(reconcile([entry(amount='-12.34'), entry('b',amount='2.04')])['total'], '-10.30') def test_duplicate_is_counted_once(self): out = reconcile([entry(), entry()]) self.assertEqual((out['total'],out['unique_entries']), ('0.10',1)) def test_conflicting_duplicate_rejected(self): with self.assertRaises(ValueError): reconcile([entry(), entry(amount='2.00')]) def test_permutation_invariance(self): data=[entry('a','z','1.00'),entry('b','a','2.00'),entry('c','z','-0.30')] wanted={'accounts':[{'account':'a','net':'2.00'},{'account':'z','net':'0.70'}],'total':'2.70','unique_entries':3} for perm in itertools.permutations(data): self.assertEqual(reconcile(perm),wanted) def test_invalid_amounts_rejected(self): for bad in ['1.2','1.234','NaN','Infinity','01.00','1e2','1,00',1.25]: with self.subTest(amount=bad), self.assertRaises(ValueError): reconcile([entry(amount=bad)]) def test_missing_fields_rejected(self): for key in ('id','account','amount'): data=entry();del data[key] with self.subTest(field=key), self.assertRaises(ValueError): reconcile([data]) def test_empty_ledger(self): self.assertEqual(reconcile([]), {'accounts':[],'total':'0.00','unique_entries':0}) def test_large_amount_stays_exact(self): self.assertEqual(reconcile([entry(amount='999999999999999999.99'),entry('b',amount='0.01')])['total'],'1000000000000000000.00') def test_cancellation_has_no_negative_zero(self): self.assertEqual(reconcile([entry(amount='-0.10'),entry('b')])['accounts'],[{'account':'main','net':'0.00'}]) if __name__ == '__main__': unittest.main(argv=[sys.argv[0]],verbosity=2)