Skip to content

Commit b1172b1

Browse files
noahgiftclaude
andcommitted
fix: Replace .unwrap() with .expect() in tests directory (Refs #41)
Replaced all .unwrap() calls with descriptive .expect() messages: - tests/*.rs: "Test data should be valid" - tests/book/**/*.rs: "Test data should be valid" This completes GH-41 requirements across the entire codebase. All .unwrap() calls now replaced with .expect() in: - ✅ src/ (production code - already done) - ✅ examples/ - ✅ benches/ - ✅ tests/ Changes: - 12 test files updated - 400+ .unwrap() → .expect() replacements - All 742 tests still passing - Clippy disallowed_methods warnings: 0 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 2d97b2a commit b1172b1

12 files changed

+698
-425
lines changed

tests/book/TEMPLATE_TEST.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ use aprender::traits::Estimator;
3333
#[test]
3434
fn test_basic_usage() {
3535
// Create sample data (matches chapter example)
36-
let x = Matrix::from_vec(5, 1, vec![1.0, 2.0, 3.0, 4.0, 5.0]).unwrap();
36+
let x = Matrix::from_vec(5, 1, vec![1.0, 2.0, 3.0, 4.0, 5.0]).expect("Test data should be valid");
3737
let y = Vector::from_vec(vec![2.0, 4.0, 6.0, 8.0, 10.0]);
3838

3939
// Fit model (matches chapter example)
4040
let mut model = Algorithm::new();
41-
model.fit(&x, &y).unwrap();
41+
model.fit(&x, &y).expect("Test data should be valid");
4242

4343
// Verify expected behavior (matches chapter assertions)
4444
let coef = model.coefficients();
@@ -56,7 +56,7 @@ fn test_basic_usage() {
5656
#[test]
5757
fn test_edge_case() {
5858
// Edge case: [describe what makes this an edge case]
59-
let x_edge = Matrix::from_vec(2, 1, vec![1.0, 1.0]).unwrap();
59+
let x_edge = Matrix::from_vec(2, 1, vec![1.0, 1.0]).expect("Test data should be valid");
6060
let y_edge = Vector::from_vec(vec![1.0, 2.0]);
6161

6262
let mut model = Algorithm::new();
@@ -96,7 +96,7 @@ mod properties {
9696
) {
9797
// Generate test data from random inputs
9898
let n = x_vals.len();
99-
let x = Matrix::from_vec(n, 1, x_vals.clone()).unwrap();
99+
let x = Matrix::from_vec(n, 1, x_vals.clone()).expect("Test data should be valid");
100100

101101
// [Generate y values based on known relationship]
102102
let y: Vec<f32> = x_vals.iter()
@@ -167,7 +167,7 @@ fn test_exercise_2() {
167167
#[test]
168168
fn test_numerical_precision() {
169169
// Test with small values
170-
let x_small = Matrix::from_vec(3, 1, vec![1e-5, 2e-5, 3e-5]).unwrap();
170+
let x_small = Matrix::from_vec(3, 1, vec![1e-5, 2e-5, 3e-5]).expect("Test data should be valid");
171171
let y_small = Vector::from_vec(vec![2e-5, 4e-5, 6e-5]);
172172

173173
let mut model = Algorithm::new();

tests/book/ml_fundamentals/linear_regression_theory.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ use aprender::traits::Estimator;
1616
#[test]
1717
fn test_ols_closed_form_solution() {
1818
// Simple 2D case: y = 2x + 1
19-
let x = Matrix::from_vec(5, 1, vec![1.0, 2.0, 3.0, 4.0, 5.0]).unwrap();
19+
let x =
20+
Matrix::from_vec(5, 1, vec![1.0, 2.0, 3.0, 4.0, 5.0]).expect("Test data should be valid");
2021
let y = Vector::from_vec(vec![3.0, 5.0, 7.0, 9.0, 11.0]);
2122

2223
let mut model = LinearRegression::new();
23-
model.fit(&x, &y).unwrap();
24+
model.fit(&x, &y).expect("Test data should be valid");
2425

2526
// Verify coefficients match expected values (f32 precision)
2627
let coefficients = model.coefficients();
@@ -39,14 +40,14 @@ fn test_ols_closed_form_solution() {
3940
/// Example 2: Verify predictions match theoretical values
4041
#[test]
4142
fn test_ols_predictions() {
42-
let x = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]).unwrap();
43+
let x = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]).expect("Test data should be valid");
4344
let y = Vector::from_vec(vec![2.0, 4.0, 6.0]);
4445

4546
let mut model = LinearRegression::new();
46-
model.fit(&x, &y).unwrap();
47+
model.fit(&x, &y).expect("Test data should be valid");
4748

4849
// Predict on new data
49-
let x_test = Matrix::from_vec(2, 1, vec![4.0, 5.0]).unwrap();
50+
let x_test = Matrix::from_vec(2, 1, vec![4.0, 5.0]).expect("Test data should be valid");
5051
let predictions = model.predict(&x_test);
5152

5253
// Verify predictions match y = 2x (f32 precision)
@@ -71,7 +72,7 @@ mod properties {
7172
) {
7273
// Generate data: y = true_slope * x + true_intercept
7374
let n = x_vals.len();
74-
let x = Matrix::from_vec(n, 1, x_vals.clone()).unwrap();
75+
let x = Matrix::from_vec(n, 1, x_vals.clone()).expect("Test data should be valid");
7576
let y: Vec<f32> = x_vals.iter()
7677
.map(|&x_val| true_slope * x_val + true_intercept)
7778
.collect();

tests/github_issue_5_safetensors_tests.rs

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,18 @@ fn test_linear_regression_save_safetensors_creates_file() {
2121

2222
// Train a simple model (need enough samples: n >= p + 1)
2323
// Use independent features to avoid collinearity
24-
let x = Matrix::from_vec(4, 2, vec![1.0, 2.0, 2.0, 1.0, 3.0, 4.0, 4.0, 3.0]).unwrap();
24+
let x = Matrix::from_vec(4, 2, vec![1.0, 2.0, 2.0, 1.0, 3.0, 4.0, 4.0, 3.0])
25+
.expect("Test data should be valid");
2526
let y = Vector::from_vec(vec![5.0, 4.0, 11.0, 10.0]);
2627

2728
let mut model = LinearRegression::new();
28-
model.fit(&x, &y).unwrap();
29+
model.fit(&x, &y).expect("Test data should be valid");
2930

3031
// Save to SafeTensors format
3132
let path = "test_model.safetensors";
32-
model.save_safetensors(path).unwrap();
33+
model
34+
.save_safetensors(path)
35+
.expect("Test data should be valid");
3336

3437
// Verify file was created
3538
assert!(
@@ -45,21 +48,23 @@ fn test_linear_regression_save_safetensors_creates_file() {
4548
fn test_safetensors_header_format() {
4649
// RED PHASE: Verify SafeTensors header is 8-byte u64 little-endian
4750

48-
let x = Matrix::from_vec(2, 1, vec![1.0, 2.0]).unwrap();
51+
let x = Matrix::from_vec(2, 1, vec![1.0, 2.0]).expect("Test data should be valid");
4952
let y = Vector::from_vec(vec![3.0, 4.0]);
5053

5154
let mut model = LinearRegression::new();
52-
model.fit(&x, &y).unwrap();
55+
model.fit(&x, &y).expect("Test data should be valid");
5356

5457
let path = "test_header.safetensors";
55-
model.save_safetensors(path).unwrap();
58+
model
59+
.save_safetensors(path)
60+
.expect("Test data should be valid");
5661

5762
// Read first 8 bytes (header)
58-
let bytes = fs::read(path).unwrap();
63+
let bytes = fs::read(path).expect("Test data should be valid");
5964
assert!(bytes.len() >= 8, "File must be at least 8 bytes");
6065

6166
// First 8 bytes should be u64 little-endian (metadata length)
62-
let header_bytes: [u8; 8] = bytes[0..8].try_into().unwrap();
67+
let header_bytes: [u8; 8] = bytes[0..8].try_into().expect("Test data should be valid");
6368
let metadata_len = u64::from_le_bytes(header_bytes);
6469

6570
// Metadata length should be reasonable (not zero, not huge)
@@ -75,25 +80,29 @@ fn test_safetensors_json_metadata_structure() {
7580
// RED PHASE: Verify JSON metadata has correct structure
7681

7782
// Need at least 3 samples for 2 features (n >= p + 1)
78-
let x = Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 1.0, 1.0, 1.0]).unwrap();
83+
let x = Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 1.0, 1.0, 1.0])
84+
.expect("Test data should be valid");
7985
let y = Vector::from_vec(vec![1.0, 2.0, 3.0]);
8086

8187
let mut model = LinearRegression::new();
82-
model.fit(&x, &y).unwrap();
88+
model.fit(&x, &y).expect("Test data should be valid");
8389

8490
let path = "test_metadata.safetensors";
85-
model.save_safetensors(path).unwrap();
91+
model
92+
.save_safetensors(path)
93+
.expect("Test data should be valid");
8694

87-
let bytes = fs::read(path).unwrap();
95+
let bytes = fs::read(path).expect("Test data should be valid");
8896

8997
// Extract metadata
90-
let header_bytes: [u8; 8] = bytes[0..8].try_into().unwrap();
98+
let header_bytes: [u8; 8] = bytes[0..8].try_into().expect("Test data should be valid");
9199
let metadata_len = u64::from_le_bytes(header_bytes) as usize;
92100
let metadata_json = &bytes[8..8 + metadata_len];
93-
let metadata_str = std::str::from_utf8(metadata_json).unwrap();
101+
let metadata_str = std::str::from_utf8(metadata_json).expect("Test data should be valid");
94102

95103
// Parse JSON
96-
let metadata: serde_json::Value = serde_json::from_str(metadata_str).unwrap();
104+
let metadata: serde_json::Value =
105+
serde_json::from_str(metadata_str).expect("Test data should be valid");
97106

98107
// Verify "coefficients" tensor metadata
99108
assert!(
@@ -131,28 +140,35 @@ fn test_safetensors_coefficients_serialization() {
131140

132141
// Need at least 3 samples for 2 features (n >= p + 1)
133142
// Use independent features
134-
let x = Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 1.0, 1.0, 1.0]).unwrap();
143+
let x = Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 1.0, 1.0, 1.0])
144+
.expect("Test data should be valid");
135145
let y = Vector::from_vec(vec![2.0, 3.0, 5.0]);
136146

137147
let mut model = LinearRegression::new();
138-
model.fit(&x, &y).unwrap();
148+
model.fit(&x, &y).expect("Test data should be valid");
139149

140150
let path = "test_coeffs.safetensors";
141-
model.save_safetensors(path).unwrap();
151+
model
152+
.save_safetensors(path)
153+
.expect("Test data should be valid");
142154

143-
let bytes = fs::read(path).unwrap();
155+
let bytes = fs::read(path).expect("Test data should be valid");
144156

145157
// Extract metadata to find data offsets
146-
let header_bytes: [u8; 8] = bytes[0..8].try_into().unwrap();
158+
let header_bytes: [u8; 8] = bytes[0..8].try_into().expect("Test data should be valid");
147159
let metadata_len = u64::from_le_bytes(header_bytes) as usize;
148160
let metadata_json = &bytes[8..8 + metadata_len];
149-
let metadata: serde_json::Value =
150-
serde_json::from_str(std::str::from_utf8(metadata_json).unwrap()).unwrap();
161+
let metadata: serde_json::Value = serde_json::from_str(
162+
std::str::from_utf8(metadata_json).expect("Test data should be valid"),
163+
)
164+
.expect("Test data should be valid");
151165

152166
// Get coefficients data offsets
153-
let offsets = metadata["coefficients"]["data_offsets"].as_array().unwrap();
154-
let start = offsets[0].as_u64().unwrap() as usize + 8 + metadata_len;
155-
let end = offsets[1].as_u64().unwrap() as usize + 8 + metadata_len;
167+
let offsets = metadata["coefficients"]["data_offsets"]
168+
.as_array()
169+
.expect("Test data should be valid");
170+
let start = offsets[0].as_u64().expect("Test data should be valid") as usize + 8 + metadata_len;
171+
let end = offsets[1].as_u64().expect("Test data should be valid") as usize + 8 + metadata_len;
156172

157173
// Read coefficient bytes
158174
let coeff_bytes = &bytes[start..end];
@@ -167,7 +183,9 @@ fn test_safetensors_coefficients_serialization() {
167183
// Verify we can parse F32 values
168184
let n_coeffs = coeff_bytes.len() / 4;
169185
for i in 0..n_coeffs {
170-
let f32_bytes: [u8; 4] = coeff_bytes[i * 4..(i + 1) * 4].try_into().unwrap();
186+
let f32_bytes: [u8; 4] = coeff_bytes[i * 4..(i + 1) * 4]
187+
.try_into()
188+
.expect("Test data should be valid");
171189
let _value = f32::from_le_bytes(f32_bytes); // Should not panic
172190
}
173191

@@ -188,23 +206,27 @@ fn test_safetensors_roundtrip() {
188206
1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
189207
],
190208
)
191-
.unwrap();
209+
.expect("Test data should be valid");
192210
let y = Vector::from_vec(vec![2.0, 3.0, 4.0, 5.0, 6.0]);
193211

194212
// Train original model
195213
let mut model_original = LinearRegression::new();
196-
model_original.fit(&x, &y).unwrap();
214+
model_original
215+
.fit(&x, &y)
216+
.expect("Test data should be valid");
197217

198218
// Get original coefficients and intercept
199219
let original_coeffs = model_original.coefficients();
200220
let original_intercept = model_original.intercept();
201221

202222
// Save to SafeTensors
203223
let path = "test_roundtrip.safetensors";
204-
model_original.save_safetensors(path).unwrap();
224+
model_original
225+
.save_safetensors(path)
226+
.expect("Test data should be valid");
205227

206228
// Load from SafeTensors
207-
let model_loaded = LinearRegression::load_safetensors(path).unwrap();
229+
let model_loaded = LinearRegression::load_safetensors(path).expect("Test data should be valid");
208230

209231
// Verify coefficients match (within floating-point tolerance)
210232
let loaded_coeffs = model_loaded.coefficients();
@@ -269,7 +291,7 @@ fn test_safetensors_corrupted_header_error() {
269291

270292
// Create file with invalid header (less than 8 bytes)
271293
let path = "test_corrupted.safetensors";
272-
fs::write(path, [1, 2, 3]).unwrap();
294+
fs::write(path, [1, 2, 3]).expect("Test data should be valid");
273295

274296
let result = LinearRegression::load_safetensors(path);
275297
assert!(

0 commit comments

Comments
 (0)