Skip to content

🧪 08_PLUGINS Testing Strategy

📍 Testing Framework Location

NO creamos testing framework aquí. Ya existe en:

c:\AudioDev\audio-lab\2 - FOUNDATION\03_INFRA\03_04_testing_framework

Este documento explica cómo usar ese framework para validar cada componente de 08_PLUGINS.


🎯 Testing Philosophy para Plugin Infrastructure

Principios Fundamentales

  1. Test-Driven Development (TDD): Escribir tests ANTES que implementación
  2. Validación Continua: Cada carpeta tiene tests que demuestran que funciona
  3. Automated Quality Gates: CI/CD ejecuta todos los tests
  4. Documentation Through Tests: Tests son ejemplos vivientes de uso

📂 Testing por Carpeta

08_00_00_contracts (Interfaces Base)

¿Qué testear? - ✅ Headers compilan sin errores - ✅ Interfaces son abstractas puras (no instanciables) - ✅ Documentación completa por método - ✅ Ejemplo de implementación compila

Ubicación tests:

2 - FOUNDATION/03_INFRA/03_04_testing_framework/tests/integration/08_plugins/
└── test_00_contracts.cpp

Ejemplo test:

TEST_CASE("IPluginProcessor interface is pure virtual", "[contracts][unit]") {
    // Verify cannot instantiate
    // IPluginProcessor processor; ← Should not compile

    REQUIRE(std::is_abstract<IPluginProcessor>::value);
}

TEST_CASE("Concrete implementation compiles", "[contracts][integration]") {
    class TestProcessor : public IPluginProcessor {
        void process(AudioBuffer& buffer) override { /* impl */ }
        void initialize(float sampleRate, int blockSize) override { /* impl */ }
    };

    TestProcessor processor;
    SUCCEED("Concrete implementation compiled and instantiated");
}


08_01_00_component_library (Catálogo L3)

¿Qué testear? - ✅ Catálogo JSON válido (schema compliance) - ✅ Todos los L3s referenciados existen en 05_MODULES - ✅ Metadata completa por componente - ✅ Search functionality funciona

Tests:

TEST_CASE("Component catalog is valid JSON", "[composition][unit]") {
    auto catalog = loadJson("component_library/catalog.json");
    REQUIRE(catalog.is_object());
    REQUIRE(catalog.contains("components"));
}

TEST_CASE("All referenced L3 engines exist", "[composition][integration]") {
    auto catalog = ComponentCatalog::load();

    for (const auto& component : catalog.components()) {
        INFO("Checking component: " << component.name);

        // Verify L3 exists in 05_MODULES
        std::filesystem::path l3Path =
            "../../3 - COMPONENTS/05_MODULES/" + component.path;

        REQUIRE(std::filesystem::exists(l3Path));
    }
}


08_02_00_engine_instantiation (DSP Factory)

¿Qué testear? - ✅ Factory crea instancias válidas de L3s - ✅ Dependency resolution correcto - ✅ Resource allocation sin memory leaks - ✅ Initialization order respetado

Tests:

TEST_CASE("Factory instantiates L3 engine", "[dsp][integration]") {
    EngineFactory factory;

    auto engine = factory.create("BiquadFilter", "v1.0");

    REQUIRE(engine != nullptr);
    REQUIRE(engine->getName() == "BiquadFilter");
    REQUIRE(engine->getVersion() == "v1.0");
}

TEST_CASE("Factory respects dependencies", "[dsp][integration]") {
    EngineFactory factory;

    // Compressor depends on EnvelopeFollower
    auto compressor = factory.create("Compressor", "v1.0");

    REQUIRE(compressor != nullptr);
    REQUIRE(compressor->getDependencies().size() > 0);

    // Verify dependencies were initialized
    for (const auto& dep : compressor->getDependencies()) {
        REQUIRE(dep->isInitialized());
    }
}


08_07_00_syntax_validation (Manifest Validation)

¿Qué testear? - ✅ Valid manifests pass validation - ✅ Invalid manifests fail with clear errors - ✅ Schema compliance checking - ✅ Helpful error messages

Tests:

TEST_CASE("Valid manifest passes validation", "[validation][unit]") {
    const char* validManifest = R"({
        "product": "TestPlugin",
        "type": "l4_plugin",
        "engines": [
            {"id": "filter", "type": "BiquadFilter", "version": "1.0"}
        ],
        "routing": {
            "signal": "input → filter → output"
        }
    })";

    ManifestValidator validator;
    auto result = validator.validate(validManifest);

    REQUIRE(result.isValid());
    REQUIRE(result.errors().empty());
}

TEST_CASE("Invalid manifest fails with clear error", "[validation][unit]") {
    const char* invalidManifest = R"({
        "product": "TestPlugin",
        "type": "invalid_type"
    })";

    ManifestValidator validator;
    auto result = validator.validate(invalidManifest);

    REQUIRE_FALSE(result.isValid());
    REQUIRE(result.errors().size() > 0);

    // Verify error message is helpful
    auto error = result.errors()[0];
    REQUIRE(error.contains("invalid_type"));
    REQUIRE(error.contains("l4_plugin or l5_suite"));
}


🔄 Testing Workflow

Paso 1: Definir SPEC

Antes de implementar, crear SPEC.md en cada carpeta:

# 08_00_00_contracts Specification

## Purpose
Define abstract interfaces for all plugins.

## Requirements
- IPluginProcessor with process(), initialize(), shutdown()
- IStateManager with saveState(), loadState()
- Pure virtual (= 0) methods only

## Acceptance Criteria
✅ Headers compile
✅ Cannot instantiate interfaces
✅ Concrete impl compiles
✅ All methods documented

Paso 2: Escribir Tests (RED)

Crear tests que fallan (aún no hay implementación):

TEST_CASE("IPluginProcessor compiles", "[contracts]") {
    // This will FAIL initially - header doesn't exist yet
    #include "IPluginProcessor.hpp"
    SUCCEED();
}

Paso 3: Implementar (GREEN)

Crear implementación mínima que pasa tests:

// IPluginProcessor.hpp
class IPluginProcessor {
public:
    virtual ~IPluginProcessor() = default;
    virtual void process(AudioBuffer& buffer) = 0;
    virtual void initialize(float sampleRate, int blockSize) = 0;
};

Paso 4: Refinar (REFACTOR)

Mejorar implementación, tests siguen pasando:

// Add documentation, better error handling, etc.

Paso 5: Validar

# Run all tests
cd "2 - FOUNDATION/03_INFRA/03_04_testing_framework"
cmake --build build --target RUN_TESTS

# Or specific category
./build/Release/audiolab_tests [contracts]

📊 Coverage Requirements

Por Categoría

Carpeta Unit Tests Integration Tests System Tests
08_00_contracts 100% N/A N/A
08_01_composition_tools 80% 90% 100%
08_02_dsp_integration 70% 90% N/A
08_07_manifest_validation 95% 100% N/A
08_13_products N/A 80% 100%

🎯 Quality Gates

Pre-Commit

# Fast tests only (< 100ms total)
./run_tests.sh --tag=[unit]

Pre-Push

# All tests except slow system tests
./run_tests.sh --tag=[unit],[integration]

CI Pipeline

# Everything including system tests
./run_tests.sh --tag=*

📝 Test Naming Convention

Seguir patrón de 03_INFRA/03_04_testing_framework:

// Pattern: [Component] [action] [expected result]
TEST_CASE("Biquad filter attenuates frequencies above cutoff", "[dsp][unit]")
TEST_CASE("Manifest validator rejects invalid routing", "[validation][unit]")
TEST_CASE("Plugin loads in VST3 host without crash", "[plugin][system]")

Tags Standardizados

  • [unit] - Unit test (< 1ms)
  • [integration] - Integration test (< 100ms)
  • [system] - System test (< 5s)
  • [benchmark] - Performance test
  • [quality] - Audio quality test
  • [regression] - Regression test for fixed bugs

🚀 Getting Started

1. Leer filosofía existente

code "2 - FOUNDATION/03_INFRA/03_04_testing_framework/03_04_00_test_frameworks/TEST_FRAMEWORK_PHILOSOPHY.md"

2. Ver ejemplos

# Hay tests ejemplo en:
2 - FOUNDATION/03_INFRA/03_04_testing_framework/03_04_02_test_utilities/

3. Crear primer test

# Para 08_00_00_contracts:
cd "2 - FOUNDATION/03_INFRA/03_04_testing_framework"
mkdir -p tests/integration/08_plugins
# Crear test_00_contracts.cpp

💡 Best Practices

DO ✅

  • Escribir tests ANTES de implementar
  • Usar helpers existentes de 03_04_02_test_utilities
  • Mantener tests rápidos (< 1ms unit, < 100ms integration)
  • Tests independientes (pueden correr en paralelo)
  • Nombres descriptivos y claros

DON'T ❌

  • Tests que dependen de orden de ejecución
  • Tests flaky (non-deterministic)
  • Tests mega (testing too much)
  • Ignorar tests que fallan
  • Commit code sin tests

🔗 Referencias

  • Framework Philosophy: 03_INFRA/03_04_testing_framework/03_04_00_test_frameworks/TEST_FRAMEWORK_PHILOSOPHY.md
  • Test Categories: 03_INFRA/03_04_testing_framework/03_04_01_test_organization/TEST_CATEGORIES.md
  • Test Utilities: 03_INFRA/03_04_testing_framework/03_04_02_test_utilities/
  • Catch2 Docs: https://github.com/catchorg/Catch2

Generated with AudioLab 🎵 Testing makes perfect