Testing

Teststrategie und -framework für WvdS FPC RAD Studio.

Testarten

Art Scope Tools Ausführung
Unit-Tests Einzelne Funktionen FPCUnit Lokal
Integration-Tests Komponenten-Zusammenspiel FPCUnit Lokal
E2E-Tests Gesamte Extension VS Code Test Runner CI

Unit-Tests

Struktur

sources/
├── extensions/
│   └── wvds.vscode.build/
│       ├── pas/
│       │   ├── Build.Service.pas
│       │   └── Build.Models.pas
│       └── tests/
│           ├── Build.Service.Tests.pas
│           └── Build.Models.Tests.pas

Test-Framework

unit Build.Service.Tests;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  TestFramework,
  Build.Service,
  Build.Models;
 
type
  TBuildServiceTest = class(TTestCase)
  published
    procedure TestValidatePath_ValidPath_ReturnsTrue;
    procedure TestValidatePath_InvalidPath_ReturnsFalse;
    procedure TestGenerateCommand_DebugMode_IncludesDebugFlags;
  end;
 
implementation
 
procedure TBuildServiceTest.TestValidatePath_ValidPath_ReturnsTrue;
var
  Error: string;
begin
  CheckTrue(ValidateBuildPath('%USERPROFILE%\Projects\MyApp', Error));
  CheckEquals('', Error);
end;
 
procedure TBuildServiceTest.TestValidatePath_InvalidPath_ReturnsFalse;
var
  Error: string;
begin
  CheckFalse(ValidateBuildPath('', Error));
  CheckNotEquals('', Error);
end;
 
procedure TBuildServiceTest.TestGenerateCommand_DebugMode_IncludesDebugFlags;
var
  Config: TWvdSBuildConfig;
  Command: string;
begin
  Config.Mode := bmDebug;
  Config.ProjectPath := 'test.lpr';
 
  Command := GenerateBuildCommand(Config);
 
  CheckTrue(Pos('-g', Command) > 0, 'Debug flag missing');
  CheckTrue(Pos('-O0', Command) > 0, 'No-optimization flag missing');
end;
 
initialization
  RegisterTest(TBuildServiceTest.Suite);
 
end.

Naming Conventions

Test{Feature}_{Scenario}_{ExpectedResult}

Beispiele:
TestValidatePath_ValidPath_ReturnsTrue
TestValidatePath_EmptyString_ReturnsFalse
TestGenerateCommand_ReleaseMode_IncludesOptimization

Testbarkeit sicherstellen

Service-Design

// TESTBAR - Keine UI-Abhängigkeit
function ValidateName(const AName: string; out AError: string): Boolean;
 
// NICHT TESTBAR - UI in Logik
procedure ValidateAndShowError(const AName: string);

Dependency Injection

// TESTBAR - Abhängigkeit injiziert
function ProcessFile(const APath: string; AFileReader: IFileReader): TResult;
 
// NICHT TESTBAR - Hardcodierte Abhängigkeit
function ProcessFile(const APath: string): TResult;
begin
  Content := ReadFile(APath);  // Nicht mockbar
end;

Mocking

type
  TMockFileReader = class(TInterfacedObject, IFileReader)
    FContent: string;
    function ReadFile(const APath: string): string;
  end;
 
function TMockFileReader.ReadFile(const APath: string): string;
begin
  Result := FContent;  // Vordefinierter Inhalt
end;
 
procedure TProcessorTest.TestProcessFile_ValidContent_Succeeds;
var
  Mock: TMockFileReader;
  Processor: TProcessor;
begin
  Mock := TMockFileReader.Create;
  Mock.FContent := 'test content';
 
  Result := ProcessFile('any.txt', Mock);
 
  CheckEquals('expected output', Result);
end;

Integration-Tests

unit Integration.BuildPipeline.Tests;
 
procedure TBuildPipelineTest.TestFullBuild_ConsoleApp_ProducesExe;
var
  Project: TWvdSProject;
  Result: TWvdSBuildResult;
begin
  // Setup
  Project := CreateTestProject(ptConsole);
 
  // Execute
  Result := BuildProject(Project);
 
  // Verify
  CheckEquals(bsSuccess, Result.Status);
  CheckTrue(FileExists(Result.OutputPath));
 
  // Cleanup
  DeleteTestProject(Project);
end;

E2E-Tests

VS Code Extension Testing mit @vscode/test-electron:

// test/extension.test.js (generiert aus Pascal)
const vscode = require('vscode');
const assert = require('assert');
 
suite('Extension Test Suite', () => {
  test('Build command exists', async () => {
    const commands = await vscode.commands.getCommands();
    assert.ok(commands.includes('wvds.build.run'));
  });
 
  test('Build command executes', async () => {
    await vscode.commands.executeCommand('wvds.build.run');
    // Verify output channel contains expected message
  });
});

Test-Ausführung

Lokal

# Unit-Tests
wvds-test unit
 
# Integration-Tests
wvds-test integration
 
# Alle Tests
wvds-test all

CI

test:
  runs-on: ubuntu-latest
  steps:
    - name: Run Unit Tests
      run: wvds-test unit --report junit

    - name: Run E2E Tests
      run: wvds-test e2e --report junit

    - name: Upload Results
      uses: actions/upload-artifact@v3
      with:
        name: test-results
        path: binaries/logs/test-*.xml

Code Coverage

wvds-test unit --coverage
 
# Generiert:
# binaries/logs/coverage.html
# binaries/logs/coverage.json

Mindest-Coverage:

  • Services: 80%
  • Models: 90%
  • Utilities: 70%

Siehe auch

Zuletzt geändert: den 29.01.2026 um 15:13