Anleitung
Clients testen
Client-Logik in automatisierten Tests ohne Anlage prüfen: einen OpcServer mit Test-Nodes im selben Prozess starten und gegen ihn testen.
Anleitung
Clients testen
Das OPC UA .NET SDK enthält Client und Server. Für automatisierte Tests lässt sich deshalb im selben Prozess ein Server starten, der genau die Nodes enthält, die der Client erwartet. Dafür brauchen Sie weder eine Testanlage noch einen externen Simulator. Die Beispiele sind unabhängig vom Testframework. In xUnit, NUnit oder MSTest gehört der Aufbau in die jeweilige Testmethode oder Fixture, die Prüfung in deren Assertions.
Server und Client im Test starten
Beteiligte TypenOpcServerOpcClientOpcDataVariableNode
Ein Server mit Nodes entsteht in einer Zeile: Der Konstruktor nimmt die Adresse und die Nodes entgegen. Den Identifier eines Nodes kennt der Test über die Eigenschaft Id des Nodes und muss ihn nicht selbst zusammensetzen. Zwei using-Blöcke beenden Client und Server auch dann, wenn eine Prüfung fehlschlägt:
var speedNode = new OpcDataVariableNode<int>("Speed", value: 100);
using (var server = new OpcServer("opc.tcp://localhost:48400/", speedNode))
using (var client = new OpcClient("opc.tcp://localhost:48400/")) {
server.Start();
client.Connect();
OpcValue value = client.ReadNode(speedNode.Id);
if ((int)value.Value != 100)
throw new Exception("Unexpected speed.");
}Dim speedNode = New OpcDataVariableNode(Of Integer)("Speed", value:=100)
Using server = New OpcServer("opc.tcp://localhost:48400/", speedNode)
Using client = New OpcClient("opc.tcp://localhost:48400/")
server.Start()
client.Connect()
Dim value As OpcValue = client.ReadNode(speedNode.Id)
If CInt(value.Value) <> 100 Then
Throw New Exception("Unexpected speed.")
End If
End Using
End UsingSchreiben prüfen
Beteiligte TypenOpcClientOpcStatusOpcDataVariableNode
Was der Client schreibt, steht danach im Wert des Nodes auf dem Server. Der Test prüft beides, den Status des Schreibvorgangs und den Wert im Node:
OpcStatus result = client.WriteNode(speedNode.Id, value: 120);
if (!result.IsGood || speedNode.Value != 120)
throw new Exception("The value has not been written.");Dim result As OpcStatus = client.WriteNode(speedNode.Id, value:=120)
If Not result.IsGood OrElse speedNode.Value <> 120 Then
Throw New Exception("The value has not been written.")
End IfSubscriptions prüfen
Beteiligte TypenOpcClientOpcDataVariableNodeOpcDataChangeReceivedEventArgs
Benachrichtigungen treffen asynchron ein. Der Test ändert den Wert auf dem Server, meldet die Änderung mit ApplyChanges und wartet mit einer Obergrenze auf die Benachrichtigung:
using (var received = new ManualResetEventSlim()) {
client.SubscribeDataChange(speedNode.Id, (sender, e) => {
if (e.Item.Value.As<int>() == 150)
received.Set();
});
speedNode.Value = 150;
speedNode.ApplyChanges(server.SystemContext);
if (!received.Wait(TimeSpan.FromSeconds(5)))
throw new Exception("No data change received.");
}Using received = New ManualResetEventSlim()
client.SubscribeDataChange( _
speedNode.Id, _
Sub(sender, e)
If e.Item.Value.As(Of Integer)() = 150 Then received.Set()
End Sub)
speedNode.Value = 150
speedNode.ApplyChanges(server.SystemContext)
If Not received.Wait(TimeSpan.FromSeconds(5)) Then
Throw New Exception("No data change received.")
End If
End UsingMethodenaufrufe prüfen
Beteiligte TypenOpcServerOpcObjectNodeOpcMethodNodeOpcClient
Methoden, die der Client aufruft, lassen sich auf dem Testserver als OpcMethodNode mit einem Delegaten nachbilden. Der Rückgabewert des Delegaten kommt beim Client als erstes Ausgabeargument an:
var machine = new OpcObjectNode("Machine");
var startJobNode = new OpcMethodNode(
machine,
name: "StartJob",
new Func<string, int>(StartJob));
using (var server = new OpcServer("opc.tcp://localhost:48401/", machine))
using (var client = new OpcClient("opc.tcp://localhost:48401/")) {
server.Start();
client.Connect();
object[] outputs = client.CallMethod(machine.Id, startJobNode.Id, "Job 1");
if ((int)outputs[0] != 42)
throw new Exception("Unexpected job number.");
}
...
private static int StartJob(string name)
{
return 42;
}Dim machine = New OpcObjectNode("Machine")
Dim startJobNode = New OpcMethodNode( _
machine, _
name:="StartJob", _
New Func(Of String, Integer)(AddressOf StartJob))
Using server = New OpcServer("opc.tcp://localhost:48401/", machine)
Using client = New OpcClient("opc.tcp://localhost:48401/")
server.Start()
client.Connect()
Dim outputs As Object() = client.CallMethod(machine.Id, startJobNode.Id, "Job 1")
If CInt(outputs(0)) <> 42 Then
Throw New Exception("Unexpected job number.")
End If
End Using
End Using
...
Private Shared Function StartJob(ByVal name As String) As Integer
Return 42
End FunctionHinweise für Testläufe
| Thema | Hinweis |
|---|---|
| Ports | Der Server bindet seinen Port standardmäßig exklusiv (Use). Wenn Tests parallel laufen, braucht jeder Test einen eigenen Port. |
| Zertifikate | Beim ersten Start erzeugen Server und Client ihr Anwendungszertifikat. Das dauert einige Sekunden. Danach laden beide ihre Zertifikate aus dem Zertifikatspeicher. |
| Vertrauen | Server und Client nehmen unbekannte Zertifikate standardmäßig an (Auto), Tests brauchen deshalb keine eigene Zertifikatsverwaltung. |
| Aufräumen | using beendet Client und Server zuverlässig, auch bei einer fehlgeschlagenen Prüfung. |
| Lizenz | Ohne Lizenzschlüssel läuft das SDK in der Evaluation je Anwendungsstart 30 Minuten. Lange Testläufe brauchen deshalb den Lizenzschlüssel, siehe Lizenz einrichten. |
Den Aufbau eines Servers beschreibt die Seite Erste Schritte der Server-Entwicklung.

