KISS Repository Tests

A comprehensive testing framework for KISS Repository implementations. This package provides a standardized test suite and factory pattern that ensures all repository implementations meet the same behavioral contracts.

Overview

The KISS Repository Tests package provides:

  • ๐Ÿญ Factory Pattern: Standardized way to create and test repository implementations
  • ๐Ÿ“‹ Comprehensive Test Suite: 28+ tests covering CRUD, batch operations, queries, streaming, and ID management
  • ๐Ÿงน Automatic Cleanup: Built-in cleanup between tests to ensure test isolation
  • ๐Ÿ”ง Extensible Framework: Easy to add new test scenarios and implementations

Features

  • โœ… Basic CRUD Operations - Create, Read, Update, Delete functionality
  • โœ… Batch Operations - Bulk add, update, and delete operations
  • โœ… Query System - Complex querying with filters and conditions
  • โœ… Real-time Streaming - Live data updates and change notifications
  • โœ… ID Management - Auto-generation and validation of unique identifiers
  • โœ… Error Handling - Proper exception handling for edge cases
  • โœ… Test Isolation - Clean state between tests with automatic cleanup

Architecture

Factory Pattern

Each repository implementation provides a factory that implements the RepositoryFactory interface:

abstract class RepositoryFactory<T> {
  Future<Repository<T>> createRepository();
  Future<void> cleanup();
  void dispose();
}

Test Framework

The testing framework provides:

  • runRepositoryTests: Main test runner function that executes all test suites
  • Test Logic Modules: Separate modules for different aspects (CRUD, batch, query, streaming, ID management)
  • Shared Test Models: Common test data models used across all implementations

Getting Started

1. Add Dependency

Add kiss_repository_tests to your pubspec.yaml:

dev_dependencies:
  kiss_repository_tests:
    path: ../kiss_repository_tests  # or your path
  test: ^1.24.0

2. Create a Factory

Implement the RepositoryFactory interface for your repository:

import 'package:kiss_repository_tests/kiss_repository_tests.dart';

class MyRepositoryFactory implements RepositoryFactory<ProductModel> {
  Repository<ProductModel>? _repository;
  
  static Future<void> initialize() async {
    // Setup your repository (database connections, etc.)
  }

  @override
  Future<Repository<ProductModel>> createRepository() async {
    _repository = MyRepository<ProductModel>(
      // your repository configuration
    );
    return _repository!;
  }

  @override
  Future<void> cleanup() async {
    // Clean up test data between tests
    final allItems = await _repository!.query();
    if (allItems.isNotEmpty) {
      final ids = allItems.map((item) => item.id).toList();
      await _repository!.deleteAll(ids);
    }
  }

  @override
  void dispose() {
    _repository?.dispose();
    _repository = null;
  }
}

3. Create Test File

Create your test file following the standard pattern:

import 'package:kiss_repository_tests/kiss_repository_tests.dart';

import 'factories/my_repository_factory.dart';

void main() {
  runRepositoryTests(
    implementationName: 'MyRepository',
    factoryProvider: () => MyRepositoryFactory(),
    cleanup: () {},
    // Optional: configure which test suites to run
    config: const TestSuiteConfig.all(), // Default - runs all tests
  );
}

4. Run Tests

dart test

Test Suite Configuration

The framework allows you to selectively run test suites based on what your repository implementation supports:

Predefined Configurations

// Run all test suites (default behavior)
config: const TestSuiteConfig.all()

// Run only basic CRUD operations
config: const TestSuiteConfig.basicOnly()

// Run all tests except streaming (for repositories without real-time features)
config: const TestSuiteConfig.withoutStreaming()

// Run only CRUD and batch operations
config: const TestSuiteConfig.crudAndBatch()

Custom Configuration

config: const TestSuiteConfig(
  runCrudTests: true,      // Basic CRUD operations
  runBatchTests: true,     // Bulk operations (addAll, updateAll, deleteAll)
  runIdTests: true,        // ID management and auto-generation
  runQueryTests: true,     // Query system testing
  runStreamingTests: false, // Real-time streaming (disable if not supported)
)

Common Use Cases

For repositories without streaming support:

void main() {
  runRepositoryTests(
    implementationName: 'MyRepository',
    factoryProvider: () => MyRepositoryFactory(),
    cleanup: () {},
    config: const TestSuiteConfig.withoutStreaming(),
  );
}

For basic implementations:

void main() {
  runRepositoryTests(
    implementationName: 'MyRepository',
    factoryProvider: () => MyRepositoryFactory(),
    cleanup: () {},
    config: const TestSuiteConfig.basicOnly(),
  );
}

Usage

This testing framework can be used with any repository implementation that follows the KISS Repository interface contract.

Contributing

When adding new test scenarios:

  1. Add the test logic to the appropriate module in lib/src/
  2. Update the runRepositoryTests function to include the new test
  3. Ensure all existing implementations still pass
  4. Document any new requirements for factory implementations

Integration

To integrate this testing framework with your repository implementation:

  1. Implement the RepositoryFactory interface
  2. Create your test files following the recommended structure
  3. Run the comprehensive test suite to validate your implementation

License

This project is licensed under the MIT License - see the LICENSE file for details.