Mit diesem Formular können Sie fehlende, unklare oder fehlerhafte Inhalte in der Dokumentation melden und Verbesserungsvorschläge machen. Ihr Feedback hilft uns, die Qualität und Vollständigkeit kontinuierlich zu verbessern.
Testautomatisierung in Extensions
In Kundenprojekten skalieren Fehler im Quellcode grundsätzlich anders, als im Standardcode von Business Central oder in Apps wie unitop. Dies liegt an der Anzahl der potentiellen Installationen (in der Regel genau eine) sowie der typischerweise vergleichsweise geringen Prozesstiefe vieler Individualanpassungen.
Daher gelten für automatisierte Tests in Projekten folgende Leitlinien:
- Tests müssen wirtschaftlich sein
- Tests müssen Kernprozesse absichern
- Tests können Nebenprozesse absichern, wenn sie dabei wirtschaftlich sind
Ein Test ist dann wirtschaftlich, wenn eine der folgenden Bedingungen erfüllt ist. Es ist in der Praxis oft so, dass auf eine betrachtete Funktionalität mehrere Aspekte zutreffen:
- Test-driven Development beschleunigt die Entwicklungszeit, der oder die Tests entstehen ohnehin bei der primären Entwicklung. Dies ist oft der Fall in Funktionalitäten,
- für die komplexe Datenaufbereitung zum manuellen Testen erforderlich ist
- oder bei denen aufgrund hoher Komplexität die Umsetzung mit Unsicherheit behaftet ist
- Die Funktionalität erstreckt sich über viele Schritte und Komponenten, deren Integration sicherzustellen aufwändige Nacharbeiten verhindert. Dies ist oft der Fall, wenn die einzelnen Bestandteile eines Prozesses eigenständige Lebenszyklen haben und ohne automatisierten Test nie klar ist, ob der Prozess (noch) funktioniert.
- Die Funktionalität hat sich als fehleranfällig erwiesen. Mit dem Bugfixing können zugleich durch den automatisierten Test zukünftige Nacharbeiten eingedämmt werden.
Kernprozesse sind die Prozesse des Kunden, bei dessen Ausfall er sein Kerngeschäft nicht abwickeln kann. Oft fallen diese Prozesse ohnehin auch in die Definition der Wirtschaftlichkeit.
Hinweis
Aktuell sind automatisierte Tests für Kundenprojekte empfohlen, aber nicht verpflichtend vorgeschrieben. Die Qualitätssicherung kann auch durch manuelle Tests erfolgen. Im Projekt legt die Entwicklungsleitung oder der zuständige Lead Developer die Nutzung fest.
Technische Organisation
Tests für eine Extension werden in eigenen Extensions bereitgestellt. Die Test Extension wird wie die produktiven Extensions in einem eigenen Ordner im Workspace bereitgestellt und hat dort folgenden Ordnernamen:
[NAME DER EXTENSION][ ]Test
Also z. B.: Meine Extension Test
Die Test Extension folgt allen sonstigen Vorgaben zur Struktur. Zuzüglich dazu hat sie eine Abhängigkeit von der zu testenden Extension und normalerweise keine weiteren Abhängigkeiten. Eine Ausnahme stellen Abhängigkeiten zu Test Apps von Microsoft und ggf. unitop dar - diese sind immer erlaubt.
Aufbau von Tests
Tests werden in Codeunits geschrieben und folgen dem Feature/Scenario/Given/When/Then-Schema.
// [Feature]beschreibt das Feature für das die gesamte Test Codeunit ausgelegt ist.// [Scenario]beschreibt das konkrete Szenario in der einzelnen Testfunktion// [Given]beschreibt (ggf. in mehreren Kommentaren) den Ausgangszustand des Szenarios. Es folgen dann die Funktionen die den Zustand dann herstellen.// [When]beschreibt (ggf. in mehreren Kommentaren) den Ablauf des Szenarios. Es folgen jeweils die konkreten Funktionen.// [Then]beschreibt (ggf. in mehreren Kommentaren) das erwartete Ergebnis. Es folgen jeweils die Prüfungen ob der erwartete Zustand erreicht wurde.
Anbei ein Beispiel aus unitop:
codeunit 50101 "GOB Webservice Management Test"
{
// [FEATURE] [GOB Webservice Management]
Subtype = Test;
trigger OnRun()
begin
end;
var
Manager: Codeunit "GOB Webservice Management";
Mock: Codeunit "GOB Webservice Comm. Mock";
ResponseGen: Codeunit "GOB Webservice Mock Resp. Gen.";
ExpCodeTxt: Label '1234';
ExpMsgTxt: Label 'Error';
ExpectedResponse: Text;
[Test]
procedure TestTrialIsCreated()
var
Assert: Codeunit Assert;
CustomerId: Text;
State: Boolean;
ExpCustIdTxt: Label 'E68C256B-EDB8-4E11-B070-FB56FCD9D260';
begin
// [Scenario] Start a trial period for a feature app
// [Given] The trial is started successful
Setup();
ResponseGen.CreateTrialSuccessResponse(ExpCustIdTxt, ExpectedResponse);
Mock.AddResponseWithContent(Mock.StartTrialUrl(), ExpectedResponse, 200, true);
// [When] CreateTrial is called
State := Manager.CreateTrial('3a765acd-18ca-4810-a0de-e48aaa756792', '40716111-e229-4294-abd3-8845c0a88568', true, CustomerId);
// [Then] CreateTrial should return true
Assert.IsTrue(State, 'Request failed');
// [Then] CreateTrial should write the customer id contained in the response to CustomerId
Assert.AreEqual(ExpCustIdTxt, CustomerId, 'CustomerId not set correctly');
// [Then] LastHttpStatusCode should be set
Assert.AreEqual(200, Manager.GetLastHttpStatusCode(), 'Http status not set correctly');
end;