Coverage for tests / unit / utils / summary / test_safe_cast.py: 100%

30 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""Unit tests for _safe_cast function in summary_tables module. 

2 

3Tests cover type conversion with fallbacks for int and float values, 

4and error handling for invalid inputs. 

5""" 

6 

7from __future__ import annotations 

8 

9from typing import Any 

10from unittest.mock import patch 

11 

12import pytest 

13from assertpy import assert_that 

14 

15from lintro.utils.summary_tables import _safe_cast 

16 

17# ============================================================================= 

18# Tests for _safe_cast function 

19# ============================================================================= 

20 

21 

22@pytest.mark.parametrize( 

23 ("value", "converter", "default", "expected"), 

24 [ 

25 ("42", int, 0, 42), 

26 ("100", int, -1, 100), 

27 ("0", int, 99, 0), 

28 ], 

29 ids=["basic-int", "with-different-default", "zero-value"], 

30) 

31def test_safe_cast_successful_int_cast( 

32 value: str, 

33 converter: type, 

34 default: int, 

35 expected: int, 

36) -> None: 

37 """Cast string to int successfully with various inputs. 

38 

39 Args: 

40 value: String value to cast. 

41 converter: Value converter function. 

42 default: Default value. 

43 expected: Expected result after casting. 

44 """ 

45 summary = {"count": value} 

46 with patch("lintro.utils.summary_tables.get_summary_value", return_value=value): 

47 result = _safe_cast(summary, "count", default, converter) 

48 assert_that(result).is_equal_to(expected) 

49 

50 

51@pytest.mark.parametrize( 

52 ("value", "default", "expected"), 

53 [ 

54 ("1.5", 0.0, 1.5), 

55 ("3.14159", 0.0, 3.14159), 

56 ("0.0", 1.0, 0.0), 

57 ], 

58 ids=["basic-float", "pi-value", "zero-float"], 

59) 

60def test_safe_cast_successful_float_cast( 

61 value: str, 

62 default: float, 

63 expected: float, 

64) -> None: 

65 """Cast string to float successfully with various inputs. 

66 

67 Args: 

68 value: String value to cast. 

69 default: Default value. 

70 expected: Expected result after casting. 

71 """ 

72 summary = {"duration": value} 

73 with patch("lintro.utils.summary_tables.get_summary_value", return_value=value): 

74 result = _safe_cast(summary, "duration", default, float) 

75 assert_that(result).is_equal_to(expected) 

76 

77 

78@pytest.mark.parametrize( 

79 ("value", "default"), 

80 [ 

81 ("not_a_number", -1), 

82 ("abc", 0), 

83 ("12.34.56", 100), 

84 ], 

85 ids=["text-value", "letters-only", "malformed-number"], 

86) 

87def test_safe_cast_returns_default_on_value_error(value: str, default: int) -> None: 

88 """Return default when value cannot be converted due to ValueError. 

89 

90 Args: 

91 value: Value to test. 

92 default: Default value to return. 

93 """ 

94 summary = {"count": value} 

95 with patch("lintro.utils.summary_tables.get_summary_value", return_value=value): 

96 result = _safe_cast(summary, "count", default, int) 

97 assert_that(result).is_equal_to(default) 

98 

99 

100@pytest.mark.parametrize( 

101 ("value", "default"), 

102 [ 

103 (None, 0), 

104 (None, -1), 

105 (None, 999), 

106 ], 

107 ids=["default-zero", "default-negative", "default-large"], 

108) 

109def test_safe_cast_returns_default_on_type_error(value: Any, default: int) -> None: 

110 """Return default when value causes TypeError during conversion. 

111 

112 Args: 

113 value: Value that causes TypeError. 

114 default: Default value to return. 

115 """ 

116 summary = {"count": value} 

117 with patch("lintro.utils.summary_tables.get_summary_value", return_value=value): 

118 result = _safe_cast(summary, "count", default, int) 

119 assert_that(result).is_equal_to(default)