# Testing Framework for emburden Package

This directory contains comprehensive tests for the emburden package, including unit tests, integration tests, and a local test runner.

## Running Tests

### Quick Local Test Run

From the package root directory:

```bash
Rscript tests/run-tests-locally.R
```

Or from R console:

```r
source("tests/run-tests-locally.R")
```

### Full R CMD Check

To run complete package checks (like GitHub Actions):

```bash
RUN_CMD_CHECK=true Rscript tests/run-tests-locally.R
```

### Run Specific Test Files

From R console:

```r
devtools::load_all()
testthat::test_file("tests/testthat/test-energy-metrics.R")
```

### Coverage Report

```r
covr::package_coverage()
covr::report()  # Opens HTML report in browser
```

## Test Organization

### Phase 1: Critical Tests (Implemented)

- **test-file-validation.R**: Data quality checks, edge cases, fixture generation
- **test-energy-metrics.R**: Core NER, energy burden, and related calculations

### Phase 2: High Priority (Planned)

- **test-data-loaders.R**: HTTP mocking, database tests, file loading
- **test-schema-normalization.R**: Vintage compatibility, bracket aggregation

### Phase 3: Medium Priority (Planned)

- **test-integration.R**: End-to-end workflows
- **test-formatting.R**: Output formatting functions

## Helper Files

- **helper-fixtures.R**: Test data generation and cleanup utilities
  - `create_sample_lead_data()`: Generate realistic test data
  - `create_corrupted_fpl_data()`: Test all-NA income_bracket bug
  - `create_test_database()`: SQLite database for testing
  - `cleanup_test_files()`: Remove temporary files

## Writing New Tests

### Template for New Test File

```r
# Phase X: Description
# Tests for specific functionality

test_that("descriptive test name", {
  # Arrange: Set up test data
  data <- create_sample_lead_data(n = 50)

  # Act: Perform the operation
  result <- some_function(data)

  # Assert: Check expectations
  expect_equal(result$value, expected_value)
  expect_true(some_condition)
})
```

### Best Practices

1. **Use fixtures**: Don't rely on external data - use `create_sample_lead_data()`
2. **Test edge cases**: Zero, negative, NA, Inf values
3. **Clean up**: Use `cleanup_test_files()` to remove temporary files
4. **Skip when appropriate**: Use `skip_if_offline()` for network tests
5. **Descriptive names**: Test names should describe what's being tested

## Coverage Goals

| Component | Target | Current |
|-----------|--------|---------|
| Data loaders | 95% | TBD |
| Energy metrics | 95% | TBD |
| Data processing | 90% | TBD |
| Validation functions | 100% | TBD |
| Overall package | 85% | TBD |

## Continuous Integration

Tests run automatically on:
- Pull requests targeting `main` branch
- Pushes to `main` branch
- Multiple OS/R version combinations (macOS, Windows, Ubuntu)

See `.github/workflows/R-CMD-check.yml` and `.github/workflows/test-coverage.yml` for details.

## Debugging Failed Tests

### View Detailed Output

```r
devtools::test(reporter = "check")  # More verbose than default
```

### Interactive Debugging

```r
devtools::load_all()
library(testthat)

# Set breakpoint in your test
test_that("my failing test", {
  browser()  # Execution will pause here
  # ... test code ...
})
```

### Check Test Data

```r
# Generate and inspect test data
data <- create_sample_lead_data(n = 10)
str(data)
summary(data)
```

## Test Data Fixtures

Test fixtures are generated on-the-fly using `helper-fixtures.R`. This ensures:

1. **No large data files in git**: Fixtures are created during test runs
2. **Reproducibility**: Seed values ensure consistent test data
3. **Flexibility**: Easy to modify fixture characteristics
4. **Speed**: Minimal data creation for fast tests

### Example Fixture Usage

```r
# Create standard test data
data <- create_sample_lead_data(n = 100, dataset = "ami", vintage = "2022")

# Create edge case data
edge_data <- create_edge_case_data()

# Create corrupted data (for testing validation)
corrupted <- create_corrupted_fpl_data(n = 50)
```

## Performance Benchmarks

Target test suite execution time:
- Unit tests: < 30 seconds
- Integration tests: < 60 seconds
- Full suite with coverage: < 2 minutes

## Adding Tests for New Features

When adding new features:

1. Write tests first (TDD approach preferred)
2. Ensure new code has >85% coverage
3. Add integration tests for major features
4. Update this README with new test files

## Troubleshooting

### "Package not installed" Error

```bash
# Install in development mode
Rscript -e "devtools::install()"
```

### Missing Test Dependencies

```r
# Install testing packages
install.packages(c("testthat", "covr", "withr", "mockery"))
```

### Tests Pass Locally but Fail in CI

- Check R version differences
- Verify all dependencies in DESCRIPTION
- Check for hardcoded paths
- Ensure fixtures are platform-independent

## Additional Resources

- [testthat documentation](https://testthat.r-lib.org/)
- [covr package](https://covr.r-lib.org/)
- [R Packages book - Testing chapter](https://r-pkgs.org/testing-basics.html)
- [Testing spec document](.dev/testing-spec.md)
