Color scheme: Dark
You are here: start » de » Dokumentation » Werkzeuge für Microsoft Access » WKL Office SDK » how-to » Vorgehen: Eine Anwendung testen

Vorgehen: Eine Anwendung testen

Eine Access-Anwendung mit Tests prüfen, die in VBA geschrieben sind, und sie von der Befehlszeile oder einem CI-Server aus ausführen – ohne dass jemand am Desktop tippt oder klickt.

Lösungsüberblick

  • Die Projektdatei nennt eine Testfunktion (<Test>), die die Namen der Testprozeduren zurückgibt.
  • Eine Testprozedur ist ein öffentliches Sub ohne Argumente in einem Standardmodul der Quellen. Sie steuert die Anwendung im Code: Sie öffnet Formulare mit DoCmd.OpenForm, ruft die Befehle der Anwendung auf, liest Steuerelemente und Daten und prüft die Ergebnisse mit WklTest.Check.
  • Die Anwendung lässt die Tests ihre Dialoge beantworten: Vor jedem MsgBox, InputBox oder Dateidialog fragt sie WklTest.Answer. Außerhalb eines Testlaufs ist die Antwort Empty, und der Dialog erscheint wie bisher.
  • wkl-office test baut das Projekt und führt dann jede Testprozedur einzeln in einem verborgenen Access aus, in einer Kopie der Datenbank. Es gibt eine Zeile je Prüfung aus und endet mit einem Exitcode; im Arbeitsordner liegt ein JUnit-Bericht.
  • PowerShell startet und wertet aus, VBA steuert. Ein Skript oder CI-Server ruft wkl-office test und wkl-office call auf und liest Exitcode, JSON-Ausgabe und Berichte. Eine Schnittstelle, mit der ein Skript ein laufendes Access über COM steuert (Formular öffnen, Befehl auslösen, Steuerelement lesen), gibt es nicht; das tun die Testprozeduren in VBA.

Das SDK fügt das Modul WklTest in jeden Build eines Projekts ein, das eine Testfunktion nennt. Die Anwendung erhält keinen neuen Verweis.

Umsetzung

1. Die Testfunktion in der Projektdatei nennen.

<Project>
  <PropertyGroup>
    <SchemaVersion>2</SchemaVersion>
    <AssemblyName>Orders</AssemblyName>
    <Test>AllTests</Test>
  </PropertyGroup>
</Project>

2. Die Anwendung über WklTest.Answer fragen lassen. Eine Funktion je Dialogart genügt; der Rest der Anwendung ruft sie statt MsgBox auf:

' A question to the user; in a test run the answer the test expects instead of the message box.
Public Function AskUser(ByVal Prompt As String, ByVal Buttons As VbMsgBoxStyle) As VbMsgBoxResult
    Dim reply As Variant
 
    reply = WklTest.Answer(WklTest.KindMessage, Prompt)
    If IsEmpty(reply) Then
        AskUser = MsgBox(Prompt, Buttons)
    ElseIf IsNumeric(reply) Then
        AskUser = CLng(reply)
    Else
        AskUser = vbCancel
    End If
End Function

3. Die Testprozeduren schreiben, in einem Standardmodul der Quellen, zum Beispiel source\modules\basTests.bas:

Option Compare Database
Option Explicit
 
' The test procedures wkl-office test runs, in this order.
Public Function AllTests() As Variant
    AllTests = Array("Orders_Total", "Orders_DeleteAsks")
End Function
 
Public Sub Orders_Total()
    WklTest.Check "total of two lines", OrderTotal(Array(10, 5)) = 15, "total was " & OrderTotal(Array(10, 5))
End Sub
 
Public Sub Orders_DeleteAsks()
    WklTest.Expect WklTest.KindMessage, "Delete order *", vbNo
    DeleteOrder 42
    WklTest.Check "order 42 kept after No", DCount("*", "tblOrder", "OrderId = 42") = 1, "order 42 was deleted"
End Sub

Eine Testprozedur braucht keine Fehlerbehandlung: Ein Laufzeitfehler, den sie nicht behandelt, wird als fehlgeschlagene Zeile mit dem Text des Fehlers gemeldet, und die nächste Prozedur läuft.

4. Die Tests ausführen.

wkl-office test Orders.acproj
wkl-office test Orders.acproj --only Orders_DeleteAsks
wkl-office test Orders.acproj -c Release -t accde --json
OK   Orders_Total: total of two lines
FAIL Orders_DeleteAsks: order 42 kept after No :: order 42 was deleted
1 OK, 1 FAIL (2 Testprozeduren)

Exitcode 0 bedeutet, dass jede Prüfung bestanden wurde, 15, dass eine Prüfung fehlschlug. Die übrigen Codes und die JSON-Ausgabe stehen in der Befehlszeilenreferenz.

Ist die Datenbank in Access geöffnet, kann der Build sie nicht ersetzen; --no-build testet dann die zuletzt gebaute Datenbank, hier im Terminal des Add-Ins:

Die Registerkarte Terminal des Arbeitsbereichs im Projektordner Kunden: der Befehl wkl-office test Kunden.acproj --no-build, zwei Zeilen OK für Laender_Stammdaten (fünf Länder aus den Stammdaten) und Kunden_UmsatzJeLand (Umsatz der zwei Kunden aus Slowenien) und die Zusammenfassung 2 OK, 0 FAIL (2 Testprozeduren)

Ein Testlauf mit zwei Testprozeduren: eine Zeile je Prüfung, dann die Zusammenfassung.

Im VBA-Editor führt das Menü Tests des Add-Ins dieselben Testprozeduren auf der in Access geöffneten Datenbank aus, ohne den Editor zu verlassen; eine fehlgeschlagene Prüfung öffnet ihre Testprozedur aus dem Bereich Probleme (siehe Access-Add-In verwenden).

Aus PowerShell und CI ausführen

Mit --json gibt wkl-office test das Ergebnis als ein JSON-Objekt aus (Felder: JSON-Ausgabe); der Exitcode sagt, wie der Lauf endete. Das folgende Skript ist ein CI-Schritt im Projektordner: Es testet die ACCDB und die ACCDE, legt vor jedem Lauf die Eingabedateien aus fixtures in den Arbeitsordner, gibt die fehlgeschlagenen Prüfungen aus und endet mit dem ersten Exitcode, der nicht 0 ist.

# Runs the tests of a project as a CI step: ACCDB and ACCDE, input files in the work folder, failed checks listed.
param([string] $Project = 'Orders.acproj', [string] $Results = 'test-results')
 
$worst = 0
foreach ($target in 'accdb', 'accde') {
    $work = Join-Path $Results $target
    New-Item -ItemType Directory $work -Force | Out-Null
    Copy-Item fixtures\* $work -Recurse -Force    # the tests read them from CurrentProject.Path
 
    $run = wkl-office test $Project -t $target --work $work --json | ConvertFrom-Json
    $code = $LASTEXITCODE
    switch ($code) {
        0       { "${target}: $($run.passed) checks passed" }
        15      { "${target}: $($run.failed) checks failed"
                  $run.checks | Where-Object { -not $_.ok } | ForEach-Object { "  FAIL $($_.test): $($_.name) :: $($_.message)" } }
        13      { "${target}: time limit: $($run.problem)" }
        16      { "${target}: Access ended: $($run.problem)" }
        default { "${target}: no test run (exit $code): $($run.problem)" }
    }
    if ($code -ne 0 -and $worst -eq 0) { $worst = $code }
}
exit $worst

Danach enthält jeder Arbeitsordner die Kopie der Datenbank, wkl-test-run.jsonl und den JUnit-Bericht wkl-test-report.xml; der CI-Server archiviert den Ordner test-results. Hielt ein Lauf an (Exitcode 13 oder 16), stehen die bis dahin geschriebenen Prüfungen in wkl-test-run.jsonl, eine JSON-Zeile je Eintrag; Prüfungen haben kind gleich check:

Get-Content test-results\accdb\wkl-test-run.jsonl | ForEach-Object { $_ | ConvertFrom-Json } |
    Where-Object { $_.kind -eq 'check' -and -not $_.ok } | Format-Table test, name, message

Verhalten, das nur außerhalb eines Testlaufs gilt (WklTest.InRun() ist False), prüft das Skript mit call im selben Arbeitsordner. call ersetzt dort die Kopie der Datenbank durch eine neue Kopie des Build-Ergebnisses; die übrigen Dateien bleiben, und {work} in einem Argument steht für den Arbeitsordner:

$text = wkl-office call Orders.acproj OrderNumberText 42 --work test-results\accdb
if ($LASTEXITCODE -ne 0 -or $text -ne 'A-00042') { throw "OrderNumberText returned '$text' (exit $LASTEXITCODE)" }

Das Modul WklTest

ElementAufgerufen vonZweck
Answer(Kind, Prompt)der AnwendungVor einem Dialog: außerhalb eines Testlaufs Empty (den Dialog zeigen); in einem Lauf die Antwort, die der Test mit Expect festgelegt hat. Ein Dialog, den der Test nicht erwartet oder dessen Text nicht passt, ist eine fehlgeschlagene Prüfung, und die Antwort ist Cancel.
InRun()der AnwendungTrue, solange wkl-office test läuft. Für Code, der nur fragen darf, wenn jemand antworten kann: Application.UserControl Or WklTest.InRun().
Expect Kind, Pattern, Replyeinem TestLegt den nächsten Dialog fest: seine Art, ein Like-Muster für seinen Text und die Antwort (ein VbMsgBoxResult, ein Text, ein Pfad, ein Array von Pfaden oder WklTest.Cancel). Die Dialoge werden in dieser Reihenfolge erwartet; einer, der nie erschien, ist am Ende der Prozedur eine fehlgeschlagene Prüfung.
Check(Title, Condition, [Message])einem TestEine Prüfung: OK oder FAIL mit der Meldung. Gibt die Bedingung zurück.
Progress Texteinem TestEine Fortschrittszeile in der Laufdatei, für lange Tests.
Cancel()einem TestDie Antwort, die für das Schließen eines Dialogs steht: Null (keine Schaltfläche, ein leerer Text, kein Pfad).
KindMessage, KindInput, KindOpen, KindSaveAs, KindFolderbeidenDie Dialogarten: msgbox, input, open, saveas, folder.

Das Modul gehört dem SDK: Jeder Build ersetzt ein Modul WklTest der Quellen durch das eigene, und der nächste Export schreibt es in die Quellen. Ändern Sie es nur über eine neue Version des SDK. Eine Anwendung, die schon vor dem Build mit dem SDK kompilieren soll, kann ein Platzhaltermodul WklTest behalten: mit Answer (gibt Empty zurück), InRun (gibt False zurück), den Konstanten KindMessage bis KindFolder mit den Werten der Tabelle und Cancel (gibt Null zurück), wenn der Code es verwendet.

Hinweise

  • Namen des Moduls. WklTest bringt öffentliche Namen in das Projekt: InRun, Cancel, Answer, Expect, Check, Progress und die Konstanten KindMessage bis KindFolder. Hat ein Standardmodul der Anwendung ein öffentliches Element gleichen Namens und verwendet der Code es ohne Modulnamen, meldet VBA „Mehrdeutiger Name“, und das Projekt lässt sich nicht mehr kompilieren. Nennen Sie das Modul mit: WklTest.KindOpen für das SDK, <Modul>.KindOpen für das eigene Element; die Beispiele dieser Seite schreiben immer WklTest..
  • Nichts startet von selbst. Die Kopie wird wie bei call ohne Startformular, Menüband-Rückrufe und AutoExec-Makro geöffnet; eine Datenbank mit AutoExec-Makro wird abgelehnt. Ein Test, der die Vorbereitung des Startformulars braucht, ruft diesen Code selbst auf.
  • Eine Prozedur nach der anderen. Die Variablen der Module behalten ihre Werte von einer Prozedur zur nächsten, ein Laufzeitfehler setzt sie aber zurück; lassen Sie keinen Test von einem früheren abhängen.
  • Dialoge, die WklTest.Answer nicht fragen, werden mit Abbrechen, Nein oder OK beantwortet, und die Prozedur schlägt fehl. Ein mit acDialog geöffnetes Formular wartet bis zum Zeitlimit; öffnen Sie solche Formulare im Test ohne acDialog und prüfen Sie sie direkt. Der Laufzeitfehlerdialog von VBA erscheint etwa eine Sekunde lang auf dem Desktop, auch wenn Access verborgen läuft.
  • Zeitlimit und Abstürze. Eine Prozedur, die --timeout überschreitet (Vorgabe 120 Sekunden), beendet ihr Access, und der Lauf hält mit Exitcode 13 an. Wird Access während einer Prozedur beendet, hält der Lauf mit Exitcode 16 an und nennt die zuletzt geschriebene Zeile; die Zeilen davor stehen in wkl-test-run.jsonl im Arbeitsordner.
  • Tests, die nicht mehr laufen, fallen auf: Ein Lauf aller Prozeduren mit weniger Prüfungen als der letzte grüne Lauf schlägt mit der Zeile check count fehl.
  • Tests je Sprache. --language sl führt die Prozeduren mit den Anwendungstexten und den WKL-Komponenten auf Slowenisch aus, unabhängig von der Sprache von Office; so prüft ein Rechner jede Sprache der Anwendung (Texte einer Anwendung). Die Anzahl der Prüfungen wird je Sprache geführt. Das setzt die WKL Forms Object Library 1.65 oder höher voraus.
  • CI-Server lesen build\<configuration>\test\wkl-test-report.xml (JUnit-XML). Die Tests laufen im Access des Build-Rechners, in dessen Bitbreite.
  • Der Arbeitsordner (Vorgabe build\<configuration>\test, sonst --work) wird angelegt, wenn er fehlt, aber nicht geleert: test ersetzt darin nur die Kopie der Datenbank und wkl-test-run.jsonl. Dateien, die ein Skript vorher hineinlegt, finden die Tests unter CurrentProject.Path.
  • Werte für die Tests. test übergibt den Testprozeduren keine Parameter; Eingaben legen Sie als Dateien in den Arbeitsordner. Unter Windows 11 sieht das verborgene Access zwar die Umgebungsvariablen des aufrufenden Prozesses, das SDK sichert das aber nicht zu. Schreiben Sie keine Kennwörter in den Arbeitsordner: Seine Dateien bleiben nach dem Lauf liegen.
  • Access Runtime und Bedienung. Die Tests laufen im vollen Access, auch mit -t accde; ein Lauf unter Access Runtime (/runtime) wird nicht unterstützt. Bedienung mit echten Tasten und Maus in einem sichtbaren Access (Tabulatorfolge, Fokus, Tastenkürzel, Ziehen und Ablegen) prüft test nicht.
  • Tests in der ausgelieferten Anwendung. Die Testprozeduren sind Quellen wie jedes andere Modul und werden in jede Datenbank des Projekts gebaut, auch in die ausgelieferte. Um sie aus der Auslieferung herauszuhalten, legen Sie sie in ein eigenes Testprojekt, das das Hauptprojekt als Vorlage nennt (Projektordner).

Verwandte Themen

de/wiki/msaccess/sdk/how-to/test-an-application.txt · Last modified: by Wolfgang van der Stille