Servizio SFUnitTests.UnitTest

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

note

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.


warning

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.

Invocare il servizio

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

note

‚ÄĘ 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:

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:

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

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:

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:

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:

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:

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:

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:

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:

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:

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.

Sosteneteci!