Contenuto

# Servizio SFUnitTests.UnitTest

Il servizio UnitTest fornisce un framework per automatizzare i test unitari usando il linguaggio Basic, comprende le funzionalità per:

- Aggregare i casi da verificare in suite di test e test unitari.

- Condividere il codice di impostazione e di terminazione tra i vari casi sottoposti a test.

- Visualizzare i risultati dei test usando la Console.

Sia i test unitari che il codice da verificare devono essere scritti in Basic. Il codice sottoposto a test può chiamare funzioni scritte in altri linguaggi.

Il servizio UnitTest non è disponibile per gli script in Python.

## Definizioni

### Test Case

Un test case è la singola unità del test. Verifica una specifica risposta a un determinato insieme di input.

Nel servizio UnitTest, un test case è costituito da una singola Sub di Basic il cui nome inizia con un prefisso comune (quello predefinito è "Test_").

Il test case fallisce se uno dei metodi AssertX restituisce False.

### Test Suite

Una test suite è una raccolta di test case che dovrebbero essere eseguiti assieme.

Tutti i test case di una test suite sono memorizzati in un singolo modulo di Basic.

Una test suite può implementare i metodi SetUp e TearDown per preparare i test case del modulo.

### Test unitario

Un test unitario completo è costituito da un insieme di test suite all'interno della stessa libreria di Basic.

## Invocazione del servizio

Prima di usare il servizio UnitTest è necessario caricare o importare le librerie ScriptForge:

• Le macro in Basic richiedono il caricamento della libreria ScriptForge usando la seguente istruzione:
GlobalScope.BasicLibraries.loadLibrary("ScriptForge")
• Gli script in Python richiedono un'importazione dal modulo scriptforge:
from scriptforge import CreateScriptService

### Modo semplificato

È possibile invocare il servizio nel modo semplificato per chiamare le funzioni AssertX senza dover costruire una gerarchia completa di test suite e test case.

Nel modo semplificato, il servizio è invocato all'interno del test case, come mostrato nell'esempio seguente:

        Sub SimpleTest
            On Local Error GoTo CatchError
            Dim myTest As Variant
            myTest = CreateScriptService("UnitTest")
            ' Alcuni semplici test
            myTest.AssertEqual(1 + 1, 2)
            myTest.AssertEqual(1 - 1, 0)
            MsgBox("Tutti i controlli sono stati passati")
            Exit Sub
        CatchError:
            myTest.ReportError("Un controllo è fallito")
        End Sub

In questo esempio, se una delle chiamate AssertEqual fallisce, l'interprete andrà all'etichetta CatchError e visualizzerà l'errore chiamando il metodo ReportError.

### Modo completo

Quando è invocato nel modo completo, la creazione del servizio è esterna al codice del test e tutti i controlli sono organizzati in test case e test suite all'interno di una singola libreria.

L'esempio seguente crea un'istanza di UnitTest i cui controlli sono situati all'interno del documento corrente (ThisComponent) nella libreria "Tests".

        GlobalScope.BasicLibraries.loadLibrary("ScriptForge")
        Dim myUnitTest As Variant
        myUnitTest = CreateScriptService("UnitTest", ThisComponent, "Tests")

### Un esempio minimale in modo completo

Si consideri un file ODS che contenga un modulo denominato "MathUtils" nella sua libreria "Standard" con il seguente codice:

        ' Codice nel modulo Standard.MathUtils
        Function Sum(a, b) As Double
            Sum = a + b
        End Function

        Function Multiply(a, b) As Double
            Multiply = a * b
        End Function

Per creare una test suite completa, si presuma che una nuova libreria "Tests" venga creata nel file con all'interno un unico modulo "AllTests" contenente il seguente codice:

        ' Codice nel modulo Tests.AllTests
        Sub Main()
            GlobalScope.BasicLibraries.loadLibrary("ScriptForge")
            Dim test As Variant
            test = CreateScriptService("UnitTest", ThisComponent, "Tests")
            test.RunTest("AllTests")
            test.Dispose()
        End Sub

        Sub Setup(test)
            ' Il codice di preparazione è eseguito prima del primo test case
            Dim exc As Variant
            exc = CreateScriptService("Exception")
            exc.Console(Modal := False)
        End Sub

        Sub TearDown(test)
            ' Codice di pulizia opzionale, chiamato dopo l'ultimo test case
        End Sub

        Sub Test_Sum(test)
            On Local Error GoTo CatchError
            test.AssertEqual(Sum(1, 1), 2, "Somma due interi positivi")
            test.AssertEqual(Sum(-10, 20), 10, "Somma di interi negativi e positivi")
            test.AssertEqual(Sum(1.5, 1), 2.5, "Somma di valori interi e a virgola mobile")
            Exit Sub
        CatchError:
            test.ReportError("Il metodo Sum non funziona")
        End Sub

        Sub Test_Multiply(test)
            On Local Error GoTo CatchError
            test.AssertEqual(Multiply(2, 2), 4, "Moltiplica due positivi interi")
            test.AssertEqual(Multiply(-4, 2), -8, "Moltiplica degli interi negativi e positivi")
            test.AssertEqual(Multiply(1.5, 3), 4.5, "Moltiplica dei valori interi e in virgola mobile")
            Exit Sub
        CatchError:
            test.ReportError("Il metodo Multiply non funziona")
        End Sub

La test suite di cui sopra, è costituita da due test case Test_Sum e Test_Multiply. Per eseguire tutti i test eseguire semplicemente il metodo Main del modulo "AllTests".

La Console del servizio Exception è usata come output predefinito per visualizzare i risultati dei test. Dopo l'esecuzione dell'esempio di cui sopra, nella console sarà visualizzato il seguente output:

        ' RUNTEST ENTER testsuite='Tests.AllTests', pattern='Test_*'
        '   SETUP Tests.AllTests.Setup() ENTER
        '   SETUP Tests.AllTests.Setup() EXIT
        '   TESTCASE Tests.AllTests.Test_Multiply() ENTER
        '   TESTCASE Tests.AllTests.Test_Multiply() EXIT (0,017 sec)
        '   TESTCASE Tests.AllTests.Test_Sum() ENTER
        '   TESTCASE Tests.AllTests.Test_Sum() EXIT (0,016 sec)
        '   TEARDOWN Tests.AllTests.TearDown() ENTER
        '   TEARDOWN Tests.AllTests.TearDown() EXIT
        ' RUNTEST EXIT testsuite='Tests.AllTests' (0,223 sec)

Se durante questi test uno dei metodi AssertEqual fallisce, nella console verrà aggiunto un messaggio di errore.

## Proprietà

Nome | Sola lettura | Tipo | Descrizione
--- | --- | --- | ---
LongMessage | No | Boolean | Quando è impostato su True (predefinito) la console visualizza il messaggio standard accodato al messaggio definito da colui che effettua il test. Se è False, viene usato solo il messaggio definito da colui che effettua il test.
ReturnCode | Sì | Integer | Valore restituito da RunTest dopo che il test unitario è terminato. Il seguente è un elenco dei possibili valori: 0 - Test terminato senza errori o test non avviato 1 - Una asserzione all'interno del test case ha restituito False 2 - Uno SkipTest è stato attivato dal metodo Setup o da uno dei test case. 3 - Termine anomalo del test
Verbose | No | Boolean | Quando è impostato a True, tutte le asserzioni sono visualizzate nella console (sia che falliscano o no). Se è False (predefinito), vengono visualizzate solo le asserzioni che falliscono.
WhenAssertionFails | No | Integer | Stabilisce cosa fare quando una asserzione non è rispettata. Il seguente è un elenco dei valori possibili: 0 - Ignora il fallimento e continua a eseguire il test 1 - Esegue il metodo TearDown del modulo per il test corrente e avvia la prossima suite (predefinito nel modo completo). 2 - Termina immediatamente (predefinito nel modo semplificato)

Elenco dei metodi del servizio UnitTest
AssertAlmostEqual AssertEqual AssertFalse AssertGreater AssertGreaterEqual AssertIn AssertIsInstance AssertIsNothing AssertLike | AssertNotRegex AssertIsNull AssertLess AssertLessEqual AssertNotAlmostEqual AssertNotEqual AssertNotIn AssertNotInstance AssertNotLike | AssertNotNothing AssertNotNull AssertRegex AssertTrue Fail Log ReportError RunTest SkipTest

## Argomenti dei metodi AssertX

Tutte le asserzioni verificano una o due espressioni, a cui nel resto di questa guida si fa riferimento come A e B. Questi sono sempre il primo o i primi due argomenti del metodo AssertX.

Tutti i metodi AssertX accettano un argomento message che specifica un messaggio personalizzato da visualizzare nella console relativamente a quella asserzione. Per impostazione predefinita è usata una stringa vuota. Questo argomento è sempre nell'ultima posizione dell'asserzione.

Alcuni metodi AssertX accettano anche degli argomenti aggiuntivi, descritti di seguito con le loro sintassi.

## AssertAlmostEqual

Restituisce True quando A e B sono valori numerici e sono considerati tra loro vicini, data una tolleranza relativa.

### Sintassi:

svc.AssertAlmostEqual(a: any, b: any, tolerance: double = 1E-09, message: str = ""): bool

Questa asserzione restituisce True se si verificano le due seguenti condizioni:

- A e B possono essere convertiti nel tipo Double.

- La differenza assoluta tra A e B divisa per il maggiore tra i valori assoluti di A e B è minore del valore di tolleranza (tolerance) specificato.

## AssertEqual

Restituisce True quando A e B sono considerati uguali.

### Sintassi:

svc.AssertEqual(a: any, b: any, message: str = ""): bool

Quando A e B sono scalari, viene restituito True se:

- Entrambe le espressioni hanno lo stesso VarType o sono entrambe numeriche.

- I valori booleani e numerici sono comparati con l'operatore =.

- Le stringhe sono comparate con la funzione incorporata StrComp. Il confronto distingue tra minuscole e maiuscole.

- Date e orari sono comparati fino al secondo.

- Null, Empty e Nothing non sono uguali, ma AssertEqual(Nothing, Nothing) restituisce True.

- Gli oggetti UNO sono comparati con il metodo incorporato EqualUnoObjects.

- Da notare che gli oggetti di Basic non sono mai uguali.

Quando A e B sono matrici, viene restituito True se:

- Entrambe le matrici hanno lo stesso numero di dimensioni (fino a 2 dimensioni) e i loro limiti inferiori e superiori sono identici per tutte le dimensioni.

- Tutti gli elementi di entrambe le matrici sono uguali, uno per uno.

- Due matrici vuote sono considerate uguali.

## AssertFalse

Restituisce True quando il tipo di A è Boolean e il suo valore è False.

### Sintassi:

svc.AssertFalse(a: any, message: str = ""): bool

## AssertGreater

Restituisce True quando A è maggiore di B.

### Sintassi:

svc.AssertGreater(a: any, b: any, message: str = ""): bool

Il confronto tra A e B presume quanto segue:

- I tipi di dati possibili sono String, Date o un tipo numerico.

- Entrambe le espressioni devono avere lo stesso VarType o entrambe devono essere numeriche.

- Il confronto tra stringhe distingue tra maiuscole e minuscole.

## AssertGreaterEqual

Restituisce True quando A è maggiore o uguale a B.

### Sintassi:

svc.AssertGreaterEqual(a: any, b: any, message: str = ""): bool

Il confronto tra A e B presume quanto segue:

- I tipi di dati possibili sono String, Date o un tipo numerico.

- Entrambe le espressioni devono avere lo stesso VarType o entrambe devono essere numeriche.

- Il confronto tra stringhe distingue tra maiuscole e minuscole.

## AssertIn

Restituisce True quando A si trova all'interno di B.

### Sintassi:

svc.AssertIn(a: any, b: any, message: str = ""): bool

Questa asserzione presume quanto segue:

- L'espressione B può essere una matrice unidimensionale, un oggetto Dictionary di ScriptForge o una stringa.

- Quando l'espressione B è una matrice unidimensionale, l'espressione A può essere una data o un valore numerico.

- Quando l'espressione B è un oggetto Dictionary di ScriptForge, la stringa A viene cercata tra le chiavi di B.

- Il confronto tra stringhe distingue tra maiuscole e minuscole.

## AssertIsInstance

Restituisce True se A è un'istanza del tipo di oggetto specificato, indicato in formato stringa contenente il nome del tipo.

### Sintassi:

svc.AssertIsInstance(a: any, objecttype: str, message: str = ""): bool

L'espressione A può contenere uno dei seguenti elementi:

- Un oggetto di ScriptForge. In questo caso, l'argomento objecttype è una stringa come "DICTIONARY", "calc", "Dialog", ecc.

- Un oggetto UNO. In questo caso l'argomento objecttype deve essere una stringa identica al valore restituito dal metodo SF_Session.UnoObjectType().

- Una matrice. In questo caso l'argomento objecttype è atteso come "array" (matrice).

- Qualsiasi altra variabile (che non sia un Object o un Array). In questo caso l'argomento objecttype è una stringa corrispondente al valore restituito dalla funzione incorporata TypeName.

## AssertIsNothing

Restituisce True se A è un oggetto con valore Nothing.

### Sintassi:

svc.AssertIsNothing(a: any, message: str = ""): bool

## AssertIsNull

Restituisce True quando A ha valore Null.

### Sintassi:

svc.AssertIsNull(a: any, message: str = ""): bool

## AssertLess

Restituisce True quando A è minore di B.

### Sintassi:

svc.AssertLess(a: any, b: any, message: str = ""): bool

Il confronto tra A e B presume quanto segue:

- I tipi di dati possibili sono String, Date o un tipo numerico.

- Entrambe le espressioni devono avere lo stesso VarType o entrambe devono essere numeriche.

- Il confronto tra stringhe distingue tra maiuscole e minuscole.

## AssertLessEqual

Restituisce True quando A è minore o uguale a B.

### Sintassi:

svc.AssertLessEqual(a: any, b: any, message: str = ""): bool

Il confronto tra A e B presume quanto segue:

- I tipi di dati possibili sono String, Date o un tipo numerico.

- Entrambe le espressioni devono avere lo stesso VarType o entrambe devono essere numeriche.

- Il confronto tra stringhe distingue tra maiuscole e minuscole.

## AssertLike

Restituisce True se la stringa A corrisponde al pattern indicato con dei caratteri jolly.

### Sintassi:

svc.AssertLike(a: any, pattern: str = "", message: str = ""): bool

Sono accettati i seguenti caratteri jolly:

- ? - Rappresenta qualunque carattere singolo.

- * - Rappresenta nessuno, uno o più caratteri.

## AssertNotAlmostEqual

Restituisce True se A e B sono valori numerici e non sono considerati vicini l'uno all'altro in base a una tolleranza relativa.

### Sintassi:

svc.AssertNotAlmostEqual(a: any, b: any, tolerance: double = 1E-09, message: str = ""): bool

Questa asserzione restituisce True se si verificano le due seguenti condizioni:

- A e B possono essere convertiti nel tipo Double.

- La differenza assoluta tra A e B divisa per il valore assoluto maggiore tra A e B è maggiore del valore di tolleranza specificato in tolerance.

## AssertNotEqual

Restituisce True se A e B non sono considerati uguali.

### Sintassi:

svc.AssertNotEqual(a: any, b: any, message: str = ""): bool

Questo metodo funziona sia per gli scalari che per le matrici. Per maggiori informazioni sul significato di uguaglianza in questa asserzione si leggano le istruzioni in AssertEqual.

## AssertNotIn

Restituisce True se A (una stringa) non viene trovata in B.

### Sintassi:

svc.AssertNotIn(a: any, b: any, message: str = ""): bool

Per maggiori informazioni sulle presunzioni di questo metodo si leggano le istruzioni in AssertIn.

## AssertNotInstance

Restituisce True se A non è un'istanza di uno specifico tipo di oggetto.

### Sintassi:

svc.AssertNotInstance(a: any, objecttype: str, message: str = ""): bool

Per maggiori informazioni sulle presunzioni di questo metodo si leggano le istruzioni in AssertIsInstance.

## AssertNotLike

Restituisce True se la stringa A non corrisponde a un pattern indicato con dei caratteri jolly.

### Sintassi:

svc.AssertNotLike(a: any, pattern: str = "", message: str = ""): bool

Per maggiori informazioni sulle presunzioni di questo metodo si leggano le istruzioni in AssertLike.

## AssertNotNothing

Restituisce True tranne quando A è un oggetto con valore Nothing.

### Sintassi:

svc.AssertNotNothing(a: any, message: str = ""): bool

## AssertNotNull

Restituisce True tranne quando A ha valore Null.

### Sintassi:

svc.AssertNotNull(a: any, message: str = ""): bool

## AssertNotRegex

Restituisce True quando A non è una stringa o non corrisponde all'espressione regolare specificata.

### Sintassi:

svc.AssertNotRegex(a: any, regex: str = "", message: str = ""): bool

Il confronto distingue tra maiuscole e minuscole.

## AssertRegex

Restituisce True se la stringa A corrisponde all'espressione regolare specificata.

### Sintassi:

svc.AssertRegex(a: any, regex: str = "", message: str = ""): bool

Il confronto distingue tra maiuscole e minuscole.

## AssertTrue

Restituisce True quando l'espressione A è di tipo Boolean e il suo valore è True.

### Sintassi:

svc.AssertTrue(a: any, message: str = ""): bool

## Fail

Causa forzatamente il fallimento di un test.

### Sintassi:

svc.Fail(message: str = "")

È possibile fornire un messaggio da riportare nella console.

## Log

Scrive il messaggio indicato in message nella console.

### Sintassi:

svc.Log(message: str = "")

È possibile fornire un messaggio da riportare nella console.

## ReportError

Visualizza una finestra di dialogo con un messaggio e i valori correnti delle proprietà del servizio Exception.

Questo metodo è comunemente usato nella sezione per la gestione delle eccezioni delle Sub che contiene il test case, che viene raggiunto quando un'asserzione fallisce o quando viene chiamato il metodo Fail.

### Sintassi:

svc.ReportError(message: str = "")

A seconda del valore della proprietà WhenAssertionFails l'esecuzione del testo può continuare o essere interrotta.

Quando si scrivono i test case è raccomandata l'inclusione di una chiamata al metodo ReportError nella sezione della gestione delle eccezioni all'interno della Sub.

Se la proprietà LongMessage è uguale a True, il messaggio specificato in message è seguito dal messaggio standard di descrizione dell'errore. In caso contrario viene visualizzato solo message.

## RunTest

Esegue la test suite completa implementata nel modulo specificato. Ogni test case viene eseguito indipendentemente dagli altri.

L'esecuzione di una test suite comprende:

1. L'esecuzione del metodo opzionale Setup presente nel modulo.

2. L'esecuzione per una volta di ciascun test case, senza un ordine specifico.

3. L'esecuzione del metodo opzionale TearDown presente nel modulo.

### Sintassi:

svc.RunTest(testsuite: str, testcasepattern: str = "", message: str = ""): int

L'argomento testcasepattern specifica un pattern costituito dai caratteri jolly "?" e "*" per selezionare quale test case eseguire. Il confronto non distingue tra maiuscole e minuscole.

Se in message è fornito un messaggio, questo viene scritto nella console all'avvio del test.

## SkipTest

Interrompe la test suite in esecuzione senza chiamare il metodo TearDown.

Saltare un test di solito ha senso nel metodo Setup quando non tutte le condizioni per l'esecuzione del test sono verificate.

È compito del metodo Setup uscire dalla Sub subito dopo la chiamata a SkipTest.

Se SkipTest viene chiamato all'interno di un test case, l'esecuzione della test suite viene interrotta e i restanti test case non sono eseguiti. Va ricordato che l'ordine in cui sono eseguiti i test case, presenti nella test suite, è arbitrario.

### Sintassi:

svc.SkipTest(message: str = "")

Se in message è fornito un messaggio, questo viene scritto nella console.

Argomenti correlati

Servizio ScriptForge.Exception