Fix issue 378 in AiDotNet repository - #450
Conversation
|
Warning Rate limit exceeded@ooples has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 23 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (10)
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Summary by CodeRabbitTests
Bug Fixes
Refactor
Documentation
✏️ Tip: You can customize this high-level summary in your review settings. WalkthroughAdded six new comprehensive unit test suites for helper utilities; refactored layer creation in DeserializationHelper and adjusted Tensor indexing in ConversionsHelper; one minor formatting change in CMAESOptimizer XML/doc and code whitespace. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull Request Overview
This PR adds comprehensive unit test coverage for five helper classes in the AiDotNet library: TextProcessingHelper, SerializationHelper, ParallelProcessingHelper, EnumHelper, DeserializationHelper, and ConversionsHelper. The tests cover edge cases, null handling, and various input scenarios to ensure robust behavior of these helper utilities.
Key changes:
- Added 441 lines of tests for TextProcessingHelper covering sentence splitting and tokenization
- Added 632 lines of tests for SerializationHelper covering binary serialization of various data structures
- Added 427 lines of tests for ParallelProcessingHelper covering concurrent task execution
- Added 309 lines of tests for EnumHelper covering enum value retrieval
- Added 378 lines of tests for DeserializationHelper covering layer deserialization
- Added 458 lines of tests for ConversionsHelper covering type conversions between tensors, matrices, and vectors
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| TextProcessingHelperTests.cs | Tests for text splitting and tokenization functions |
| SerializationHelperTests.cs | Tests for binary serialization of trees, matrices, vectors, and tensors |
| ParallelProcessingHelperTests.cs | Tests for parallel task processing with concurrency controls |
| EnumHelperTests.cs | Tests for enum value retrieval with filtering |
| DeserializationHelperTests.cs | Tests for neural network layer deserialization |
| ConversionsHelperTests.cs | Tests for conversions between different data structure types |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (3)
tests/AiDotNet.Tests/UnitTests/Helpers/TextProcessingHelperTests.cs (1)
396-408: Test name contradicts the assertion.The test is named
SplitsOnHyphenbut asserts that"state-of-the-art"is preserved as a single token. Either rename the test toPreservesHyphenatedWordsor update the assertion to match the actual behavior of theTokenizemethod.tests/AiDotNet.Tests/UnitTests/Helpers/EnumHelperTests.cs (1)
30-40: Test lacks meaningful assertions.The test acknowledges a potential bug in the implementation but provides no assertion to verify expected behavior. Either add a specific assertion documenting the expected behavior, or skip the test with a reason like
[Fact(Skip = "Known bug: ...")].tests/AiDotNet.Tests/UnitTests/Helpers/ConversionsHelperTests.cs (1)
287-289: Copilot’s integer-overflow warning is benign here; adjust only if analyzers complain.The assignments:
- Line 289:
matrix[i, j] = i * matrix.Columns + j;- Line 447:
matrix[i, j] = i * 4 + j;use only very small loop bounds in these tests (
2x3and2x4), so there is no realistic risk ofintoverflow at runtime.If your static analysis tooling keeps flagging this, you can optionally silence it by widening before multiplication, e.g.:
- matrix[i, j] = i * matrix.Columns + j; + matrix[i, j] = (double)((long)i * matrix.Columns + j);and similarly for the
i * 4 + jcase. Functionally, though, the current code is safe for the test dimensions you’re using.Also applies to: 444-447
🧹 Nitpick comments (9)
tests/AiDotNet.Tests/UnitTests/Helpers/EnumHelperTests.cs (2)
26-28: Unused test enum.
EmptyEnumis defined but never used in any test. Consider removing it or adding a test case that validates behavior with an empty enum.
64-102: Consider strengthening assertions in these tests.Several tests (e.g.,
GetEnumValues_WithPoolingType_ReturnsValues,GetEnumValues_WithNullIgnoreName_WorksCorrectly) only assertNotNullwithout verifying the returned values. Adding assertions likeAssert.ContainsorAssert.Equalfor expected count would improve test effectiveness.tests/AiDotNet.Tests/UnitTests/Helpers/ParallelProcessingHelperTests.cs (1)
300-321: Timing assertion may be flaky in slow CI environments.The assertion
duration.TotalMilliseconds < 1000is reasonable but could fail on heavily loaded CI runners. Consider usingStopwatchfor more accurate timing and a more generous threshold, or simply asserting that results are returned correctly without the timing constraint.tests/AiDotNet.Tests/UnitTests/Helpers/ConversionsHelperTests.cs (6)
10-61: ConvertToMatrix tests look correct; consider asserting contents, not just shape.The three
ConvertToMatrix_*tests correctly exercise matrix passthrough, 2D tensor conversion, and higher‑rank tensor reshaping as implemented inConversionsHelper.ConvertToMatrix. As written they verify the key behaviors (identity for matrices and expected 2D shape for tensors).If you want these tests to guard more strongly against regressions, you could also assert on a couple of representative element values (e.g., top‑left, last element) to ensure the reshaping isn’t just producing the right shape but also preserves ordering. This is optional given current coverage.
63-94: ConvertToVector tests are aligned with the helper behavior; optional value assertions.The vector tests correctly cover:
- Vector passthrough (
Assert.Same),- Tensor flattening with the right total length.
Similar to the matrix tests, you might optionally assert one or two element values from the flattened tensor to lock in the ordering guarantee, but behavior-wise these tests already match the documented
ConvertToVectorsemantics.
185-224: ConvertObjectToVector tests cover main paths; consider identity assertion and invalid-type case.The null,
Vector<T>, andTensor<T>cases are exercised correctly and match the helper’s contract.Two optional improvements if you want even stronger coverage:
- For the vector case, assert
Assert.Same(vector, result)(after casting) to pin down that it’s not copying.- Add a negative test (e.g., passing an
int[]orMatrix<T>) that assertsInvalidOperationException, to guard the error path.
226-252: ConvertFitFunction test validates matrix-input path; tensor-input path is untested.This test correctly verifies that:
- A
Func<Matrix<double>, Vector<double>>passes through the matrix unchanged asTInput,- The returned function from
ConvertFitFunctionproduces the expectedVector<double>.Given the implementation also supports
TInputasTensor<T>(usingTensor<T>.FromRowMatrix), you might consider adding a companion test withFunc<Tensor<double>, Tensor<double>>orFunc<Tensor<double>, Vector<double>>to exercise that branch and catch regressions in the matrix→tensor adaptation logic.
254-337: TensorToMatrix / MatrixToTensor / VectorToTensor tests cover shapes well; minor opportunity to assert data.These tests collectively do a good job validating:
- Successful conversions with matching sizes,
- Proper
ArgumentExceptionbehavior for mismatched shapes,- Rank and shape metadata for valid conversions.
If you want to tighten them further, you could:
- In at least one of these conversions (e.g.,
MatrixToTensor_WithValidShape_ConvertsCorrectly), assert that a specific element value is preserved at the expected index after conversion.
This would make it harder for an internal reshaping bug to slip through while still keeping tests lightweight.
423-456: 3D shape tests validate rank and size; consider asserting 3D shape inMatrixToTensor_With3DShape.The 3D tests (
VectorToTensor_With3DShape_ConvertsCorrectlyandMatrixToTensor_With3DShape_ConvertsCorrectly) correctly exercise higher‑dimensional shapes and confirm:
- Rank = 3,
- Proper shape for the vector case,
- Correct total length for the matrix case.
For symmetry and a bit more safety, you might also assert
result.Shape[0..2]inMatrixToTensor_With3DShape_ConvertsCorrectly, similar to the vector test, to ensure the resulting tensor’s logical shape is exactly{ 2, 2, 2 }and not just any rank‑3 tensor of length 8.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
tests/AiDotNet.Tests/UnitTests/Helpers/ConversionsHelperTests.cs(1 hunks)tests/AiDotNet.Tests/UnitTests/Helpers/DeserializationHelperTests.cs(1 hunks)tests/AiDotNet.Tests/UnitTests/Helpers/EnumHelperTests.cs(1 hunks)tests/AiDotNet.Tests/UnitTests/Helpers/ParallelProcessingHelperTests.cs(1 hunks)tests/AiDotNet.Tests/UnitTests/Helpers/SerializationHelperTests.cs(1 hunks)tests/AiDotNet.Tests/UnitTests/Helpers/TextProcessingHelperTests.cs(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
tests/AiDotNet.Tests/UnitTests/Helpers/SerializationHelperTests.cs (3)
src/Reasoning/Models/ThoughtNode.cs (1)
IsLeaf(256-256)src/Extensions/SerializationExtensions.cs (2)
WriteValue(90-109)ReadValue(133-144)src/NeuralNetworks/EchoStateNetwork.cs (2)
SerializeMatrix(1577-1589)SerializeVector(1596-1604)
tests/AiDotNet.Tests/UnitTests/Helpers/ConversionsHelperTests.cs (1)
src/Helpers/ConversionsHelper.cs (2)
ConversionsHelper(14-479)Func(208-235)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Analyze (csharp)
- GitHub Check: Build All Frameworks
- GitHub Check: Build
- GitHub Check: Codacy Security Scan
🔇 Additional comments (9)
tests/AiDotNet.Tests/UnitTests/Helpers/TextProcessingHelperTests.cs (1)
1-10: Well-structured test class with comprehensive coverage.Good use of the AAA (Arrange-Act-Assert) pattern and clear test naming conventions throughout.
tests/AiDotNet.Tests/UnitTests/Helpers/DeserializationHelperTests.cs (2)
1-11: Good test coverage for deserialization helper.The test class comprehensively covers layer creation across multiple layer types and generic type parameters.
175-223: DeserializeInterface tests are well-designed.Good coverage of null/empty input handling, invalid type name exceptions, and valid type instantiation.
tests/AiDotNet.Tests/UnitTests/Helpers/SerializationHelperTests.cs (2)
1-10: Comprehensive serialization test coverage.Good coverage of round-trip serialization for matrices, vectors, tensors, and decision tree nodes across multiple numeric types.
566-630: No action required. BothSerializationHelper<T>.WriteValueandSerializationHelper<T>.ReadValueexplicitly supportdecimal(lines 109–112, 179–182) andlong(lines 113–116, 183–186) types. The tests are correct.Likely an incorrect or invalid review comment.
tests/AiDotNet.Tests/UnitTests/Helpers/ParallelProcessingHelperTests.cs (2)
1-11: Comprehensive parallel processing test coverage.Good coverage of both
Func<T>andTask<T>overloads with various parallelism configurations.
406-425: Test validates result ordering, not execution ordering.Note that
Task.Runstarts tasks immediately, so all three tasks begin executing concurrently beforeProcessTasksInParallelis called. The test correctly verifies that results are returned in input order (by task index), which is the meaningful guarantee. The test is valid but the nameMaintainsOrdercould be clarified toMaintainsResultOrder.tests/AiDotNet.Tests/UnitTests/Helpers/ConversionsHelperTests.cs (2)
96-183: ConvertToScalar tests are thorough and match documented edge cases.These tests nicely cover:
- Scalar passthrough,
- First-element extraction from vector, matrix, and tensor,
- All three empty-source cases throwing
InvalidOperationException.This aligns well with the
ConvertToScalarcontract summarized inConversionsHelper.cs, and I don’t see any gaps or logic issues here.
339-421: ConvertToTensor & float-variant tests are correct and provide good generic coverage.The tests for
ConvertToTensorverify:
- Matrix inputs yield rank‑2 tensors,
- Vector inputs yield rank‑1 tensors,
- Tensor inputs are returned by reference (
Assert.Same).The float-based
ConvertToMatrix/Vector/Scalartests also give nice spot checks that the generic conversions behave as expected for non‑double numeric types. All of these look consistent with the helper’s intended behavior.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (4)
tests/AiDotNet.Tests/UnitTests/Helpers/ConversionsHelperTests.cs (3)
289-291: Integer overflow unlikely for test matrices, but cast order could be improved.For a 2x3 matrix,
i * matrix.Columns + jyields max value 5, so no overflow risk here. However, for larger matrices in production code, the operation order matters. This was flagged in a past review.
447-449: Same overflow pattern as above - acceptable for small test matrices.For a 2x4 matrix,
i * 4 + jyields max value 7. No practical overflow concern for this test data.
166-172: Misleading test name - tests Matrix constructor, notConvertToScalar.This test verifies that
Matrix<double>(0, 0)throwsArgumentException, which tests the constructor behavior rather thanConvertToScalarhandling of empty matrices. Either rename or restructure to actually test the conversion method.[Fact] - public void ConvertToScalar_WithEmptyMatrix_ThrowsArgumentException() + public void MatrixConstructor_WithZeroDimensions_ThrowsArgumentException() { - // Arrange & Act & Assert - // Matrix constructor throws ArgumentException for 0 rows/cols + // Arrange, Act & Assert + // Documenting that Matrix doesn't allow 0-dimension construction, + // so ConvertToScalar empty matrix path cannot be reached this way Assert.Throws<ArgumentException>(() => new Matrix<double>(0, 0)); }tests/AiDotNet.Tests/UnitTests/Helpers/EnumHelperTests.cs (1)
30-40: Incomplete test with no meaningful assertion.This test acknowledges a potential bug but provides no assertion beyond
Assert.NotNull(result). Either add a concrete assertion documenting the expected behavior, or skip the test with a clear reason.[Fact] - public void GetEnumValues_WithNoIgnore_ReturnsAllValues() + [Fact(Skip = "Known implementation quirk: method requires non-null ignoreName to populate list")] + public void GetEnumValues_WithNoIgnore_ReturnsAllValues() { // Act var result = EnumHelper.GetEnumValues<TestEnum>(); // Assert Assert.NotNull(result); - // The method has a bug - it only adds values when ignoreName is not null/empty - // So we expect the result to depend on the actual implementation + Assert.Equal(5, result.Count); + Assert.Contains(TestEnum.Value1, result); + Assert.Contains(TestEnum.Value2, result); + Assert.Contains(TestEnum.Value3, result); + Assert.Contains(TestEnum.Value4, result); + Assert.Contains(TestEnum.Value5, result); }
🧹 Nitpick comments (6)
tests/AiDotNet.Tests/UnitTests/Helpers/SerializationHelperTests.cs (2)
224-246: Consider asserting the actual serialized values inSerializeMatrix_WithSmallMatrix_SerializesCorrectly.The test only verifies the row and column counts were written but doesn't verify the actual matrix values were serialized. Consider adding assertions for the element values to ensure complete serialization correctness.
// Assert ms.Position = 0; using var reader = new BinaryReader(ms); Assert.Equal(2, reader.ReadInt32()); // rows Assert.Equal(3, reader.ReadInt32()); // columns + // Verify first element + Assert.Equal(1.0, reader.ReadDouble()); }
336-351: Similar incomplete assertion inSerializeVector_WithSmallVector_SerializesCorrectly.This test only verifies the length header but not the actual vector values. The round-trip test covers this, but for a serialization-specific test, asserting values would be more thorough.
tests/AiDotNet.Tests/UnitTests/Helpers/EnumHelperTests.cs (2)
26-28: Consider adding a test forEmptyEnumbehavior.
EmptyEnumis defined but not tested. Add a test to verify behavior when callingGetEnumValues<EmptyEnum>()to document expected handling of enums with no values.[Fact] public void GetEnumValues_WithEmptyEnum_ReturnsEmptyList() { // Act var result = EnumHelper.GetEnumValues<EmptyEnum>("NonExistent"); // Assert Assert.NotNull(result); Assert.Empty(result); }
193-201: Test verifies count equality but not content consistency.
GetEnumValues_MultipleCallsWithSameEnum_ReturnsConsistentResultsonly checks that counts match. Consider usingAssert.Equal(result1, result2)orSequenceEqualto verify the actual content is consistent.// Assert - Assert.Equal(result1.Count, result2.Count); + Assert.Equal(result1.Count, result2.Count); + Assert.True(result1.SequenceEqual(result2));tests/AiDotNet.Tests/UnitTests/Helpers/ConversionsHelperTests.cs (1)
254-271:TensorToMatrix_WithMatchingDimensions_ConvertsCorrectlycould verify values.The test creates a tensor with sequential values but only asserts dimensions. Consider verifying at least one value to ensure data integrity during conversion.
// Assert Assert.NotNull(result); Assert.Equal(2, result.Rows); Assert.Equal(3, result.Columns); + Assert.Equal(0.0, result[0, 0]); + Assert.Equal(5.0, result[1, 2]); }src/Helpers/DeserializationHelper.cs (1)
125-151: Consider handling Softmax edge case with a clearer error.Per
ActivationFunctionFactory, passingActivationFunction.Softmaxwill throwNotSupportedException("Softmax is not applicable to single values..."). While this is correct behavior (ActivationLayer expectsIActivationFunction<T>, notIVectorActivationFunction<T>), the error message may be confusing during deserialization.Consider catching and rethrowing with context:
try { object? activationFunction = createMethod.Invoke(null, [activationFunctionEnum]); // ... } catch (TargetInvocationException ex) when (ex.InnerException is NotSupportedException) { throw new InvalidOperationException( $"ActivationLayer does not support {activationFunctionEnum}. Use a vector-based layer for Softmax.", ex.InnerException); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/AiDotNet.Tensors/LinearAlgebra/VectorBase.cs(1 hunks)src/Helpers/ConversionsHelper.cs(1 hunks)src/Helpers/DeserializationHelper.cs(1 hunks)src/Optimizers/CMAESOptimizer.cs(0 hunks)tests/AiDotNet.Tests/UnitTests/Helpers/ConversionsHelperTests.cs(1 hunks)tests/AiDotNet.Tests/UnitTests/Helpers/EnumHelperTests.cs(1 hunks)tests/AiDotNet.Tests/UnitTests/Helpers/SerializationHelperTests.cs(1 hunks)
💤 Files with no reviewable changes (1)
- src/Optimizers/CMAESOptimizer.cs
✅ Files skipped from review due to trivial changes (1)
- src/AiDotNet.Tensors/LinearAlgebra/VectorBase.cs
🧰 Additional context used
🧬 Code graph analysis (4)
src/Helpers/DeserializationHelper.cs (4)
src/AiDotNet.Tensors/LinearAlgebra/VectorBase.cs (4)
T(136-139)T(328-332)T(345-348)T(360-366)src/Helpers/ConversionsHelper.cs (1)
T(119-153)src/NeuralNetworks/Layers/LayerBase.cs (1)
ActivationFunction(849-859)src/Factories/ActivationFunctionFactory.cs (1)
ActivationFunctionFactory(19-106)
tests/AiDotNet.Tests/UnitTests/Helpers/EnumHelperTests.cs (1)
src/NeuralNetworks/Layers/LayerBase.cs (1)
ActivationFunction(849-859)
tests/AiDotNet.Tests/UnitTests/Helpers/SerializationHelperTests.cs (2)
src/Extensions/SerializationExtensions.cs (2)
WriteValue(90-109)ReadValue(133-144)src/NeuralNetworks/EchoStateNetwork.cs (2)
SerializeMatrix(1577-1589)SerializeVector(1596-1604)
tests/AiDotNet.Tests/UnitTests/Helpers/ConversionsHelperTests.cs (1)
src/Helpers/ConversionsHelper.cs (9)
Matrix(31-66)Matrix(255-264)ConversionsHelper(14-481)Tensor(280-296)Tensor(313-329)Tensor(345-361)Vector(83-102)Vector(168-192)Func(210-237)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Test (tests/AiDotNet.Tests/AiDotNetTests.csproj)
- GitHub Check: Codacy Security Scan
- GitHub Check: Analyze (csharp)
- GitHub Check: Build All Frameworks
🔇 Additional comments (7)
tests/AiDotNet.Tests/UnitTests/Helpers/SerializationHelperTests.cs (2)
1-10: Well-structured test class with comprehensive coverage.The test file follows good xUnit conventions with clear AAA (Arrange-Act-Assert) patterns and covers serialization/deserialization scenarios for nodes, matrices, vectors, and tensors across multiple numeric types.
564-628: This review comment is incorrect.SerializationHelper<T>fully supports bothdecimal(lines 109-112 and 179-182) andlong(lines 113-116 and 183-186) types in itsWriteValueandReadValuemethods. The tests will execute correctly.Likely an incorrect or invalid review comment.
src/Helpers/ConversionsHelper.cs (1)
147-149: Correct fix for multi-dimensional tensor scalar extraction.The change properly handles tensors of any rank by creating a zero-initialized index array. Previously using
tensor[0]would fail or behave incorrectly for tensors with rank > 1.tests/AiDotNet.Tests/UnitTests/Helpers/ConversionsHelperTests.cs (1)
1-9: Comprehensive test coverage forConversionsHelper.Good test suite covering matrix/tensor/vector conversions, scalar extraction, edge cases for empty collections, and type-specific tests with both
doubleandfloat.src/Helpers/DeserializationHelper.cs (3)
86-105: Approve with note on array access safety.The length checks on lines 93-96 provide some defensive handling for varying input shape formats, but these still rely on at least one element existing. This is addressed by the array validation suggested above.
The constructor resolution and parameter extraction logic is well-structured.
106-124: LGTM!The PoolingLayer creation logic correctly extracts parameters from
additionalParamswith sensible defaults and properly resolves the constructor.
152-162: LGTM!The default fallback provides reasonable extensibility for layer types not explicitly handled, and the null check before cast is appropriate.
a6db6fa to
542e027
Compare
Add 158 unit tests for six utility helper classes covering serialization, deserialization, type conversions, parallel processing, text processing, and enum handling. Fix bug in enumhelper where getenumvalues returned empty list when no ignore name was specified. Test Coverage: - SerializationHelper: 32 tests for matrix/vector/tensor serialization - DeserializationHelper: 21 tests for layer and interface deserialization - ConversionsHelper: 30 tests for type conversions with edge cases - ParallelProcessingHelper: 21 tests for concurrent task execution - TextProcessingHelper: 29 tests for sentence splitting and tokenization - EnumHelper: 25 tests for enum value retrieval with filtering Includes validation fixes for input/output shapes in deserialization and generic type checks for layer instantiation. Resolves #378 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
511dc5e to
c350e2f
Compare
Add 158 unit tests for six utility helper classes covering serialization, deserialization, type conversions, parallel processing, text processing, and enum handling. Fix bug in enumhelper where getenumvalues returned empty list when no ignore name was specified. Test Coverage: - SerializationHelper: 32 tests for matrix/vector/tensor serialization - DeserializationHelper: 21 tests for layer and interface deserialization - ConversionsHelper: 30 tests for type conversions with edge cases - ParallelProcessingHelper: 21 tests for concurrent task execution - TextProcessingHelper: 29 tests for sentence splitting and tokenization - EnumHelper: 25 tests for enum value retrieval with filtering Includes validation fixes for input/output shapes in deserialization and generic type checks for layer instantiation. Resolves #378 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Implemented comprehensive unit tests for six utility helper classes:
Total: 158 tests providing 75%+ coverage per helper
Resolves #378
User Story / Context
merge-dev2-to-masterSummary
Verification
Copilot Review Loop (Outcome-Based)
Record counts before/after your last push:
Files Modified
Notes