Udostępnij przez


Źródło danych WMI

Przed kontynuowaniem tej sekcji upewnij się, że znasz podstawowe wykonywanie funkcji TAEF i wiesz, jak tworzyć testy przy użyciu tej funkcji.

Tło

"WMI" oznacza "Instrumentacja zarządzania Windows". Używanie modelu Common Information Model (CIM), który jest standardem branżowym reprezentującym systemy. Instrumentacja zarządzania Windows zapewnia ujednolicony sposób uzyskiwania dostępu do informacji o zarządzaniu systemem.

Jak to pomaga w testach?

Korzystając z obsługi zapytań WMI dostępnej jako źródło danych WMI w TAEF, możesz dodać warunek wstępny do testu, a także uzyskać informacje o zasobach na komputerze testowym zanim uruchomisz test. Oto kilka przykładów tego rodzaju zapytania, które można utworzyć przy użyciu usługi WMI:

  • Sprawdź, czy maszyna, na którym działa test, jest laptopem, i uruchom test tylko wtedy, gdy jest to laptop.
  • Sprawdź, czy na maszynie testowej zainstalowano pakiet Service Pack i uruchom test tylko wtedy, gdy został zainstalowany.
  • Pobierz wszystkie dyski wymienne i lokalne dyski twarde na maszynie testowej i uruchom test dla każdego z dysków pasujących do zapytania.
  • Uruchom test tylko wtedy, gdy maszyna testowa nie jest przyłączona do domeny LUB
  • Uruchom test tylko wtedy, gdy maszyna testowa jest przyłączona do domeny i pobierz nazwę domeny.

Miejmy nadzieję, że wiesz, gdzie i jak można wykorzystać źródło danych WMI do testowania. Przyjrzyjmy się, jak dodać tę obsługę zapytań WMI podczas tworzenia testu TAEF.

Jedynymi specjalnymi metadanymi, których potrzebujesz, aby twój test stał się testem WMI DataSource, są "DataSource". Składnia źródła danych musi wyglądać następująco:

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

Lub w kodzie natywnym:

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

Należy zauważyć, że wartość Źródło danych zaczyna się od wartości "WMI:", która informuje TAEF, że jest to rzeczywiście źródło danych dla testu, który zależy od wyniku zapytania usługi WMI, a także odróżnia go od testu opartego na danych. Jest to dobra okazja, aby wspomnieć, że obecnie TAEF nie obsługuje zarówno testu opartego na danych, jak i testu, który zależy od wyniku zapytania WMI.

Następne pytanie naturalnie brzmi jak pisać zapytania WQL dla tego, czego szukasz? Składnia zapytań WQL jest bardzo podobna do uproszczonych zapytań SQL. Istnieje kilka bardzo dobrych przykładów zapytań dostępnych w zadaniach usługi WMI dla skryptów i aplikacji. Oto kilka przykładów:

-- Wybierz opis, interakcję z pulpitem, identyfikator procesu z serwisu Win32_Service, gdzie nazwa równa się 'Themes'SELECT Description, DesktopInteract, ProcessId FROM Win32_Service WHERE Name='Themes'
Uruchom test w usłudze "Motywy" po zapoznaniu się z jej opisem oraz właściwościami DesktopInteract i ProcessId, które zamierzasz użyć w swoich testach.

SELECT Capabilities, CapabilityDescriptions FROM Win32_Printer
Uruchom test dla każdej drukarki podłączonej do tego komputera. Zezwól testowi na dostęp do możliwości i opisów możliwości dla każdej drukarki.

SELECT Name (Nazwa), User (Użytkownik), Location (Lokalizacja) FROM Win32_StartupCommand
Uruchom test dla każdego procesu, który zostanie uruchomiony podczas uruchamiania systemu Windows. W przypadku każdego procesu poinformuj test o tym, jaka jest nazwa procesu, gdzie znajduje się (lokalizacja) i jaki jest użytkownik, w którym jest uruchamiany proces.

Więcej przykładów można znaleźć w powyższej dokumentacji, a także w pliku .cs i pliku nagłówka w przykładach, które zostały otwarte. Ogólna, nadmiernie uproszczona składnia jest następująca:

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

W przykładach, które zostały właśnie wyświetlone, Win32_Service, Win32_Printer i Win32_StartupCommand są wszystkie klasy WMI. Klasy WMI można wyszukać w klasach WMI.

Funkcja TAEF nie obsługuje pobierania właściwości systemu.

Za sceną TAEF wykona zapytanie dla Ciebie i potwierdzi wynik. Jeśli co najmniej jeden obiekt zostanie zwrócony w wyniku zapytania, test zostanie wykonany dla każdego zwróconego obiektu. Jeśli zapytanie WQL nie zwraca żadnych obiektów, test zostanie zarejestrowany jako Zablokowany przy użyciu tych informacji i wykonanie przejdzie do następnego testu.

Sprawdzanie lub weryfikowanie zapytania przed utworzeniem testu wydaje się być doskonałym pomysłem i jest bardzo prostym procesem:

  • Albo w oknie dialogowym uruchamiania, albo w wierszu polecenia wywołaj polecenie "wbemtest.exe"
  • Kliknij przycisk "Połącz" w prawym górnym rogu.
  • Przed ponownym kliknięciem pozycji "Połącz" w prawym górnym rogu upewnij się, że przestrzeń nazw to "root\cimv2".
  • W obszarze "IWbemServices" kliknij pozycję "Zapytanie"
  • Wprowadź zapytanie w wyświetlonym polu edycji i kliknij pozycję "Zastosuj".

UWAGA: Element "IWbemService" ma kilka innych opcji, które mogą pomóc w zapytaniu. Na przykład użycie opcji "Klasy wyliczeniowe" i ustawienie przycisku radiowego na "rekursywne" pozwoli zobaczyć wszystkie klasy WMI w systemie.

Pobieranie właściwości zapytanych przy użyciu zapytania usługi WMI

Do tej pory masz pomysł, jak wymyślić zapytanie WMI dla metody testowej i jak zastosować je jako metadane podczas tworzenia testu. Wiesz również, jak potwierdzić, że zapytanie jest prawidłowe przy użyciu wbemtest.exe. Zobaczmy teraz, jak pobrać szukane wartości właściwości.

Podstawy pobierania tych informacji są bardzo podobne do pobierania wartości dla testu opartego na danych. Na przykład w kodzie zarządzanym będzie to wyglądać następująco:

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}

Wiersze 24–30 w powyższym przykładzie są dokładnie tym, co jest wymagane dla zarządzanego testu opartego na danych. Zdefiniowano prywatną właściwość TestContext i podano publiczne akcesory: get i set, aby TAEF mógł ustawić odpowiednie wartości. Korzystając z prywatnej właściwości TestContext, możesz pobrać bieżącą wartość dla dowolnych właściwości obiektu wynikowego zapytania WMI pobranych z funkcji TAEF.

Kod natywny do pobierania właściwości usługi WMI jest bardzo podobny. Podobnie jak w przypadku natywnych testów opartych na danych, użyjesz funkcji TestData, aby uzyskać wartości właściwości. Rozważmy na przykład test pobierania właściwości drukarki domyślnej. Plik nagłówkowy tworzy ten test w następujący sposób:

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()

W tym celu nasz kod pobierania w pliku cpp wygląda następująco:

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    }

Uwzględnianie możliwych wartości właściwości NULL

Należy pamiętać, że zapytanie WMI może nie zawsze zwracać właściwość inną niż null. Czasami zwracana wartość właściwości WMI to "null". Jeśli uważasz, że właściwość, której szukasz, może mieć wartość "null" w niektórych scenariuszach, sprawdź ją przed zweryfikowaniem lub podjęciem próby jej użycia.

Na przykład w zarządzanym kodzie testowym TestContext będzie przechowywać wartości null jako obiekt typu DBNull. Przed podjęciem próby rzutowania wynikowej wartości do typu, którego się oczekuje, należy sprawdzić, czy obiekt jest typu DBNull. Przyjrzyjmy się:

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}

Na przykład w powyższym teście wartości "Skompresowane", "MaximumComponentLength" i "Dostępność" mogą być null w niektórych scenariuszach (gdy zapytanie zwraca napędy wymienne, takie jak dyskietki). Chcesz upewnić się, że test działa odpowiednio w takich przypadkach. W tym celu pobierz wartość właściwości jako obiekt i sprawdź, czy jego typ to "DBNull". Jeśli tak jest, oznacza to, że zwrócona wartość właściwości ma wartość null. Jeśli tak nie jest, zwrócona wartość nie miała wartości null i dlatego prawidłowa — dlatego rzutuj ją do odpowiednich typów i użyj jej do testowania.

To samo dotyczy również natywnych interfejsów API pobierania, zwracana wartość właściwości może być NULL. Oznacza to, że należy sprawdzić, czy TestData pomyślnie pobrały wartość bez użycia wywołania weryfikacyjnego (gdyż niemożność pobrania może być spowodowana tym, że wartość jest równa null). Na przykład możesz mieć metodę testową, która zależy od zapytania WMI:

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()

Wartości "Dostępność" i "MaximumComponentLength" mogą być zwracane jako wartości NULL. Napisz test, aby uwzględnić to w następujący sposób:

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    }