Compartir a través de


Origen de datos WMI

Asegúrese de que está familiarizado con la ejecución básica de TAEF y sabe cómo crear pruebas con ella antes de continuar con esta sección.

Fondo

"WMI" significa "Instrumental de administración de Windows". Uso del modelo de información común (CIM), que es el estándar del sector para representar sistemas. Instrumental de administración de Windows proporciona una manera unificada de acceder a la información de administración del sistema.

¿Cómo ayuda mis pruebas?

Con la compatibilidad con consultas WMI disponible como DataSource de WMI en TAEF, puede agregar una condición previa a la prueba, así como obtener información sobre los recursos de la máquina de prueba antes de ejecutar la prueba. Estos son algunos de los ejemplos del tipo de consulta que podría realizar mediante WMI:

  • Compruebe si la máquina en la que se ejecuta la prueba es un portátil y ejecute la prueba solo si es un portátil.
  • Compruebe si se ha instalado un Service Pack en la máquina de prueba y ejecute la prueba solo si ha sido.
  • Recupere todas las unidades extraíbles y las unidades de disco duro locales en el equipo de prueba y ejecute la prueba para cada una de las unidades que coincidan con la consulta.
  • Ejecute la prueba solo si la máquina de prueba no está unida a un dominio O
  • Ejecute la prueba solo si la máquina de prueba está unida a un dominio y recupera el nombre de dominio.

Eso le habría dado alguna idea sobre dónde y cómo puede aprovechar WMI DataSource para las pruebas. Veamos cómo agregar esta compatibilidad con consultas WMI al crear una prueba TAEF.

Los únicos metadatos especiales que necesita para hacer que la prueba sea una prueba de WMI DataSource es "DataSource". La sintaxis de DataSource debe tener el siguiente aspecto:

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

O en código nativo:

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

Debe haber observado que el valor dataSource comienza por "WMI:", lo que permite a TAEF saber que es realmente el origen de datos de una prueba que depende del resultado de la consulta WMI y también lo distingue de la prueba controlada por datos. Esta es una buena oportunidad para mencionar que actualmente TAEF no admite una prueba para ser ambas: una prueba controlada por datos, así como una prueba que depende del resultado de la consulta WMI.

La siguiente pregunta naturalmente es cómo escribir consultas WQL para lo que está buscando? La sintaxis de consulta WQL es muy similar a las consultas SQL simplificadas. Hay algunos ejemplos muy buenos de consultas proporcionadas en tareas de WMI para scripts y aplicaciones. Estos son algunos ejemplos:

SELECT Description, DesktopInteract, ProcessId FROM Win32_Service WHERE Name='Themes'
Ejecute la prueba en el servicio "Temas" después de averiguar que se trata de las propiedades Description, DesktopInteract y ProcessId que quiere usar en las pruebas.

SELECT Capabilities, CapabilityDescriptions FROM Win32_Printe
Ejecute la prueba para cada impresora conectada a este equipo. Permita que la prueba tenga acceso a las funcionalidades y capabilityDescriptions de cada impresora.

SELECT Name, User, Location FROM Win32_StartupCommand
Ejecute la prueba para cada proceso que se ejecute en el inicio de Windows. Para cada proceso, la prueba sepa cuál es el nombre del proceso, dónde se encuentra (ubicación) y qué usuario ejecuta el proceso.

Puede encontrar más ejemplos en la documentación mencionada anteriormente, así como en el archivo .cs y el archivo de encabezado en los ejemplos que ha abierto. La sintaxis general y simplificada es la siguiente:

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

En los ejemplos que acaba de ver, Win32_Service, Win32_Printer y Win32_StartupCommand son todas las clases WMI. Puede buscar las clases WMI en las clases WMI.

TAEF no admite la recuperación de propiedades del sistema.

Detrás de la escena TAEF ejecutará la consulta automáticamente y confirmará el resultado. Si se devuelve al menos un objeto como resultado de la consulta, la prueba se ejecuta para cada objeto devuelto. Si la consulta WQL no devuelve ningún objeto, la prueba se registra como Bloqueada con esta información y la ejecución pasa a la siguiente prueba.

Comprobar o comprobar la consulta antes de crear la prueba parece ser una buena idea y es un proceso muy sencillo:

  • Desde el cuadro de diálogo de ejecución o un símbolo del sistema, invoque "wbemtest.exe"
  • Haga clic en el botón "Conectar" en la esquina superior derecha.
  • Asegúrese de que el espacio de nombres es "root\cimv2" antes de volver a hacer clic en "Conectar" en la esquina superior derecha.
  • En "IWbemServices", haga clic en "Consulta".
  • Escriba la consulta en el cuadro de edición que aparece y haga clic en "Aplicar".

NOTA: "IWbemService" tiene otras opciones que podrían ayudarle con la consulta. Por ejemplo, el uso de "Enum Classes" y el cambio del botón de radio a "recursive" le ayudará a ver todas las clases WMI en el sistema.

Recuperación de propiedades consultadas mediante la consulta WMI

Ahora tiene una idea de cómo crear una consulta WMI para un método de prueba y cómo aplicarla como metadatos durante la creación de una prueba. También sabe cómo confirmar que la consulta es válida mediante wbemtest.exe. Ahora veamos cómo recuperar los valores de propiedad que estaba buscando.

Los conceptos básicos sobre la recuperación de esta información son muy similares a la recuperación de valores para la prueba controlada por datos. Por ejemplo, en el código administrado, tendría el siguiente aspecto:

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}

Las líneas 24-30 del ejemplo anterior son exactamente lo que se necesita para una prueba administrada controlada por datos. Ha definido una propiedad TestContext privada y ha proporcionado el captador público y el establecedor en él para que TAEF establezca los valores correctos. Con la propiedad testContext privada, puede recuperar el valor actual de cualquiera de las propiedades del objeto resultante de consulta WMI que recuperó de TAEF.

El código nativo para recuperar las propiedades WMI es muy similar. Al igual que con las pruebas nativas controladas por datos, usará TestData para obtener los valores de propiedad. Por ejemplo, vamos a considerar la prueba para obtener propiedades de la impresora predeterminada. El archivo de encabezado crea esta prueba de la siguiente manera:

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

Para ello, nuestro código de recuperación, en el archivo cpp tiene el siguiente aspecto:

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    }

Contabilidad de posibles valores de propiedad NULL

El elemento que se debe tener en cuenta es que es posible que la consulta WMI no siempre devuelva una propiedad que no sea NULL. Podría haber ocasiones en las que el valor de la propiedad WMI devuelto es "null". Si cree que la propiedad que busca podría ser "null" en algunos escenarios, compruébala antes de comprobarla o intentar usarla.

En el código de prueba administrado, por ejemplo, TestContext almacenará los valores NULL como un objeto de tipo DBNull. Debe comprobar si el objeto es de tipo DBNull antes de intentar convertir el valor resultante en el tipo que espera que sea. Observemos lo siguiente:

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}

Por ejemplo, en la prueba anterior, "Compressed", "MaximumComponentLength" y "Availability" pueden ser null en algunos escenarios (cuando la consulta devuelve unidades extraíbles como unidades de disquete). Quiere asegurarse de que la prueba se comporta correctamente en tales casos. Hacia este final, recupere el valor de la propiedad como un objeto y compruebe si es del tipo "DBNull". Si es así, significa que el valor de propiedad devuelto era NULL. Si no es así, el valor devuelto no era null y, por tanto, válido, así que lo convierta en los tipos adecuados y úselo para las pruebas.

Lo mismo ocurre con las API de recuperación nativas, pero el valor de propiedad devuelto podría ser NULL. Esto significa que debe comprobar si TestData recuperó correctamente el valor sin usar una llamada verify (ya que no se puede recuperar podría ser porque el valor es NULL). Por ejemplo, puede tener un método de prueba que dependa de una consulta 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()

Es posible que tenga "Availability" y "MaximumComponentLength" devueltos como valores NULL. Por lo tanto, escriba la prueba para tener en cuenta esto de esta manera:

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    }