閱讀英文

共用方式為


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    }