This document describes the testing strategy and how to run tests for BitCheck.
The test project is located at src/BitCheck.Tests/ and uses MSTest as the testing framework.
ApplicationTests/- Application-level integration testsAddOperationTests.cs- Tests for add operation functionalityApplicationTestBase.cs- Base class providing test helpers and setupCheckOperationTests.cs- Tests for check operation functionalityDeleteOperationTests.cs- Tests for delete operation functionalityExitCodeTests.cs- Tests for exit code behavior (success/error scenarios)InfoModeTests.cs- Tests for info mode functionalityListModeTests.cs- Tests for list mode functionalityRecursiveAndDatabaseModeTests.cs- Tests for recursive and database mode optionsSingleFileModeTests.cs- Tests for single file mode operationsUpdateOperationTests.cs- Tests for update operation functionalityVerboseOptionTests.cs- Tests for verbose output option
DatabaseServiceTests.cs- Tests for database operations (CRUD, persistence, caching)FileAccessTests.cs- Tests for file access validation and error handlingFileEntryTests.cs- Tests for theFileEntrydata modelFileSystemUtilitiesTests.cs- Tests for file system utility functionsHashUtilityTests.cs- Tests for XXHash64 file hashing functionalityHiddenFileFilterTests.cs- Tests for hidden file and directory detection on all platformsMissingFileTests.cs- Tests for database operations and missing file handling
- Open the solution in Visual Studio
- Go to Test → Run All Tests
- View results in the Test Explorer
Run all tests:
dotnet test src/BitCheck.slnRun tests with detailed output:
dotnet test src/BitCheck.sln --verbosity normalRun tests with code coverage:
dotnet test src/BitCheck.sln --collect:"XPlat Code Coverage"Run specific test class:
dotnet test src/BitCheck.sln --filter "FullyQualifiedName~DatabaseServiceTests"Run exit code tests:
dotnet test src/BitCheck.sln --filter "FullyQualifiedName~ExitCodeTests"Run specific test method:
dotnet test src/BitCheck.sln --filter "FullyQualifiedName~DatabaseService_InsertFileEntry_AddsNewEntry"- Exit Code Tests (22 tests)
- Successful operations return exit code 0
- Validation errors return exit code 1
- Check with mismatches returns exit code 1
- Check with missing files returns exit code 1
- Update that fixes mismatches returns exit code 0
- Update that removes missing files returns exit code 0
- Invalid operation combinations return exit code 1
- List mode returns exit code 0
- Single file mode exit codes
- Recursive mode exit codes
- Delete mode exit codes
- Info mode exit codes
- Timestamp mode exit codes
- Application Logic
- Recursive vs non-recursive directory processing
- Add/update/check operations
- Verbose and quiet output modes
- Single database vs per-directory databases
- Missing File Handling
- Missing files with check-only retain entries
- Missing files with update remove entries
- Timestamp Operations
- Creation time refresh with timestamps flag
- Single File Mode
- Add single file to database
- Check single file for corruption
- Detect mismatch in single file
- Update single file hash
- Delete file record from database
- Delete non-existent file handling
- Single file with single-db mode
- File not found error handling
- Timestamps tracking in single file mode
- Delete without file validation
- Delete with other operations validation
- Recursive with file validation
- Info and List Modes
- Info mode shows tracked file details
- Info mode shows not tracked for new files
- Info mode requires file option
- Info mode cannot be combined with other operations
- List mode shows tracked files
- List mode shows missing files
- List mode cannot be used with file
- List mode cannot be combined with other operations
- CRUD Operations
- Insert new entries
- Get existing entries
- Update entries
- Delete entries
- Validation
- Duplicate entry prevention
- Empty filename validation
- Non-existent entry handling
- Persistence
- Flush to disk
- Dispose behavior
- Cache invalidation
- Edge Cases
- Corrupted file handling
- Multiple operations
- File reload after external modification
- Basic Access
- Regular files can be read
- Empty files can be read
- Non-existent files detected
- File States
- Read-only files can be read (Windows)
- Locked files handled gracefully
- Large files (10MB+) can be read
- File Types
- Binary files can be read
- Files with special characters in names
- Files with Unicode content
- Advanced Scenarios
- Multiple files with different states
- Files in nested directories
- Long path handling
- Multiple concurrent readers (shared read)
- Default constructor initialization
- Property setters and getters
- Independent timestamp updates
- Empty string handling
- File Filtering
- Database and hidden file exclusion
- Hidden directory exclusion
- File Access Validation
- Missing file detection
- Zero-length file allowance
- Hash Computation
- Null return for missing files
- Consistency
- Same content produces same hash
- Different content produces different hash
- Empty file handling
- Formats
- Valid hex string output
- Correct hash length (16 characters)
- File Types
- Text files
- Binary files
- Large files (1MB+)
- Error Handling
- Non-existent file exception
- Sensitivity
- Single byte change detection
Hidden File Filter Tests (10 tests)
- Platform Detection
- Dot files are hidden on all platforms
- Dot directories are hidden on all platforms
- Windows Hidden attribute detection
- Database File
- Database file exclusion (.bitcheck.db)
- Regular Files
- Regular files are not hidden
- Regular directories are not hidden
- Multiple Files
- Multiple hidden files detection
- Mixed hidden and regular files
- Nested hidden directories
- Edge Cases
- Empty filename handling
- Database Enumeration
- Empty database handling
- All entries retrieval
- State after deletion operations
- Data Integrity
- Returned collections are copies
- Persistence after flush operations
- Delete Operations
- File removal from database
- Non-existent file handling
- Persistence of deletions
- Complex Operations
- Multiple add/delete sequences
- Case-insensitive filename handling
Each test is isolated and independent:
- Uses unique temporary files (
Guid.NewGuid()) - Cleans up resources in
[TestCleanup] - No shared state between tests
Tests follow the pattern: MethodName_Scenario_ExpectedBehavior
Examples:
DatabaseService_InsertFileEntry_AddsNewEntryXXHash64_SameContent_ProducesSameHashFileEntry_DefaultConstructor_CreatesEmptyEntry
[TestMethod]
public void MethodName_Scenario_ExpectedBehavior()
{
// Arrange - Set up test data and preconditions
var entry = new FileEntry { FileName = "test.txt" };
// Act - Execute the method being tested
var result = db.InsertFileEntry(entry);
// Assert - Verify the expected outcome
Assert.IsNotNull(result);
Assert.AreEqual("test.txt", result.FileName);
}Tests are automatically run in GitHub Actions on:
- Every push to main branch
- Every pull request
- Before creating releases
See .github/workflows/release.yml for CI configuration.
When adding new functionality:
-
Create test file in
src/BitCheck.Tests/ -
Follow naming convention:
{ClassName}Tests.cs -
Add test class:
[TestClass] public class NewFeatureTests { [TestInitialize] public void Setup() { /* Setup code */ } [TestCleanup] public void Cleanup() { /* Cleanup code */ } [TestMethod] public void NewFeature_Scenario_ExpectedBehavior() { // Test implementation } }
-
Run tests to verify they pass
-
Update this document if adding new test categories
- Set breakpoint in test method
- Right-click test → Debug Test
- Step through code as normal
# Run with detailed diagnostic output
dotnet test src/BitCheck.sln --logger "console;verbosity=detailed"Tests use temporary files in the system temp directory:
- Created with
Path.GetTempPath()+ unique GUID - Automatically cleaned up in
[TestCleanup] - No test artifacts left behind
BitCheck returns proper exit codes following CLI conventions:
- Exit code 0: Success (no errors or all issues resolved)
- Exit code 1: Errors (validation failures, unresolved mismatches, missing files, exceptions)
The ExitCodeTests suite validates:
- Successful operations return 0
- Validation errors (invalid arguments) return 1
- Integrity check failures return 1
- Update operations that fix all issues return 0
- All operation modes (add, check, update, delete, info, list) return correct codes
The ApplicationTestBase class provides two helper methods:
RunApp()- Runs the application without capturing exit code (for existing tests)RunAppWithExitCode()- Runs the application and returns the exit code (for exit code tests)
- Tests do not cover the CLI argument parsing (System.CommandLine)
- Integration tests for full end-to-end scenarios are not included
- Performance benchmarks are not automated
- Add integration tests for complete workflows
- Add performance benchmarks
- Add CLI argument parsing tests
- Increase code coverage to 90%+
- Add mutation testing
- Add property-based testing for edge cases
- Ensure .NET 10.0 SDK is installed
- Restore packages:
dotnet restore src/BitCheck.sln - Clean and rebuild:
dotnet clean && dotnet build
- Tests may fail if temp directory is full or inaccessible
- Check permissions on temp directory
- Ensure no antivirus is blocking file operations
- All tests should be deterministic and isolated
- If a test fails intermittently, check for:
- Timing issues
- File system race conditions
- Improper cleanup
When contributing tests:
- Ensure all tests pass locally
- Follow existing naming conventions
- Add appropriate assertions
- Clean up resources properly
- Document complex test scenarios