# Testing Guide for django-cronjob-utils

## Prerequisites

To run the full test suite with hooks support, you need to install the `django-package-hooks` dependency.

## Installation Methods

### Method 1: From Local Source (Recommended for Development)

If you have the `django-package-hooks` source code in an adjacent directory:

```bash
# Navigate to the project directory
cd django-cronjob-utils

# Install in user directory (no sudo required)
pip3 install --user -e ../django-package-hooks

# Or install in virtual environment
source venv/bin/activate
pip install -e ../django-package-hooks
```

### Method 2: From PyPI (When Published)

Once the package is published to PyPI:

```bash
pip install django-package-hooks>=1.0.0

# Or add to requirements.txt
echo "django-package-hooks>=1.0.0" >> requirements.txt
pip install -r requirements.txt
```

### Method 3: Install All Dependencies

Install the package with all development dependencies:

```bash
# From the project root
pip install -e .[test]
```

## Verify Installation

Check if `django-package-hooks` is installed:

```bash
python3 -c "import django_package_hooks; print('✓ Installed version:', django_package_hooks.__version__)"
```

Expected output:
```
✓ Installed version: 1.0.0
```

## Running Tests

### Run All Tests

```bash
# Set Django settings module
export DJANGO_SETTINGS_MODULE=tests.settings

# Run all tests
python3 manage.py test

# Run with verbose output
python3 manage.py test --verbosity=2
```

### Run Specific Test Modules

```bash
# Run only hook tests
python3 manage.py test tests.test_hooks

# Run only base functionality tests
python3 manage.py test tests.test_base

# Run only management command tests
python3 manage.py test tests.test_management_command
```

### Run Specific Test Classes

```bash
# Run a specific test class
python3 manage.py test tests.test_hooks.PreHookStandardTests

# Run a specific test method
python3 manage.py test tests.test_hooks.PreHookStandardTests.test_pre_hook_allows_execution
```

### Using the Test Runner Script

```bash
# Make the script executable
chmod +x tests/run_tests.sh

# Run all tests
./tests/run_tests.sh

# Run specific tests
./tests/run_tests.sh tests.test_hooks
```

## Test Coverage

The test suite includes **182 tests** covering:

### Core Functionality (157 tests)
- ✅ Task execution and lifecycle
- ✅ Database record creation and updates
- ✅ Lock management and duplicate prevention
- ✅ Retry mechanisms
- ✅ Notification systems (Email, Slack, Telegram)
- ✅ Management commands
- ✅ Error handling

### Hook Integration (25 tests)
- ✅ PRE hook execution (before lock acquisition)
- ✅ POST hook execution (after task completion)
- ✅ Hook rejection and validation
- ✅ Priority ordering
- ✅ Metadata sharing between hooks
- ✅ Edge cases and error handling
- ✅ Real-world integration patterns

## Understanding Hook Tests

When `django-package-hooks` is **installed**:
- All 182 tests run, including 25 hook integration tests
- Expected output: `Ran 182 tests in X.XXXs`

When `django-package-hooks` is **not installed**:
- Hook tests are automatically skipped
- Core functionality still works perfectly
- Expected output: `Ran 157 tests in X.XXXs (25 skipped)`

## Test Isolation

Each test is properly isolated with:
- Fresh database for each test run
- Automatic cleanup of hook registrations
- Independent task instances
- Clean metadata between tests

## Common Test Scenarios

### Testing Hook Integration

```python
from django_cronjob_utils import (
    CronTask,
    get_global_cronjob_hook_manager,
    clear_cronjob_hooks,
)
from django_package_hooks import HookType, HookRejectionError

# Clear any existing hooks
clear_cronjob_hooks()

# Register a PRE hook
def my_pre_hook(context):
    if not_ready():
        raise HookRejectionError(
            code="NOT_READY",
            message="System not ready"
        )

manager = get_global_cronjob_hook_manager()
manager.registry.register(
    name='cronjob.execute',
    hook_type=HookType.PRE,
    callback=my_pre_hook,
    operation='*',
    priority=100
)

# Run your task
task = MyTask()
result = task.run()
```

### Testing Without Hooks

```python
from django_cronjob_utils import CronTask

# Works perfectly even without django-package-hooks installed
class MyTask(CronTask):
    task_name = "my-task"
    
    def execute(self, execution_date):
        # Your task logic
        return {"status": "success"}

task = MyTask()
result = task.run()
```

## Troubleshooting

### ImportError: No module named 'django_package_hooks'

**Solution**: Install the package using one of the methods above.

```bash
pip3 install --user -e ../django-package-hooks
```

### Tests Fail Due to Hook Interference

**Solution**: Ensure `clear_cronjob_hooks()` is called in test setUp:

```python
from django_cronjob_utils import clear_cronjob_hooks

class MyTestCase(TestCase):
    def setUp(self):
        super().setUp()
        clear_cronjob_hooks()  # Clean hook registry
```

### Permission Denied When Installing

**Solution 1**: Install in user directory (no sudo needed):
```bash
pip3 install --user -e ../django-package-hooks
```

**Solution 2**: Use a virtual environment:
```bash
python3 -m venv venv
source venv/bin/activate
pip install -e ../django-package-hooks
```

### Database Errors During Tests

**Solution**: Django creates a test database automatically. Make sure your settings allow this:

```python
# tests/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': ':memory:',  # In-memory database for tests
    }
}
```

## Continuous Integration

Example GitHub Actions workflow:

```yaml
name: Run Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      
      - name: Install dependencies
        run: |
          pip install -e ../django-package-hooks
          pip install -e .[test]
      
      - name: Run tests
        run: |
          export DJANGO_SETTINGS_MODULE=tests.settings
          python manage.py test --verbosity=2
```

## Performance Notes

- Test execution time: ~1-2 seconds for all 182 tests
- Hook tests add minimal overhead (<0.1s)
- In-memory SQLite database for fast test execution
- Parallel test execution available with `--parallel` flag

```bash
# Run tests in parallel (4 processes)
python3 manage.py test --parallel=4
```

## Getting Help

If you encounter issues:

1. Check that `django-package-hooks` is installed: `pip list | grep django-package-hooks`
2. Verify Python version: `python3 --version` (requires Python 3.8+)
3. Check Django version: `python3 -c "import django; print(django.VERSION)"` (requires 3.2+)
4. Run tests with verbose output: `python3 manage.py test --verbosity=2`
5. Check the GitHub issues or documentation

## Additional Resources

- [Hook System Documentation](./hooks.md)
- [Usage Guide](./usage.md)
- [django-package-hooks README](../../django-package-hooks/README.md)
- [Example Hook Implementations](../examples/cronjob_hooks.py)
