Testing

Strategia e framework di test per WvdS FPC RAD Studio.

Tipi di test

Tipo Scope Strumenti Esecuzione
Unit test Singole funzioni FPCUnit Locale
Test integrazione Interazione componenti FPCUnit Locale
Test E2E Estensione completa VS Code Test Runner CI

Unit test

Struttura

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

Framework di test

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.

Convenzioni naming

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

Esempi:
TestValidatePath_ValidPath_ReturnsTrue
TestValidatePath_EmptyString_ReturnsFalse
TestGenerateCommand_ReleaseMode_IncludesOptimization

Garantire la testabilita

Design dei service

// TESTABILE - Nessuna dipendenza UI
function ValidateName(const AName: string; out AError: string): Boolean;
 
// NON TESTABILE - UI nella logica
procedure ValidateAndShowError(const AName: string);

Dependency Injection

// TESTABILE - Dipendenza iniettata
function ProcessFile(const APath: string; AFileReader: IFileReader): TResult;
 
// NON TESTABILE - Dipendenza hardcoded
function ProcessFile(const APath: string): TResult;
begin
  Content := ReadFile(APath);  // Non mockabile
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;  // Contenuto predefinito
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;

Test di integrazione

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;

Test E2E

Testing estensioni VS Code con @vscode/test-electron:

// test/extension.test.js (generato da 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');
    // Verificare che output channel contenga messaggio atteso
  });
});

Esecuzione test

Locale

# Unit test
wvds-test unit
 
# Test integrazione
wvds-test integration
 
# Tutti i test
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
 
# Genera:
# binaries/logs/coverage.html
# binaries/logs/coverage.json

Coverage minima:

  • Service: 80%
  • Model: 90%
  • Utility: 70%

Vedi anche

Zuletzt geändert: il 29/01/2026 alle 22:38