Skip to content

Unit & Integration Tests implementieren #7

@csaeum

Description

@csaeum

Beschreibung

Das Plugin hat aktuell keine Tests. Für Production-Readiness und Wartbarkeit sollen umfassende Tests implementiert werden.

Anforderungen

1. Test-Struktur

tests/
├── Unit/
│   ├── Service/
│   │   ├── VariantUpdateServiceTest.php
│   │   ├── BatchSizeCalculatorTest.php
│   │   └── ProgressTrackerTest.php
│   └── Command/
│       └── UpdateVariantCommandTest.php
├── Integration/
│   ├── Command/
│   │   ├── UpdateVariantCommandIntegrationTest.php
│   │   └── UpdateAllVariantsCommandIntegrationTest.php
│   ├── MessageHandler/
│   │   └── UpdateVariantsBatchMessageHandlerTest.php
│   └── Controller/
│       └── VariantUpdateControllerTest.php
└── Fixtures/
    ├── ProductFixtures.php
    └── VariantFixtures.php

2. Unit Tests

A. String-Normalisierung (normalizeString())

class VariantUpdateServiceTest extends TestCase
{
    /**
     * @dataProvider normalizeStringProvider
     */
    public function testNormalizeString(string $input, string $expected): void
    {
        // Test cases:
        // - Umlaute: "Größe XL" → "groesse-xl"
        // - Spaces: "Black Metallic" → "black-metallic"
        // - Mixed: "Blau/Grün" → "blau-gruen"
        // - Edge: "   Test  " → "test"
    }
}

B. Produktnummern-Generierung (generateProductNumber())

public function testGenerateProductNumber(): void
{
    // Test cases:
    // - Single option: "jacket-001" + ["XL"] → "jacket-001-xl"
    // - Multiple: "jacket-001" + ["XL", "Black"] → "jacket-001-xl-black"
    // - Special chars: Option "Blau/Grün" → "blau-gruen"
    // - Empty options: [] → parent number unchanged
}

C. Batch-Size-Calculator

class BatchSizeCalculatorTest extends TestCase
{
    public function testIncreaseBatchSizeOnSuccess(): void
    {
        // 100 → 120 (bei schneller Verarbeitung)
    }
    
    public function testDecreaseBatchSizeOnTimeout(): void
    {
        // 100 → 70 (bei langsamer Verarbeitung)
    }
    
    public function testMaxBatchSizeLimit(): void
    {
        // Nicht über 500 erhöhen
    }
    
    public function testMinBatchSizeLimit(): void
    {
        // Nicht unter 10 reduzieren
    }
}

3. Integration Tests

A. Command Execution

class UpdateVariantCommandIntegrationTest extends KernelTestCase
{
    use IntegrationTestBehaviour;
    
    protected function setUp(): void
    {
        parent::setUp();
        $this->createTestProducts(); // Fixture mit Parent + 3 Varianten
    }
    
    public function testUpdateSingleProduct(): void
    {
        $command = $this->getContainer()->get(UpdateVariantCommand::class);
        $input = new ArrayInput([
            '--product-numbers' => 'test-product-001',
        ]);
        $output = new BufferedOutput();
        
        $exitCode = $command->run($input, $output);
        
        $this->assertSame(Command::SUCCESS, $exitCode);
        $this->assertVariantsUpdated('test-product-001');
    }
    
    public function testDryRunDoesNotPersist(): void
    {
        // Prüfen dass Varianten NICHT aktualisiert werden
    }
    
    public function testNameOnlyOption(): void
    {
        // Prüfen dass nur Namen aktualisiert werden
    }
}

B. Message Queue Handler

class UpdateVariantsBatchMessageHandlerTest extends KernelTestCase
{
    public function testHandlerProcessesBatch(): void
    {
        $message = new UpdateVariantsBatchMessage(['prod-1', 'prod-2']);
        $handler = $this->getContainer()->get(UpdateVariantsBatchMessageHandler::class);
        
        $handler->__invoke($message);
        
        $this->assertVariantsUpdated('prod-1');
        $this->assertVariantsUpdated('prod-2');
    }
    
    public function testProgressTracking(): void
    {
        // Prüfen dass Progress korrekt getrackt wird
    }
}

C. Admin Controller

class VariantUpdateControllerTest extends KernelTestCase
{
    public function testTriggerUpdateEndpoint(): void
    {
        $client = $this->getBrowser();
        $client->request('POST', '/api/_action/wsc-variant-updater/update', [
            'productNumbers' => ['test-001'],
        ]);
        
        $this->assertResponseStatusCodeSame(200);
        $response = json_decode($client->getResponse()->getContent(), true);
        $this->assertArrayHasKey('batchId', $response);
    }
}

4. Test-Fixtures

Product Fixtures

trait ProductFixtures
{
    private function createTestProduct(string $productNumber, array $variants = []): string
    {
        // Erstellt Parent-Produkt + Varianten mit Options
        // Gibt Parent-ID zurück
    }
    
    private function createOptionGroup(string $name, array $options): string
    {
        // Erstellt OptionGroup (z.B. "Größe") mit Options (["XL", "L", "M"])
    }
}

5. Test-Coverage-Ziele

Komponente Ziel Aktuell
Commands 80% 0%
Services 90% 0%
Message Handlers 85% 0%
Controllers 75% 0%
Gesamt 80% 0%

6. CI Integration

PHPUnit in GitHub Actions

test:
  runs-on: ubuntu-latest
  strategy:
    matrix:
      php: ['8.1', '8.2', '8.3']
      shopware: ['6.5', '6.6']
  steps:
    - uses: shivammathur/setup-php@v2
      with:
        php-version: ${{ matrix.php }}
    - run: composer install
    - run: vendor/bin/phpunit --coverage-clover coverage.xml
    - uses: codecov/codecov-action@v3

7. Technische Umsetzung

Dependencies

{
  "require-dev": {
    "phpunit/phpunit": "^10.0",
    "symfony/browser-kit": "^6.0",
    "symfony/http-client": "^6.0"
  }
}

phpunit.xml.dist

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php">
    <testsuites>
        <testsuite name="Unit">
            <directory>tests/Unit</directory>
        </testsuite>
        <testsuite name="Integration">
            <directory>tests/Integration</directory>
        </testsuite>
    </testsuites>
    <coverage>
        <include>
            <directory>src</directory>
        </include>
        <exclude>
            <directory>src/Resources</directory>
        </exclude>
        <report>
            <clover outputFile="var/coverage/clover.xml"/>
            <html outputDirectory="var/coverage/html"/>
        </report>
    </coverage>
</phpunit>

Akzeptanzkriterien

  • PHPUnit konfiguriert und lauffähig
  • Mind. 80% Code Coverage
  • Unit Tests für alle Service-Methoden
  • Integration Tests für Commands
  • Integration Tests für Message Handlers
  • Fixtures für Test-Daten
  • CI führt Tests automatisch aus
  • Coverage-Report in CI

Priorisierung

Phase 1 (Sofort):

  1. normalizeString() Unit Tests
  2. generateProductNumber() Unit Tests
  3. UpdateVariantCommand Integration Test

Phase 2 (Mit Message Queue):
4. Batch-Size-Calculator Tests
5. Message Handler Tests
6. Progress Tracker Tests

Phase 3 (Mit Admin):
7. Controller Tests
8. End-to-End Admin Tests

Abhängigkeiten

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions