Freigeben über


WMI-Datenquelle

Stellen Sie sicher, dass Sie mit der grundlegenden Ausführung von TAEF vertraut sind und wissen, wie Sie Tests erstellen können, bevor Sie mit diesem Abschnitt fortfahren.

Hintergrund

"WMI" steht für "Windows-Verwaltungsinstrumentation". Verwenden des Common Information Model (CIM), dem Branchenstandard zur Darstellung von Systemen. Die Windows-Verwaltungsinstrumentation bietet eine einheitliche Möglichkeit für den Zugriff auf Systemverwaltungsinformationen.

Wie hilft es meinen Tests?

Mithilfe der WMI-Abfrageunterstützung, die als WMI-Datenquelle in TAEF verfügbar ist, können Sie Ihrem Test eine Vorbedingung hinzufügen und Informationen zu den Ressourcen auf dem Testcomputer abrufen, bevor Sie den Test ausführen. Im Folgenden finden Sie einige Beispiele für die Art von Abfrage, die Sie mit WMI durchführen könnten:

  • Überprüfen Sie, ob der Computer, auf dem der Test ausgeführt wird, ein Laptop ist, und führen Sie den Test nur aus, wenn es sich um einen Laptop handelt.
  • Überprüfen Sie, ob ein Service Pack auf dem Testcomputer installiert wurde, und führen Sie den Test nur aus, wenn dies der Test war.
  • Rufen Sie alle Wechseldatenträger und lokalen Festplattenlaufwerke auf dem Testcomputer ab, und führen Sie den Test für jedes der Laufwerke aus, die der Abfrage entsprechen.
  • Führen Sie den Test nur aus, wenn der Testcomputer nicht in die Domäne eingebunden ist ODER
  • Führen Sie den Test nur aus, wenn der Testcomputer in die Domäne eingebunden ist, und rufen Sie den Domänennamen ab.

Dies hätte Ihnen hoffentlich eine Vorstellung davon gegeben, wo und wie Sie WMI DataSource für Ihre Tests nutzen können. Sehen wir uns an, wie Sie diese WMI-Abfrageunterstützung beim Erstellen eines TAEF-Tests hinzufügen.

Die einzigen speziellen Metadaten, die Sie benötigen, um Ihren Test als WMI-DataSource-Test auszuführen, ist die "DataSource". Die DataSource-Syntax muss wie folgt aussehen:

[DataSource("WMI:<WQL query>")]

Oder im nativen Code:

TEST_METHOD_PROPERTY(L"DataSource", L"WMI:<WQL query>")]

Sie müssen bemerkt haben, dass der DataSource-Wert mit "WMI:" beginnt, wodurch TAEF wissen lässt, dass dies tatsächlich die Datenquelle für einen Test ist, der vom WMI-Abfrageergebnis abhängt und ihn auch von datengesteuertem Test unterscheidet. Dies ist eine gute Gelegenheit, um zu Erwähnung, dass TAEF derzeit keinen Test unterstützt, der sowohl ein datengesteuerter Test als auch ein Test ist, der vom WMI-Abfrageergebnis abhängt.

Die nächste Frage ist natürlich, wie Sie WQL-Abfragen für das schreiben, wonach Sie suchen? Die WQL-Abfragesyntax ähnelt stark vereinfachten SQL-Abfragen. Es gibt einige sehr gute Beispiele für Abfragen, die in WMI-Aufgaben für Skripts und Anwendungen bereitgestellt werden. Hier sind einige Beispiele:

SELECT Description, DesktopInteract, ProcessId FROM Win32_Service WHERE Name='Themes'
Führen Sie den Test für den "Designs"-Dienst aus, nachdem Sie die Eigenschaften Description, DesktopInteract und ProcessId herausgearbeitet haben, die Sie in Ihrem Test verwenden möchten.

SELECT Capabilities, CapabilityDescriptions FROM Win32_Printe
Führen Sie den Test für jeden Drucker aus, der mit diesem Computer verbunden ist. Ermöglichen Sie dem Test den Zugriff auf die Funktionen und Funktionsbeschreibungen für jeden Drucker.

SELECT Name, Benutzer, Location FROM Win32_StartupCommand
Führen Sie den Test für jeden Prozess aus, der beim Windows-Start ausgeführt wird. Lassen Sie den Test für jeden Prozess wissen, wie der Name des Prozesses ist, wo er sich befindet (Speicherort) und unter welchem Benutzer der Prozess ausgeführt wird.

Weitere Beispiele finden Sie in der oben erwähnten Dokumentation sowie in der CS-Datei und der Headerdatei in den von Ihnen geöffneten Beispielen. Die allgemeine, über vereinfachte Syntax lautet wie folgt:

SELECT <comma separated properties> FROM <WMI Class name> [WHERE <add condition on some properties>]

In den soeben angezeigten Beispielen sind Win32_Service, Win32_Printer und Win32_StartupCommand alle WMI-Klassen. Sie können die WMI-Klassen in WMI-Klassen suchen.

TAEF unterstützt das Abrufen von Systemeigenschaften nicht.

Im Hintergrund führt TAEF die Abfrage für Sie aus und bestätigt das Ergebnis. Wenn als Ergebnis der Abfrage mindestens ein Objekt zurückgegeben wird, wird der Test für jedes zurückgegebene Objekt ausgeführt. Wenn die WQL-Abfrage keine Objekte zurückgibt, wird der Test mit diesen Informationen als Blockiert protokolliert, und die Ausführung wird mit dem nächsten Test fortgesetzt.

Das Überprüfen oder Überprüfen Ihrer Abfrage vor dem Erstellen des Tests scheint eine gute Idee zu sein und ist ein sehr einfacher Prozess:

  • Entweder über das Ausführungsdialogfeld oder über eine Eingabeaufforderung wird "wbemtest.exe" aufgerufen.
  • Klicken Sie oben rechts auf die Schaltfläche "Verbinden".
  • Stellen Sie sicher, dass Ihr Namespace "root\cimv2" lautet, bevor Sie in der oberen rechten Ecke erneut auf "Verbinden" klicken.
  • Klicken Sie unter "IWbemServices" auf "Abfrage".
  • Geben Sie Ihre Abfrage in das daraufhin angezeigte Bearbeitungsfeld ein, und klicken Sie auf "Anwenden".

HINWEIS: Der "IWbemService" verfügt über mehrere weitere Optionen, die Ihnen bei Ihrer Abfrage helfen können. Wenn Sie beispielsweise "Enumerationsklassen" verwenden und das Optionsfeld in "rekursiv" ändern, können Sie alle WMI-Klassen im System anzeigen.

Abrufen von Eigenschaften, die mithilfe der WMI-Abfrage abgefragt wurden

Inzwischen haben Sie eine Vorstellung davon, wie Sie eine WMI-Abfrage für eine Testmethode erstellen und sie beim Erstellen eines Tests als Metadaten anwenden können. Sie wissen auch, wie Sie mithilfe von wbemtest.exe bestätigen, dass die Abfrage gültig ist. Nun sehen wir uns an, wie Sie die eigenschaftenwerte abrufen, nach denen Sie gesucht haben.

Die Grundlagen zum Abrufen dieser Informationen ähneln dem Abrufen von Werten für Ihren datengesteuerten Test. Im verwalteten Code sieht dies beispielsweise wie folgt aus:

1 namespace WEX.Examples
2 {
3     using Microsoft.VisualStudio.TestTools.UnitTesting;
4     using System;
5     using System.Collections;
6     using System.Data;
7     using WEX.Logging.Interop;
8     using WEX.TestExecution;
9
10    [TestClass]
11    public class CSharpWmiDataSourceExample
12    {
13        [TestMethod]
14        [DataSource("WMI:SELECT Description, DesktopInteract, ProcessId FROM Win32_Service WHERE Name='Themes'")]
15        public void ThemesTest()
16        {
17            String description = (String)m_testContext.DataRow["Description"];
18            Boolean desktopInteract = (Boolean)m_testContext.DataRow["DesktopInteract"];
19            UInt32 processId = (UInt32)m_testContext.DataRow["ProcessId"];
20            Log.Comment("Themes service is running on process " + processId.ToString() + " with desktop interact set to "
                           + desktopInteract.ToString());
21            Log.Comment("Themes service description: " + description);
22        }
23        ...
24        public TestContext TestContext
25        {
26            get { return m_testContext; }
27            set { m_testContext = value; }
28        }
29
30        private TestContext m_testContext;
31    }
32}

Die Zeilen 24-30 im obigen Beispiel sind genau das, was für einen verwalteten datengesteuerten Test erforderlich ist. Sie haben eine private TestContext-Eigenschaft definiert und für TAEF öffentliche Getter und Setter bereitgestellt, um die richtigen Werte festzulegen. Mithilfe der privaten TestContext-Eigenschaft können Sie den aktuellen Wert für alle Eigenschaften des WMI-Abfrageergebnisobjekts abrufen, die Sie aus TAEF abgerufen haben.

Der native Code zum Abrufen der WMI-Eigenschaften ist sehr ähnlich. Wie bei nativen datengesteuerten Tests verwenden Sie TestData, um die Eigenschaftswerte abzurufen. Betrachten wir beispielsweise den Test zum Abrufen von Eigenschaften des Standarddruckers. Die Headerdatei erstellt diesen Test wie folgt:

1        // Test on the default printer and its driver name
2        BEGIN_TEST_METHOD(DefaultPrinterTest)
3            TEST_METHOD_PROPERTY(L"DataSource",
              L"WMI:SELECT DriverName, DeviceId, LanguagesSupported FROM Win32_Printer WHERE Default = True")
4        END_TEST_METHOD()

Hierzu sieht unser Abrufcode in der cpp-Datei wie folgt aus:

1     void WmiExample::DefaultPrinterTest()
2     {
3         String deviceId;
4         VERIFY_SUCCEEDED(TestData::TryGetValue(L"DeviceId", deviceId));
5
6         String driverName;
7         VERIFY_SUCCEEDED(TestData::TryGetValue(L"DriverName", driverName));
8
9         TestDataArray<unsigned int> languagesSupported;
10        VERIFY_SUCCEEDED(TestData::TryGetValue(L"LanguagesSupported", languagesSupported));
11
12        Log::Comment(L"The default driver is " + deviceId + L" which is a " + driverName);
13        size_t count = languagesSupported.GetSize();
14        for (size_t i = 0; i < count; i++)
15        {
16            Log::Comment(String().Format(L"Language supported: %d", languagesSupported[i]));
17        }
18    }

Berücksichtigung möglicher NULL-Eigenschaftswerte

Zu beachten ist, dass die WMI-Abfrage möglicherweise nicht immer eine Eigenschaft ungleich NULL zurückgibt. Es kann vorkommen, dass der zurückgegebene WMI-Eigenschaftswert "NULL" ist. Wenn Sie der Meinung sind, dass die gesuchte Eigenschaft in einigen Szenarien "NULL" sein könnte, überprüfen Sie sie, bevor Sie sie überprüfen oder versuchen, sie zu verwenden.

In verwaltetem Testcode speichert TestContext beispielsweise die NULL-Werte als Objekt vom Typ DBNull. Sie müssen überprüfen, ob das Objekt vom Typ DBNull ist, bevor Sie versuchen, den resultierenden Wert in den Typ zu umwandeln, den Sie erwarten. Sehen wir uns das einmal genauer an:

1 namespace WEX.Examples
2 {
3     using Microsoft.VisualStudio.TestTools.UnitTesting;
4     using System;
5     using System.Collections;
6     using System.Data;
7     using WEX.Logging.Interop;
8     using WEX.TestExecution;
9
10    [TestClass]
11    public class CSharpWmiDataSourceExample
12    {
13        [TestMethod]
14        [DataSource("WMI:SELECT MaximumComponentLength, Availability, DeviceId, DriveType, Compressed
                         FROM Win32_LogicalDisk WHERE DriveType=2 Or DriveType=3")]
15        public void LogicalDiskTest()
16        {
17            UInt32 driveType = (UInt32)m_testContext.DataRow["DriveType"];
18            Log.Comment("DeviceId is " + m_testContext.DataRow["DeviceId"]);
19            Log.Comment("DriveType is " + driveType.ToString());
20
21            object nullCheckCompressed = m_testContext.DataRow["Compressed"];
22            Log.Comment("Compressed's type is: " + nullCheckCompressed.GetType().ToString());
23            if (nullCheckCompressed.GetType() == typeof(DBNull))
24            {
25                Log.Comment("Compressed is NULL");
26            }
27            else
28            {
29                Boolean compressed = (Boolean)nullCheckCompressed;
30                Log.Comment("Compressed is " + compressed.ToString());
31            }
32
33            object nullCheckMaxComponentLength = m_testContext.DataRow["MaximumComponentLength"];
34            if (nullCheckMaxComponentLength.GetType() == typeof(DBNull))
35            {
36                Log.Comment("MaxComponentLength is NULL");
37            }
38            else
39            {
40                UInt32 maxComponentLength = (UInt32)nullCheckMaxComponentLength;
41                Log.Comment("MaxComponentLength is " + maxComponentLength.ToString());
42            }
43
44            object nullCheckAvailability = m_testContext.DataRow["Availability"];
45            if (nullCheckAvailability.GetType() == typeof(DBNull))
46            {
47                Log.Comment("Availability is NULL");
48            }
49            else
50            {
51                UInt32 availability = (UInt32)nullCheckAvailability;
52                Log.Comment("Availability is " + availability.ToString());
53            }
54        }
55        ...
56        public TestContext TestContext
57        {
58            get { return m_testContext; }
59            set { m_testContext = value; }
60        }
61
62        private TestContext m_testContext;
63    }
64}

Im obigen Test können beispielsweise "Compressed", "MaximumComponentLength" und "Availability" in einigen Szenarien NULL sein (wenn die Abfrage Wechseldatenträger wie Diskettenlaufwerke zurückgibt). Sie möchten sicherstellen, dass sich der Test in solchen Fällen angemessen verhält. Rufen Sie zu diesem Zweck den Eigenschaftswert als Objekt ab, und überprüfen Sie, ob er vom Typ "DBNull" ist. Wenn dies der Grund ist, bedeutet dies, dass der zurückgegebene Eigenschaftswert NULL war. Andernfalls war der zurückgegebene Wert nicht NULL und daher gültig. Wandeln Sie ihn daher in die entsprechenden Typen um, und verwenden Sie ihn für den Test.

Das gleiche gilt auch für native Abruf-APIs: Der zurückgegebene Eigenschaftswert könnte NULL sein. Dies bedeutet, dass Sie überprüfen müssen, ob testData den Wert erfolgreich abgerufen hat, ohne einen Überprüfungsaufruf zu verwenden (da nicht abgerufen werden kann, weil der Wert NULL ist). Beispielsweise verfügen Sie über eine Testmethode, die von einer WMI-Abfrage abhängig ist:

1        // Test on only local (drive type = 3) or removable (drive type = 2) harddrive
2        BEGIN_TEST_METHOD(LocalOrRemovableHardDriveTest)
3            TEST_METHOD_PROPERTY(L"DataSource", L"WMI:SELECT DeviceId, DriveType, Availability,
                  MaximumComponentLength FROM Win32_LogicalDisk WHERE DriveType=2 OR DriveType=3")
4        END_TEST_METHOD()

Möglicherweise werden "Availability" und "MaximumComponentLength" als NULL-Werte zurückgegeben. Schreiben Sie also den Test, um folgendes zu berücksichtigen:

1     void WmiExample::LocalOrRemovableHardDriveTest()
2     {
3         String deviceId;
4         VERIFY_SUCCEEDED(TestData::TryGetValue(L"DeviceId", deviceId));
5         int driveType;
6         VERIFY_SUCCEEDED(TestData::TryGetValue(L"DriveType", driveType));
7
8         unsigned int maxComponentLength;
9         if (SUCCEEDED(TestData::TryGetValue(L"MaximumComponentLength", maxComponentLength)))
10        {
11            Log::Comment(String().Format(L"MaximumComponentLength: %d", maxComponentLength));
12        }
13
14        unsigned int availability;
15        if (SUCCEEDED(TestData::TryGetValue(L"Availability", availability)))
16        {
17            Log::Comment(String().Format(L"Availability: %d", availability));
18        }
19
20        Log::Comment(L"DeviceId: " + deviceId);
21        Log::Comment(String().Format(L"DriveType: %d", driveType));
22    }