Freigeben über


WMI-Datenquelle

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

Hintergrund

"WMI" steht für "Windows-Verwaltungsinstrumentation". Mit dem Common Information Model (CIM), dem Branchenstandard, um Systeme darzustellen. 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 DataSource in TAEF verfügbar ist, können Sie ihrem Test eine Vorbedingung hinzufügen sowie Informationen zu den Ressourcen auf dem Testcomputer abrufen, bevor Sie den Test ausführen. Im Folgenden sind einige Beispiele für die Art der Abfrage aufgeführt, die Sie mit WMI erstellen können:

  • Überprüfen Sie, ob der Test auf einem Laptop ausgeführt wird, und führen Sie den Test nur dann 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 es bereits geschehen ist.
  • Rufen Sie alle Wechseldatenträger und lokale 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 einer Domäne beigetreten ist ODER
  • Führen Sie den Test nur aus, wenn der Testcomputer einer Domäne beigetreten ist, und rufen Sie den Domänennamen ab.

Das 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 diese WMI-Abfrageunterstützung während des Erstellens eines TAEF-Tests hinzugefügt wird.

Die einzigen speziellen Metadaten, die Sie zum Testen eines WMI DataSource-Tests benötigen, ist die "DataSource". Die DataSource-Syntax muss wie folgt aussehen:

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

Oder im systemeigenen Code:

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

Sie müssen bemerkt haben, dass der DataSource-Wert mit "WMI:" beginnt, der TAEF informiert, dass dies tatsächlich die Datenquelle für einen Test ist, der vom WMI-Abfrageergebnis abhängt, und unterscheidet ihn auch vom datengesteuerten Test. Dies ist eine gute Gelegenheit, zu erwähnen, dass TAEF derzeit keinen Test unterstützt, der sowohl datengesteuert ist als auch vom Ergebnis einer WMI-Abfrage abhängt.

Die nächste Frage ist natürlich, wie WQL-Abfragen für das geschrieben werden, wonach Sie suchen? Die WQL-Abfragesyntax ist ähnlich wie vereinfachte 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 auf dem "Themes"-Service aus, nachdem Sie die Eigenschaften "Description", "DesktopInteract" und "ProcessId" gefunden haben, die Sie in Ihren Tests verwenden möchten.

SELECT-Funktionen, 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 CapabilityDescriptions für jeden Drucker.

SELECT Name, Benutzer, Standort FROM Win32_StartupCommand
Führen Sie den Test für jeden Prozess aus, der beim Windows-Start ausgeführt wird. Geben Sie für jeden Prozess an, wie der Name des Prozesses lautet, wo er sich befindet (Ort), und unter welchem Benutzer der Prozess läuft.

Weitere Beispiele finden Sie in der oben genannten Dokumentation sowie in der .cs Datei- und Headerdatei in den von Ihnen geöffneten Beispielen. Die allgemeine, übervereinfachte Syntax lautet wie folgt:

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

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

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 mindestens ein Objekt als Ergebnis der Abfrage 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 der Information 'Blockiert' protokolliert und die Ausführung geht zum nächsten Test über.

Das Überprüfen oder Verifizieren Ihrer Abfrage vor der Erstellung des Tests ist eine sehr gute Idee und ein sehr einfacher Prozess:

  • Rufen Sie "wbemtest.exe" entweder über das Dialogfeld "Ausführen" oder eine Eingabeaufforderung auf.
  • Klicken Sie in der oberen rechten Ecke auf die Schaltfläche "Verbinden".
  • Stellen Sie sicher, dass Ihr Namespace "root\cimv2" ist, 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 "Übernehmen".

HINWEIS: Der "IWbemService" verfügt über mehrere andere Optionen, die Ihnen bei der Abfrage helfen könnten. Wenn Sie beispielsweise die Option "Enum Classes" verwenden und das Optionsfeld auf "rekursiv" ändern, können Sie alle WMI-Klassen im System sehen.

Abrufen von eigenschaften, die mit der WMI-Abfrage abgefragt wurden

Jetzt haben Sie eine Vorstellung davon, wie Sie eine WMI-Abfrage für eine Testmethode erstellen und wie Sie sie als Metadaten anwenden können, während Sie einen Test erstellen. Sie wissen auch, wie Sie bestätigen können, dass die Abfrage mit wbemtest.exegültig ist. Sehen wir uns nun an, wie man die Eigenschaftswerte abrufen kann, nach denen Sie gesucht haben.

Die Grundlagen zum Abrufen dieser Informationen ähneln dem Abrufen von Werten für Ihren datengesteuerten Test. In verwaltetem Code würde dies z. B. wie folgt aussehen:

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 einen öffentlichen Getter und Setter bereitgestellt, damit TAEF die richtigen Werte setzen kann. Mit der privaten TestContext-Eigenschaft können Sie den aktuellen Wert für alle Eigenschaften des WMI-Abfrageergebnisseobjekts abrufen, die Sie aus TAEF abgerufen haben.

Der systemeigene Code zum Abrufen der WMI-Eigenschaften ist sehr ähnlich. Wie bei systemeigenen datengesteuerten Tests verwenden Sie TestData, um die Eigenschaftswerte abzurufen. Betrachten wir beispielsweise den Test zum Abrufen von Eigenschaften des Standarddruckers. Die Header-Datei 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()

Dazu 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ücksichtigen möglicher NULL-Eigenschaftswerte

Beachten Sie, dass die WMI-Abfrage möglicherweise nicht immer eine Nicht-Null-Eigenschaft 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 Nullwerte 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 umzuwandeln, den Sie erwarten. Sehen wir uns folgendes 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 entsprechend 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. Falls dies nicht der Fall ist, war der zurückgegebene Wert nicht null und daher gültig. Wandeln Sie ihn also in die entsprechenden Typen um und verwenden Sie ihn für die Tests.

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

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 so, 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    }