Coverage for backend/django/core/testing/Assertions.py: 86%

44 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-12-18 04:00 +0000

1import json 

2 

3def almost_equal(a, b, tol=1e-2): 

4 try: 

5 return abs(a - b) <= tol 

6 except Exception: 

7 return a == b 

8 

9def remove_ids(obj): 

10 obj = json.loads(json.dumps(obj)) 

11 if isinstance(obj, dict): 

12 obj.pop("id", None) 

13 for v in obj.values(): 

14 remove_ids(v) 

15 elif isinstance(obj, list): 

16 for item in obj: 

17 remove_ids(item) 

18 return obj 

19 

20def almost_equal_dicts(d1, d2, tol=1e-2): 

21 # Remove any 'id' fields 

22 d1 = remove_ids(d1) 

23 d2 = remove_ids(d2) 

24 

25 # Convert int to float for comparison 

26 if type(d1) == int: 

27 d1 = float(d1) 

28 if type(d2) == int: 

29 d2 = float(d2) 

30 

31 # Types differ → not equal 

32 if type(d1) != type(d2): 32 ↛ 33line 32 didn't jump to line 33 because the condition on line 32 was never true

33 return False 

34 

35 # ---- Case: dict ---- 

36 if isinstance(d1, dict): 

37 if d1.keys() != d2.keys(): 37 ↛ 38line 37 didn't jump to line 38 because the condition on line 37 was never true

38 return False 

39 for k in d1: 

40 if not almost_equal_dicts(d1[k], d2[k], tol): 40 ↛ 41line 40 didn't jump to line 41 because the condition on line 40 was never true

41 return False 

42 return True 

43 

44 # ---- Case: list ---- 

45 if isinstance(d1, list): 

46 if len(d1) != len(d2): 46 ↛ 47line 46 didn't jump to line 47 because the condition on line 46 was never true

47 return False 

48 for x, y in zip(d1, d2): 

49 if not almost_equal_dicts(x, y, tol): 49 ↛ 50line 49 didn't jump to line 50 because the condition on line 49 was never true

50 return False 

51 return True 

52 

53 # ---- Case: primitive ---- 

54 return almost_equal(d1, d2, tol) 

55 

56def compare_almost_equal_dicts(instance, d1, d2): 

57 instance.assertTrue( 

58 almost_equal_dicts(d1, d2), 

59 f'Dictionaries not almost equal:\n{json.dumps(d1, indent=2)}\n{json.dumps(d2, indent=2)}' 

60 ) 

61 

62def subset_fields(data, fields): 

63 return [{k: d.get(k) for k in fields} for d in data]