Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Убедитесь, что вы знакомы с базовым выполнением TAEF и знаете, как создавать тесты с помощью этого раздела, прежде чем продолжить работу с этим разделом.
Контекст
WMI означает "Инструментирование управления Windows". Использование общей информационной модели (CIM), которая является отраслевым стандартом для представления систем. Инструментирование управления Windows обеспечивает единый способ доступа к сведениям об управлении системой.
Как это помогает моим тестам?
Используя поддержку запросов WMI, доступную в качестве WMI DataSource в TAEF, можно добавить предварительные условия для теста, а также получить сведения о ресурсах на тестовом компьютере перед выполнением теста. Ниже приведены некоторые примеры типа запроса, который можно сделать с помощью WMI:
- Проверьте, работает ли тест на ноутбуке и запустите тест только в том случае, если он ноутбук.
- Проверьте, установлен ли пакет обновления на тестовом компьютере и запустите тест только в том случае, если он был.
- Извлеките все съемные диски и локальные жесткие диски на тестовом компьютере и запустите тест для каждого диска, соответствующего запросу.
- Запустите тест только в том случае, если тестовый компьютер не присоединен к домену ИЛИ
- Запустите тест, только если тестовый компьютер присоединен к домену и извлекает доменное имя.
Это, надеюсь, дало вам некоторую идею о том, где и как можно использовать WMI DataSource для тестирования. Давайте рассмотрим, как добавить поддержку запросов WMI при создании теста TAEF.
Единственными специальными метаданными, которые необходимо, чтобы ваш тест стал тестом 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, DesktopInteract, ProcessId FROM Win32_Service WHERE Name='Темы'
Запустите тест в службе "Темы" после получения его описания, свойств DesktopInteract и ProcessId, которые вы планируете использовать в тестировании.
Возможности SELECT, CapabilityDescriptions FROM Win32_Printe
Запустите тест для каждого принтера, подключенного к этому компьютеру. Разрешите тесту доступ к возможностям и описаниям возможностей для каждого принтера.
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. Теперь давайте рассмотрим, как получить значения свойств, которые вы искали.
Основы получения этой информации очень похожи на получение значений для теста на основе данных. Например, в управляемом коде это будет выглядеть следующим образом:
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 в приведенном выше примере являются именно тем, что требуется для управляемого теста на основе данных. Вы определили закрытое свойство TestContext и предоставили для него публичные геттер и сеттер, чтобы TAEF мог задать правильные значения. Используя частное свойство TestContext, можно получить текущее значение для любого из свойств результирующих объектов WMI, полученных из TAEF.
Нативный код для получения свойств 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 в некоторых сценариях, проверьте его перед проверкой или попыткой его использования.
Например, в управляемом коде теста 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}
Например, в приведенном выше тесте "Сжатый", "MaximumComponentLength" и "Availability" может иметь значение NULL в некоторых сценариях (когда запрос возвращает съемные диски, такие как диски floppy). Вы хотите убедиться, что тест работает правильно в таких случаях. С этой целью извлеките значение свойства как объект и проверьте, имеет ли оно тип 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" и "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 }