Obsah

# SFUnitTests.UnitTest

Služba UnitTest nabízí prostředí pro automatizaci jednotkových testů v jazyce Basic, a to včetně možností:

- Agregovat testovací případy do testovacích sad a jednotkových testů.

- Sdílet mezi testovacími případy kód spouštěný při inicializaci a ukončování testů.

- Vypisovat výsledky testů pomocí Console.

Jak jednotkové testy, tak testovaný kód musí být napsány v jazyce Basic. Testovaný kód však může volat funkce napsané v jiných jazycích.

Služba UnitTest není k dispozici pro skripty Pythonu.

## Definice

### Testovací případ

Testovací případ je základní samostatná jednotka testování. Kontroluje, zda má určitá sada vstupů za následek příslušnou odpověď.

Ve službě UnitTest je testovací případ představován jedním podprogramem Sub, jehož název začíná společnou předponou (výchozí je "Test_").

Testovací případ selže, pokud některá z metod AssertX vrátí False.

### Testovací sada

Testovací sada je soubor testovacích případů, který by se měl spouštět společně.

Všechny testovací případy jedné sady jsou uloženy v jediném modulu Basicu.

V testovací sadě mohou být implementovány metody SetUp a TearDown, které budou připraveny pro testovací případy ve stejném modulu.

### Jednotkový test

Celý jednotkový test sestává ze skupiny testovacích sad, které se nachází v téže knihovně Basicu.

## Volání služby

Před používáním služby UnitTest je nutné načíst či naimportovat knihovnu ScriptForge pomocí:

• V makrech Basicu je nutné načíst knihovnu ScriptForge následujícím příkazem:
GlobalScope.BasicLibraries.loadLibrary("ScriptForge")
• Ve skriptech Pythonu je nezbytné import z modulu scriptforge:
from scriptforge import CreateScriptService

### Jednoduchý režim

V jednoduchém režimu je služba inicializována, aby mohly být volány funkce AssertX bez nutnosti vytvářet hierarchii testovacích sad a případů.

V tomto režimu je služba inicializována v rámci testovacího případu, jak ukazuje následující příklad:

        Sub SimpleTest
            On Local Error GoTo CatchError
            Dim myTest As Variant
            myTest = CreateScriptService("UnitTest")
            ' Několik primitivních testů
            myTest.AssertEqual(1 + 1, 2)
            myTest.AssertEqual(1 - 1, 0)
            MsgBox("Všechny testy úspěšné")
            Exit Sub
        CatchError:
            myTest.ReportError("Test selhal")
        End Sub

Pokud v tomto příkladu jakékoliv volání AssertEqual selže, interpret přejde na návěstí CatchError a ohlásí chybu zavoláním metody ReportError.

### Úplný režim

V úplném režimu je služba vytvořena mimo testovací kód, a všechny testy jsou v rámci jedné knihovny uspořádány do testovacích případů a sad.

V následujícím příkladu je vytvořena instance služby UnitTest, jejíž testy jsou umístěny v aktuálním dokumentu (ThisComponent) v knihovně "Tests".

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

### Minimální příklad v úplném režimu

Předpokládejme, že soubor ODS obsahuje v knihovně "Standard" modul s názvem "MathUtils" a následujícím kódem:

        ' Kód v modulu Standard.MathUtils
        Function Sum(a, b) As Double
            Sum = a + b
        End Function

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

Chcete-li vytvořit úplnou testovací sadu, je vhodné v souboru vytvořit novou knihovnu pojmenovanou "Tests" s jediným modulem "AllTests", který obsahuje následující kód:

        ' Kód v modulu 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)
            ' Přípravný kód spouštěný před prvním testovacím případem
            Dim exc As Variant
            exc = CreateScriptService("Exception")
            exc.Console(Modal := False)
        End Sub

        Sub TearDown(test)
            ' Volitelný kód s čištěním, volaný po posledním testovacím případu
        End Sub

        Sub Test_Sum(test)
            On Local Error GoTo CatchError
            test.AssertEqual(Sum(1, 1), 2, "Součet dvou kladných celých čísel")
            test.AssertEqual(Sum(-10, 20), 10, "Součet záporného a kladného celého čísla")
            test.AssertEqual(Sum(1.5, 1), 2.5, "Součet desetinného a celého čísla")
            Exit Sub
        CatchError:
            test.ReportError("Metoda pro součet nefunguje")
        End Sub

        Sub Test_Multiply(test)
            On Local Error GoTo CatchError
            test.AssertEqual(Multiply(2, 2), 4, "Násobek dvou kladných celých čísel")
            test.AssertEqual(Multiply(-4, 2), -8, "Násobek záporného a kladného celého čísla")
            test.AssertEqual(Multiply(1.5, 3), 4.5, "Násobek desetinného a celého čísla")
            Exit Sub
        CatchError:
            test.ReportError("Metoda pro násobení nefunguje")
        End Sub

Výše uvedená testovací sada sestává ze dvou testovacích případů: Test_Sum and Test_Multiply. Všechny testy jednoduše spustíte zavoláním metody Main z modulu "AllTests".

Jako výchozí výstup pro výsledky testu slouží Console ze služby Exception. Po spuštění výše uvedeného příkladu se v konzoli zobrazí následující výstup:

        ' 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)

Jestliže během těchto testů selže jakákoliv z metod AssertEqual, v konzoli přibude zpráva o chybě.

## Vlastnosti

Název | Pouze pro čtení | Typ | Popis
--- | --- | --- | ---
LongMessage | ne | Boolean | Je-li nastaveno na True (výchozí), v konzoli se kromě zprávy zadané autorem testu zobrazí také standardní zprávy. Je-li False, zobrazí se pouze zpráva určená autorem testu.
ReturnCode | ano | Integer | Hodnota vrácená metodou RunTest po ukončení jednotkového testu. Seznam možných hodnot: 0 - Test skončil bez chyb nebo ještě nebyl spuštěn. 1 - Některá kontrola v testovacím případu vrátila False. 2 - Metodou Setup nebo některým testovacím případem byla zavolána metoda SkipTest. 3 - Abnormální ukončení testu.
Verbose | ne | Boolean | Je-li nastaveno na True, do konzole se vypíšou všechny kontroly (ať už úspěšné, či nikoliv). Je-li False (výchozí), vypíšou se pouze kontroly, které selhaly.
WhenAssertionFails | ne | Integer | Určuje, co se stane při selhání kontroly. Seznam možných hodnot: 0 - Selhání je ignorováno a pokračuje se v běhu testu. 1 - V aktuální testovací sadě se zavolá metoda TearDown z modulu a spustí se následující sada (výchozí v úplném režimu). 2 - Okamžité zastavení (výchozí v jednoduchém režimu).

Seznam metod služby 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

## Argumenty metod AssertX

Všechny kontroly testují jeden nebo dva výrazy, které jsou ve zbývající části této stránky označovány jako A and B. Vždy se jedná o první argument či první dva argumenty metody AssertX.

Všechny metody AssertX mají argument message určující vlastní zprávu týkající se kontroly a vypisovanou do konzole, Jako výchozí se použije prázdný řetězec. Tento argument se nachází vždy na posledním místě.

Některé metody AssertX mají rovněž dodatečné argumenty, jak je uvedeno u popisu jejich syntaxe níže.

## AssertAlmostEqual

Vrátí True, pokud jsou A a B číselné hodnoty sobě blízké, a to za předpokladu určité relativní tolerance.

### Syntaxe:

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

Tato kontrola vrátí True, pokud jsou splněny obě následující podmínky:

- A a B je možné převést na typ Double.

- Absolutní rozdíl mezi A a B dělený větší z hodnot A a B je menší než hodnota uvedená v argumentu tolerance.

## AssertEqual

Vrátí True, pokud jsou hodnoty A a B považovány za sobě rovné.

### Syntaxe:

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

Pokud jsou A a B skalární hodnoty, True se vrátí v případě, že:

- Oba výrazy mají stejný typ VarType nebo jsou oba číselné.

- Booleovské a číselné hodnoty jsou porovnávány operátorem =.

- Řetězce jsou porovnávány vestavěnou funkcí StrComp. U porovnání se rozlišuje velikost písmen.

- Data a časy jsou porovnávány s přesností na sekundy.

- Null, Empty a Nothing se nerovnají, avšak AssertEqual(Nothing, Nothing) vrátí True.

- Objekty UNO jsou porovnávány pomocí vestavěné metody EqualUnoObjects.

- Objekty Basicu si nikdy rovny nejsou.

Pokud jsou A a B pole, True se vrátí v případě, že:

- Obě pole mají tentýž počet rozměrů (až do 2 rozměrů) a jejich dolní a horní meze jsou pro všechny rozměry stejné.

- Všechny prvky v obou polích si jsou vzájemně rovny.

- Dvě prázdná pole se považují za sobě rovná.

## AssertFalse

Vrátí True, pokud je typ A Boolean a jeho hodnota je False.

### Syntaxe:

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

## AssertGreater

Vrátí True, pokud je A větší než B.

### Syntaxe:

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

Při porovnávání A a B platí následující:

- Relevantní datové typy jsou String, Date nebo číselný.

- Oba výrazy musí mít stejný typ VarType nebo musí být oba číselné.

- Při porovnávání řetězců se rozlišuje velikost písmen.

## AssertGreaterEqual

Vrátí True, pokud je A větší nebo rovno B.

### Syntaxe:

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

Při porovnávání A a B platí následující:

- Relevantní datové typy jsou String, Date nebo číselný.

- Oba výrazy musí mít stejný typ VarType nebo musí být oba číselné.

- Při porovnávání řetězců se rozlišuje velikost písmen.

## AssertIn

Vrátí True, pokud je A nalezeno v B.

### Syntaxe:

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

Tato kontrola předpokládá následující:

- Výraz B může být jednorozměrné pole, objekt Dictionary z knihovny ScriptForge nebo řetězec.

- Pokud je výraz B jednorozměrné pole, výraz A může být datum nebo číselná hodnota.

- Pokud je výraz B objekt Dictionary z knihovny ScriptForge, bude řetězec A hledat mezi klíči slovníku B.

- Při porovnávání řetězců se rozlišuje velikost písmen.

## AssertIsInstance

Vrátí True, pokud je A instancí objektu zadaného typu. Tento typ je uveden jako řetězec s názvem typu.

### Syntaxe:

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

Výraz A může být některý z následujících:

- Objekt knihovny ScriptForge. V takovém případě je argument objecttype řetězec, například "DICTIONARY", "calc", "Dialog" atd.

- Objekt UNO. V takovém případě musí být argument objecttype řetězec totožný s hodnotou, kterou vrátí metoda SF_Session.UnoObjectType().

- Pole. V takovém případě se předpokládá, že argument objecttype bude "array".

- Jakákoliv jiná proměnná (ani Object, ani Array). V takovém případě je argument objecttype řetězec odpovídající hodnotě, kterou vrátí vetavěná funkce TypeName.

## AssertIsNothing

Vrátí True, pokud je A objekt, který má hodnotu Nothing.

### Syntaxe:

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

## AssertIsNull

Vrátí True, pokud má A hodnotu Null.

### Syntaxe:

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

## AssertLess

Vrátí True, pokud je A menší než B.

### Syntaxe:

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

Při porovnávání A a B platí následující:

- Relevantní datové typy jsou String, Date nebo číselný.

- Oba výrazy musí mít stejný typ VarType nebo musí být oba číselné.

- Při porovnávání řetězců se rozlišuje velikost písmen.

## AssertLessEqual

Vrátí True, pokud je A menší nebo rovno B.

### Syntaxe:

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

Při porovnávání A a B platí následující:

- Relevantní datové typy jsou String, Date nebo číselný.

- Oba výrazy musí mít stejný typ VarType nebo musí být oba číselné.

- Při porovnávání řetězců se rozlišuje velikost písmen.

## AssertLike

Vrátí True, pokud řetězec A odpovídá zadanému vzorku obsahujícímu zástupné znaky.

### Syntaxe:

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

Je možné použít následující zástupné znaky:

- ? - Představuje libovolný jediný znak.

- * - Představuje žádný, jeden či více znaků.

## AssertNotAlmostEqual

Vrátí True, pokud jsou A a B číselné hodnoty a nejsou považovány za sobě blízké, a to za předpokladu určité relativní tolerance.

### Syntaxe:

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

Tato kontrola vrátí True, pokud jsou splněny obě následující podmínky:

- A a B je možné převést na typ Double.

- Absolutní rozdíl mezi A a B dělený větší z hodnot A a B je větší než hodnota uvedená v argumentu tolerance.

## AssertNotEqual

Vrátí True, pokud hodnoty A a B nejsou považovány za sobě rovné.

### Syntaxe:

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

Tato metoda funguje pro skalární hodnoty i pole. Podrobnosti o tom, co znamená u této kontroly rovnost, naleznete v popisu metody AssertEqual.

## AssertNotIn

Vrátí True, pokud A (řetězec) není nalezeno v B.

### Syntaxe:

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

Podrobnosti o předpokladech této metody naleznete v popisu metody AssertIn.

## AssertNotInstance

Vrátí True, pokud A není instancí objektu zadaného typu.

### Syntaxe:

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

Podrobnosti o předpokladech této metody naleznete v popisu metody AssertIsInstance.

## AssertNotLike

Vrátí True, pokud řetězec A neodpovídá zadanému vzorku obsahujícímu zástupné znaky.

### Syntaxe:

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

Podrobnosti o předpokladech této metody naleznete v popisu metody AssertLike.

## AssertNotNothing

Vrátí True s výjimkou případu, že A je objekt, který má hodnotu Nothing.

### Syntaxe:

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

## AssertNotNull

Vrátí True s výjimkou případu, že A má hodnotu Null.

### Syntaxe:

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

## AssertNotRegex

Vrátí True, pokud A není řetězec nebo neodpovídá Zadanému regulárnímu výrazu.

### Syntaxe:

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

Při porovnávání se rozlišuje velikost písmen.

## AssertRegex

Vrátí True, pokud řetězec A odpovídá zadanému regulárnímu výrazu.

### Syntaxe:

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

Při porovnávání se rozlišuje velikost písmen.

## AssertTrue

Vrátí True, pokud je typ A Boolean a jeho hodnota je True.

### Syntaxe:

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

## Fail

Vynutí selhání testu.

### Syntaxe:

svc.Fail(message: str = "")

Je možné zadat zprávu, která se zobrazí v konzoli.

## Log

Vypíše zprávu určenou argumentem message do konzole.

### Syntaxe:

svc.Log(message: str = "")

Je možné zadat zprávu, která se zobrazí v konzoli.

## ReportError

Zobrazí dialog se zprávou a aktuální hodnotou vlastnosti služby Exception.

Tato metoda se obvykle používá v té části podprogramu Sub obsahujícího testovací případ, která zpracovává výjimky a která je spuštěna, pokud selže kontrola nebo je zavolána metoda Fail.

### Syntaxe:

svc.ReportError(message: str = "")

V závislosti na hodnotě vlastnosti WhenAssertionFails může test pokračovat, nebo být přerušen.

V testovacích případech je doporučeno metodu ReportError volat v té části podprogramu Sub, která zpracovává výjimky.

Pokud je vlastnost LongMessage rovna True, argument message bude ve výpisu doplněn standardní chybovou zprávou. V opačném případě se zobrazí pouze message.

## RunTest

Spustí kompletní testovací sadu implementovanou v zadaném modulu. Každý testovací případ je spuštěn nezávisle na ostatních.

Spuštění testovací sady sestává z:

1. Provedení volitené metody Setup umístěné v modulu.

2. Jedno spuštění každého testovací případu, přitom není stanoveno jejich pořadí.

3. Provedení volitené metody TearDown umístěné v modulu.

### Syntaxe:

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

Argument testcasepattern udává vzorek se zástupnými znaky "?" a "*", podle kterého budou vybrány spuštěné testovací případy. Při porovnávání se nerozlišuje velikost písmen.

Je-li zadán argument message, je zpráva z něho vypsána do konzole na úvod spouštění testů.

## SkipTest

Přeruší běžící testovací sadu, aniž by byla zavolána metoda TearDown.

Přerušit test má obvykle smysl v metodě Setup, pokud nejsou splněny podmínky k tomu, aby mohl být spuštěn.

Metoda Setup poté musí zajistit, aby se zavolání metody SkipTest ukončil podprogram Sub.

Jestliže je metoda SkipTest zavolána z testovacího případu, provádění testovací sady se přeruší a zbývající testovací případy se nespustí. Je třeba mít na paměti, že pořadí, v jakém jsou testovací případy v rámci sady spouštěny, je nahodilé.

### Syntaxe:

svc.SkipTest(message: str = "")

Je-li zadán argument message, je zpráva z něho vypsána do konzole.

Související témata

Služba ScriptForge.Exception