共用方式為


WMI 資料來源

請先確定您已熟悉 TAEF 的基本執行,並知道如何使用它撰寫測試,再繼續進行本節。

背景

「WMI」 代表 「Windows Management Instrumentation」。 使用通用訊息模型 (CIM) ,這是代表系統的業界標準。 Windows Management Instrumentation 提供存取系統管理資訊的統一方式。

其如何協助我的測試?

您可以使用 WMI 查詢支援作為 TAEF 中的 WMI DataSource,在測試中新增前置條件,以及在執行測試之前取得測試機器上資源的相關資訊。 以下是您可以使用 WMI 進行之查詢類型的一些範例:

  • 檢查測試執行所在的電腦是否為膝上型電腦,且只有在其為膝上型電腦時才執行測試。
  • 檢查測試機器上是否已安裝 Service Pack,並只在已安裝時執行測試。
  • 擷取測試電腦上的所有抽取式磁片磁碟機和本機硬碟,並針對符合查詢的每個磁片磁碟機執行測試。
  • 只有在測試電腦未加入網域或時,才執行測試
  • 只有在測試電腦已加入網域並擷取功能變數名稱時,才執行測試。

這可希望您瞭解 WMI DataSource 在何處及如何運用 WMI DataSource 進行測試。 讓我們看看如何在撰寫 TAEF 測試時新增此 WMI 查詢支援。

您唯一需要讓測試成為 WMI DataSource 測試的特殊中繼資料是 「DataSource」。 DataSource 語法必須如下所示:

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

或在機器碼中:

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

您必須注意到,DataSource 值開頭為 「WMI:」,這可讓 TAEF 知道這確實是相依于 WMI 查詢結果之測試的資料來源,也會區分它與資料驅動測試。 這是一個很好的機會,提及目前 TAEF 不支援同時進行測試 - 資料驅動測試,以及相依于 WMI 查詢結果的測試。

下一個問題自然是如何撰寫您要尋找的 WQL 查詢? WQL 查詢語法非常類似于簡化的 SQL 查詢。 腳本 和應用程式的 WMI 工作中提供一些非常良好的查詢範例。 以下是一些範例:

SELECT Description, DesktopInteract, ProcessId FROM Win32_Service WHERE Name='Themes'
在找出您想要在測試中使用的 Description、DesktopInteract 和 ProcessId 屬性之後,在 「Themes」 服務上執行測試。

SELECT 功能、功能描述 FROM Win32_Printe
針對連線到這部電腦的每部印表機執行測試。 允許測試存取每部印表機的 Capabilities and CapabilityDescriptions。

SELECT Name, User, Location FROM Win32_StartupCommand
針對在 Windows 啟動時執行的每個進程執行測試。 針對每個進程,讓測試知道進程的名稱、其所在位置 (位置) ,以及進程執行身分的使用者。

您可以在上述檔以及您已開啟的範例中找到 .cs 檔案和標頭檔中的更多範例。 一般、過度簡化的語法如下所示:

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

在剛才看到的範例中,Win32_Service、Win32_Printer和Win32_StartupCommand都是 WMI 類別。 您可以在 WMI 類別中查閱 WMI 類別

TAEF 不支援擷取系統屬性。

幕後 TAEF 會為您執行查詢,並確認結果。 如果查詢結果至少傳回一個物件,則會針對每個傳回的物件執行測試。 如果 WQL 查詢未傳回任何物件,測試會記錄為 「封鎖」,並使用此資訊執行繼續進行下一個測試。

在撰寫測試之前檢查或驗證您的查詢似乎相當好主意,而且是非常簡單的程式:

  • 從執行對話方塊或命令提示字元叫用 「wbemtest.exe」
  • 按一下右上角的 [連線] 按鈕。
  • 請先確定您的命名空間是 「root\cimv2」,然後再按一下右上角的 [連線]。
  • 在 [IWbemServices] 下,按一下 [查詢]
  • 在出現的編輯方塊中輸入您的查詢,然後按一下 [套用]

注意:「IWbemService」 有數個其他選項可協助您進行查詢。 例如,使用 「列舉類別」,並將選項按鈕變更為「遞迴」將可協助您查看系統上的所有 WMI 類別。

使用 WMI 查詢擷取查詢的屬性

現在,您已瞭解如何針對測試方法提出 WMI 查詢,以及如何在撰寫測試時將它套用為中繼資料。 您也知道如何使用 wbemtest.exe 確認查詢有效。 現在讓我們看看如何擷取您要尋找的屬性值。

擷取這項資訊的基本概念與擷取資料驅動測試的值非常類似。 例如,在 Managed 程式碼中,如下所示:

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}

上述範例中的第 24-30 行完全是 Managed 資料驅動測試所需的專案。 您已定義私人 TestCoNtext 屬性,並在其上提供公用 getter 和 setter,讓 TAEF 設定正確的值。 使用私人 TestCoNtext 屬性,您可以擷取任何從 TAEF 擷取之 WMI 查詢結果物件屬性的目前值。

擷取 WMI 屬性的機器碼非常類似。 如同原生資料驅動測試,您將使用 TestData 來取得屬性值。 例如,讓我們考慮測試以取得預設印表機的屬性。 標頭檔作者此測試如下:

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

為此,我們在 cpp 檔案中的擷取程式碼如下所示:

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    }

考慮可能的 Null 屬性值

請記住,WMI 查詢不一定會傳回非 Null 屬性。 有時傳回的 WMI 屬性值為 「null」。 如果您認為您正在尋找的屬性在某些情況下可能是「null」,請在驗證或嘗試使用它之前先檢查它。

例如,在 Managed 測試程式碼中,TestCoNtext 會將 Null 值儲存為 DBNull 類型的物件。 您必須先檢查物件是否為 DBNull 類型,然後才嘗試將結果值轉換成您預期的類型。 讓我們來看看:

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}

例如,在上述測試中,當查詢傳回磁片磁碟機,例如磁碟片磁片磁碟機) 時, (在某些情況下,「Compressed」、「MaximumComponentLength」 和 「Availability」 可為 null。 您想要確定測試在這類情況下會適當運作。 在此結尾,將屬性值擷取為物件,並檢查其類型是否為 「DBNull」。 如果是,則表示傳回的屬性值為 null。 如果不是,傳回的值不是 Null,因此有效,因此請將其轉換成適當的類型,並將其用於測試。

原生擷取 API 也是如此 ,傳回的屬性值可以是 Null。 這表示您需要檢查 TestData 是否成功擷取值,而不使用驗證呼叫 (,因為無法擷取可能是因為值為 null) 。 例如,您可能有一個相依于 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()

您可能會將 「Availability and 」MaximumComponentLength「 傳回為 Null 值。 因此,請撰寫測試以考慮此情況,如下所示:

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    }