---
title: "Functional testing"
manual: "TYPO3 LLM Extension"
version: "0.35"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-llm:testing-functional-testing@0.35"
source: "Testing/FunctionalTesting.rst"
modified: "2026-09-16T22:09:16+00:00"
---

# Functional testing

## Running functional tests

**Run functional tests**

```bash
# Run TYPO3 functional tests
Build/Scripts/runTests.sh -s functional

# Alternative: Via Composer script
composer ci:test:php:functional
```

## Functional test example

**Example: Functional test**

```php
<?php

namespace Netresearch\NrLlm\Tests\Functional\Repository;

use Netresearch\NrLlm\Domain\Model\Provider;
use Netresearch\NrLlm\Domain\Repository\ProviderRepository;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;

class ProviderRepositoryTest extends FunctionalTestCase
{
    protected array $testExtensionsToLoad = [
        'netresearch/nr-llm',
    ];

    private ProviderRepository $repository;

    protected function setUp(): void
    {
        parent::setUp();
        $this->repository = $this->get(ProviderRepository::class);
    }

    public function testFindOneByIdentifierReturnsProvider(): void
    {
        $this->importCSVDataSet(__DIR__ . '/Fixtures/providers.csv');

        $provider = $this->repository->findOneByIdentifier('openai-test');

        $this->assertInstanceOf(Provider::class, $provider);
        $this->assertEquals('OpenAI Test', $provider->getName());
    }
}
```

## Test fixtures

### CSV fixtures

**Tests/Functional/Fixtures/providers.csv**

```text
"tx_nrllm_provider"
"uid","pid","identifier","name","adapter_type","is_active"
1,0,"openai-test","OpenAI Test","openai",1
```

### JSON response fixtures

**Tests/Fixtures/openai_chat_response.json**

```json
{
  "id": "chatcmpl-123",
  "object": "chat.completion",
  "created": 1677652288,
  "model": "gpt-5",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Test response"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 10,
    "completion_tokens": 5,
    "total_tokens": 15
  }
}
```

## Mutation testing

The extension uses Infection for mutation testing to ensure test quality.

### Running mutation tests

**Run mutation tests**

```bash
# Run mutation tests via runTests.sh
Build/Scripts/runTests.sh -s mutation

# Alternative: Via Composer script
composer ci:test:php:mutation
```

### Interpreting results

-   **MSI (Mutation Score Indicator)**: Percentage of mutations killed.
-   **Target**: >60% MSI indicates good test quality.
-   **Current**: 58% MSI (459 tests).

**Mutation testing results**

```text
Mutation Score Indicator (MSI): 58%
Mutation Code Coverage: 85%
Covered Code MSI: 68%
```

## Best practices

1.  **Isolate tests**: Each test should be independent.
1.  **Mock external APIs**: Never call real APIs in unit tests.
1.  **Use data providers**: For testing multiple scenarios.
1.  **Test edge cases**: Empty inputs, null values, boundaries.
1.  **Descriptive names**: Test method names should describe behavior.
1.  **Arrange-Act-Assert**: Follow AAA pattern.
1.  **Fast tests**: Unit tests should complete in milliseconds.
1.  **Coverage goals**: Aim for >80% line coverage.
