SOG-Helpcenter Logo SOG Business - Software

Entwicklung von Unit Tests für Cobol-Module


Um für Cobol-Programme, die auf CSharp umgesetzt sind, Unit Tests zu entwickeln, kann prinzipiell genauso vorgegangen werden, wie bei der Entwicklung von Unit Tests für herkömmliche CSharp-Klassen. Für Cobol-Programme, die nicht reine Batch-Programme sind sondern im Programmablauf mit ActiveSkin kommunizieren um Eingaben über eine Maske entgegegen zu nehmen, ist es nicht ohne weiteres möglich, einen Unit Test zu entwickeln. Hier muss im Unit Test die Komunikation mit ActiveSkin simuliert werden. Es bietet sich dabei auch an, an diesen Stellen die Test-Annahmen zu prüfen, da es im Unit Test meistens nicht möglich ist, direkt auf Member, Eigenschaften oder Methoden des Cobol-Programms zuzugreifen.
Ein so aufgebauter Unit Test verhält sich dann ähnlich wie ein Oberflächentest.

Die Klasse TestCaller



SOG.ERP.Testlib.CobRtm.TestCaller


Diese Klasse sollte als Basisklasse für die Implementation einer eigenen Caller-Klasse verwendet werden. Es bietet sich hier an, eine Funktion Call() zu implementieren, die alle für den Programmaufruf notwendigen Parameter übergeben bekommt und intern die Methode GetCaller() der Basisklasse aufruft, um den eigentlichen Cobol-Caller zu erzeugen.

Beispiel: Caller für das p941 in SOG.ERP.Modules.CobRtm.p941.Test.Helper.P941Caller


public class P941Caller : TestCaller
{
    protected override string Name => "p941_mod";

    public void Call(p941use_copy p941Use = null)
    {
        par_copy par = new par_copy();
        par.firmpar.LoadFrom(SOGERPSession.Current.GetFirmenparameter());
        par.sachbearbeiter.LoadFrom(SOGERPSession.Current.GetSachbearbeiter());

        if (p941Use == null)
        {
            p941Use = new p941use_copy();
            p941Use.Satz.Initialize();
        }

        SOGCSDATA csdat = new SOGCSDATA();

        CobCaller caller = GetCaller();
        caller.Call(null, csdat, par, p941Use);
    }
}


Die Klasse TestCallerBuilder<T>



SOG.ERP.Testlib.CobRtm.TestCallerBuilder<T>


Diese Klasse wird verwendet, um im Unit Test die TestCaller-Instanz (siehe oben) zu erzeugen. Sie stellt über die Eigenschaft Queue eine Warteschlange zur Verfügung, über die alle vom Programm angeforderten Maskeneingaben als simulierte Eingaben in der richtigen Reihenfolge registriert werden müssen. Nach Simulation der Maskeneingaben kann über Build() der TestCaller erzeugt und anschließend aufgerufen werden.

Über die Eigenschaft Register der Eigenschaft Queue stehen Methoden zur Verfügung, mit denen Aktionen registriert werden, die bei der Anforderung einer Maskeneingabe als Simulation ausgeführt werden sollen.

Beispiel für die Definition eines einfachen UnitTests für das p941:

Über die Methode VRead<TModul,TMask> wird angegeben, für welches Modul (TModul) und für welche Maske (TMask) die Maskeneingabe erwartet wird. Über die Methode WithAction() wird dann die Aktion definiert, die als Simulation der Eingabe durchgeführt werden soll. Hier kann eine anonyme Methode verwendet werden, die als einzigen Parameter eine Instanz vom Typ ExecutionQueueContext<TModul,TMask> erwartet. Über diesen Parameter kann dann direkt auf die aktuellen Instanzen vom Typ TModul (Eigenschaft Module) und TMask (Eigenschaft Mask) zugegriffen werden.

Es müssen im Unit Test alle Anforderungen für Maskeneingaben in der richtigen Reihenfolge angegeben werden. Fehlende Anforderungen oder Anforderungen für eine Modul/Masken-Kombination, die nicht definiert ist, führen zu einem fehlgeschlagenen Testlauf.


public void AnwahlArtikel()
{
    TestCallerBuilder<P941Caller> builder = new TestCallerBuilder<P941Caller>();

    // Aufruf p841
    builder.Queue.Register.VRead<p941_mod, p941v1_msk>().WithAction(context =>
    {
        // Artikel-ID eingeben und mit "fertig" auslösen
        context.Mask.m_art.Value = 22009;
        context.Module.VSkCode.Value = 143;
    });

    builder.Queue.Register.VScript<p941_mod, p941v1_msk>("p941v1Script").DefaultAction();

    // Artikel angelesen
    builder.Queue.Register.VRead<p941a_mod, p941v1_msk>().WithAction(context =>
    {
        // Prüfen, ob jetzt "TISCHVASE" im Feld "mcart" steht
        context.Mask.m_mcart.Value.Should().Be("TISCHVASE");
        // Mit "fertig" auslösen
        context.Module.VSkCode.Value = 143;
    });

    builder.Queue.Register.VScript<p941z_mod, p941v1_msk>("p941v1Script").DefaultAction();

    // Programm mit "beenden" verlassen
    builder.Queue.Register.VRead<p941_mod, p941v1_msk>().ExecuteSoftkey(2900);

    P941Caller caller = builder.Build();
    caller.Call();
}


Weitere Klassen mit Beispielen für Unit Tests:

SOG.ERP.Modules.CobRtm.p941.Test.p941_modTest
SOG.ERP.Modules.CobRtm.p941.Test.Zwangsfeldpruefungen


UnitTestRecorder


Über den Kommandozeilenparameter -unittestrecorder kann in ActiveSkin eine Funktion zur Protokollierung der Anforderungen für Maskeneingaben aus Cobol-Programmen heraus aktiviert werden. Es entsteht bei der Ausführung von Cobol-Programmen in ActiveSkin im Verzeichnis UnitTestRecorder unterhalb des sogtemp-Verzeichnisses eine Protokolldatei, in der alle notwendigen Informationen zur Definition eines Unit Tests protokolliert werden.

Beispielausgabe:


15.09.2016-11:20:31:442 p941_mod - p941v1_msk VClear
15.09.2016-11:20:31:810 p941_mod - p941v1_msk VRead
15.09.2016-11:20:38:970 p941_mod - p941v1_msk m_art: 0 => 22009
15.09.2016-11:20:38:974 p941_mod - p941v1_msk VSkCode: 143
15.09.2016-11:20:39:028 p941_mod - p941v1_msk VScript: p941v1Script
15.09.2016-11:20:42:529 p941a_mod - p941v1_msk VRead
15.09.2016-11:20:45:787 p941a_mod - p941v1_msk VSkCode: 143
15.09.2016-11:20:49:729 p941z_mod - p941v1_msk VScript: p941v1Script
15.09.2016-11:20:49:914 p941_mod - p941v1_msk VRead
15.09.2016-11:20:51:627 p941_mod - p941v1_msk VSkCode: 2900