Compartir a través de


Origen de datos de tabla

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

Ahora que tiene la automatización de pruebas básica escrita y trabajando con TAEF, puede concentrarse en escenarios en los que se puede usar el mismo código de prueba para trabajar en diferentes conjuntos de datos. Para ello, TAEF proporciona un enfoque "basado en tablas" para las pruebas controladas por datos. Echemos un vistazo a un ejemplo sencillo para comprender cómo crear una prueba controlada por datos.

Considere un ejemplo sencillo no controlado por datos en el que va a imprimir el tamaño y el tema en la consola. En este ejercicio, convertirá esta prueba en una prueba controlada por datos.

1  namespace WEX { namespace TestExecution { namespace Examples
2  {
3     void DataDrivenTests::FirstTable()
4     {
5         int size = 12;
6         Log::Comment(String().Format(L"Size retrieved was %d", size));
7     }
8
9     void DataDrivenTests::SecondTable()
10    {
11        String theme = "Aero";
12        Log::Comment(L"Theme supplied as " + theme);
13    }
14 } /* namespace Examples */ } /* namespace TestExecution */ } /* namespace WEX */

Definición de los datos

Ahora, quiere que la función anterior funcione para un conjunto de tamaños y temas. En otras palabras, desea valores de datos variantes que nuestra función puede consumir. Para ello, defina dos tablas en un archivo XML DataDrivenTests.xml :

1  <?xml version="1.0"?>
2  <Data>
3  <Table Id ="Table1">
4          <ParameterTypes>
5                  <ParameterType Name="Size">Int32</ParameterType>
6                  <ParameterType Name="Color">String</ParameterType>
7                  <ParameterType Name="Transparency">Boolean</ParameterType>
8          </ParameterTypes>
9          <Row Priority="1" Owner="C2">
10                 <Parameter Name="Size">12</Parameter>
11                 <Parameter Name="Color">Blue</Parameter>
12                 <Parameter Name="Transparency">True</Parameter>
13         </Row>
14         <Row Priority="2" Owner="wex">
15                 <Parameter Name="Size">4</Parameter>
16                 <Parameter Name="Color">White</Parameter>
17                 <Parameter Name="Transparency">False</Parameter>
18         </Row>
19         <Row Owner="C2">
20                 <Parameter Name="Size">9</Parameter>
21                 <Parameter Name="Color">Black</Parameter>
22                 <Parameter Name="Transparency">True</Parameter>
23         </Row>
24 </Table>
25 <Table id ="Table2">
26         <Row Description="ButtonTest" Owner="C2" Priority="1">
27                 <Parameter Name="Control">Button</Parameter>
28                 <Parameter Name="Theme">Aero</Parameter>
29         </Row>
30         <Row Description="ComboBoxTest" Priority="2">
31                 <Parameter Name="Control">ComboBox</Parameter>
32                 <Parameter Name="Theme">Classic</Parameter>
33         </Row>
34         <Row Description="ListviewTest" Owner="wex">
35                 <Parameter Name="Control">Listview</Parameter>
36                 <Parameter Name="Theme">AeroBasic</Parameter>
37         </Row>
38 </Table>
39 </Data>

Ahora ha definido dos tablas, "Table1" y "Table2". Puede definir tablas para varios métodos de prueba en el mismo archivo XML.

Observe que, en Table1, definió parameterTypes por adelantado y eligió "Size" para ser un entero. La sección ParameterTypes es opcional. De forma predeterminada, si no se proporciona información de tipo de parámetro, se guardará como una cadena. Este es el caso de todos los parámetros de "Table2".

Cada "Fila" definida dentro de una tabla es un conjunto de valores de datos (parámetro) que desea que acepte la función de prueba. Las líneas 9, 14 y 19 definen 3 conjuntos de datos que aceptaría nuestra función FirstTable. De forma similar, las líneas 26, 30 y 34 definen los conjuntos de datos para SecondTable.

Observe las líneas 9, 14, 19, 26, 30 y 34 en el ejemplo anterior: puede definir metadatos específicos de la fila. Ahora hay una manera de cambiar la información de metadatos con conjuntos de datos para la misma función. La prioridad del primer conjunto de datos (línea 9) es 1, la prioridad para el segundo conjunto de datos (línea 14) es 2 y el tercer conjunto de datos (línea 19) tiene como valor predeterminado la prioridad de la función. Todas las filas heredan los metadatos de la función a la que está asociada la tabla. Si los mismos metadatos se especifican de nuevo en el nivel de fila, invalidará los valores de metadatos definidos en el nivel de función.

NOTA: La definición del esquema de archivo XML es la misma para el código nativo y administrado, excepto para las definiciones de tipo admitidas. Consulte la parte inicial de la sección "Prueba controlada por datos administrados" a continuación para obtener otro ejemplo de cómo definir los datos. Continúe con Pruebas controladas por datos nativos para comprender los tipos permitidos en código nativo.

Prueba controlada por datos nativos

Con los conjuntos de datos definidos y listos para su consumo, ahora necesita una manera de calificar la función de prueba como una prueba controlada por datos y asociarla a la tabla que define el conjunto de datos. Esto se realiza mediante metadatos adicionales durante la creación de la prueba:

1  namespace WEX { namespace TestExecution { namespace Examples
2  {
3      class DataDrivenTests
4      {
5          TEST_CLASS(DataDrivenTests);
6
7          BEGIN_TEST_METHOD(SecondTable)
8              TEST_METHOD_PROPERTY(L"DataSource", L"Table:DataDrivenTests.xml#Table2")
9              TEST_METHOD_PROPERTY(L"Priority", L"3")
10         END_TEST_METHOD()
11
12         BEGIN_TEST_METHOD(FirstTable)
13             TEST_METHOD_PROPERTY(L"Priority", L"4")
14             TEST_METHOD_PROPERTY(L"DataSource", L"Table:DataDrivenTests.xml#Table1")
15         END_TEST_METHOD()
16     };
17 } /* namespace Examples */ } /* namespace TestExecution */ } /* namespace WEX */

Para asociar la tabla XML con la prueba, agregue los metadatos "DataSource" al método de la prueba. A través de esta asociación TAEF usará el DataSource dado para conducir la prueba. El valor dataSource tiene tres partes:

  1. 'Table:': identifica el origen de datos como una tabla XML.
  2. 'DataDrivenTests.xml': este es el archivo que contiene la tabla XML.
  3. '#Table2': después del delimeter '#', el valor 'Table2' identifica la tabla concreta dentro del documento XML que se va a usar. Un único origen de datos de tabla XML puede contener varias tablas. TAEF examinará el archivo XML de un elemento Table con un atributo "Id" que coincida con el valor especificado.

Es posible que haya observado en el ejemplo anterior que "SecondTable" se define antes de "FirstTable". Esto significa que la función "SecondTable" se ejecutará antes de la función "FirstTable", pero definió "Table1", la tabla correspondiente a "FirstTable", antes de "Table2", la tabla correspondiente a "SecondTable". Esto es para destacar que el orden de la definición de tabla es irrelevante durante la detección y ejecución de las pruebas controladas por datos.

Con la asignación de nuestro origen de datos al método de prueba completado, ahora puede modificar el ejemplo para obtener los datos del origen. Antes de hacerlo, eche un vistazo al archivo de encabezado publicado, TestData.h. La parte de interés es:

1    class TestData
2    {
3    public:
4        template <typename T>
5        static HRESULT __stdcall TryGetValue(_In_z_ const wchar_t* pszString, T& result)
6        {
7            return Private::TestData<T>::TryGetValue(pszString, result);
8        }
9    };

La línea 5 muestra la API a la que llamar para recuperar los datos de la función. Eche un vistazo a los tipos de parámetros disponibles para su recuperación.

Ok: todo establecido para volver a escribir nuestro ejemplo:

1  namespace WEX { namespace TestExecution { namespace Examples
2  {
3      void DataDrivenTests::FirstTable()
4      {
5          Log::Comment(L"I am in first table");
6          int size;
7          if (SUCCEEDED(TestData::TryGetValue(L"size", size)))
8          {
9              VERIFY_ARE_NOT_EQUAL(size, 0);
10             Log::Comment(String().Format(L"Size retrieved was %d", size));
11         }
12     }
13
14     void DataDrivenTests::SecondTable()
15     {
16         Log::Comment(L"I am in second table.");
17         String theme;
18         if (SUCCEEDED(TestData::TryGetValue(L"theme", theme)))
19         {
20             Log::Comment(L"Theme supplied as " + theme);
21         }
22     }
23 } /* namespace Examples */ } /* namespace TestExecution */ } /* namespace WEX */

Las líneas 7 y 18 son las partes principales que han cambiado para hacer que los datos de prueba estén controlados. No es un gran cambio. Eche un vistazo a La ejecución de pruebas controladas por datos para comprender cómo sacar el máximo partido de TAEF al ejecutar pruebas controladas por datos.

Prueba controlada por datos administrados

Considere un ejemplo en el que desea imprimir las coordenadas de un rectángulo en la consola. Comience por definir estas coordenadas como conjunto de datos en un archivo XML.

1  <?xml version="1.0"?>
2  <Data>
3  <Table Id="FirstTable">
4          <ParameterTypes>
5                  <ParameterType Name="Left">Int32</ParameterType>
6                  <ParameterType Name="Right">String</ParameterType>
7                  <ParameterType Name="Top">Integer</ParameterType>
8                  <ParameterType Name="Bottom">Int32</ParameterType>
9          </ParameterTypes>
10         <Row Priority="1" Owner="C2" Description="Zero rect">
11                 <Parameter Name="Left">0</Parameter>
12                 <Parameter Name="Right">0</Parameter>
13                 <Parameter Name="Top">0</Parameter>
14                 <Parameter Name="Bottom">0</Parameter>
15         </Row>
16         <Row Priority="2" Owner="wex" Description="normal rect">
17                 <Parameter Name="Left">12</Parameter>
18                 <Parameter Name="Right">25</Parameter>
19                 <Parameter Name="Top">10</Parameter>
20                 <Parameter Name="Bottom">50</Parameter>
21         </Row>
22         <Row Owner="C2" Description="invalid rect">
23                 <Parameter Name="Left">30</Parameter>
24                 <Parameter Name="Right">15</Parameter>
25                 <Parameter Name="Top">40</Parameter>
26                 <Parameter Name="Bottom">10</Parameter>
27         </Row>
28 </Table>
29 </Data>

Defina el conjunto de datos en el ámbito de una tabla, en este caso "FirstTable", que se define en la línea 3 anterior. Puede definir tablas para varios métodos de prueba en el mismo archivo XML.

Observe que FirstTable define parameterTypes por adelantado y llama a "Left" para que sea "Int32". La sección ParameterTypes es opcional. De forma predeterminada, si no se proporciona información de tipo de parámetro, se guardará como una cadena.

Eche un vistazo a la lista de tipos de parámetros admitidos.

Si se especifica cualquier otro tipo de datos, la prueba producirá una advertencia y considerará que es una cadena.

NOTA: Las cadenas de tipo no distinguen mayúsculas de minúsculas, pero deben ortografía exactamente como se muestra anteriormente.

Cada "Fila" definida dentro de una tabla es un conjunto de valores de datos (parámetro) que desea que acepte la función de prueba. Las líneas 10, 16 y 22 definen tres conjuntos de datos que nuestra función.

Observe las líneas 10, 16 y 22 del ejemplo anterior: puede definir metadatos específicos de Row. Ahora tiene una manera de que la información de metadatos cambie con conjuntos de datos para la misma función. La prioridad del primer conjunto de datos (línea 10) es 1, la prioridad para el segundo conjunto de datos (línea 16) es 2 y el tercer conjunto de datos (línea 22) tiene como valor predeterminado la prioridad de la función. Todas las filas heredan los metadatos de la función a la que está asociada la tabla. Si los mismos metadatos se especifican de nuevo en el nivel de fila, invalidará los valores de metadatos definidos en el nivel de función.

NOTA: La definición del esquema de archivo XML es la misma para el código nativo y administrado, excepto para las definiciones de tipo admitidas. Eche un vistazo a la sección "Definir los datos" en la parte superior de esta página para ver otro ejemplo de cómo definir esto.

Ahora, tiene todos los datos definidos. En el ejemplo siguiente se muestra cómo acceder a él.

1  namespace WEX.Examples
2  {
3      using Microsoft.VisualStudio.TestTools.UnitTesting;
4      using System;
5      using System.Collections;
6      using WEX.Logging.Interop;
7      using WEX.TestExecution;
8
9      [TestClass]
10     public class CSharpDataDrivenTests
11     {
12         [TestMethod]
15         [DataSource("Table:CSharpDataDrivenTests.xml#FirstTable")]
16         public void First()
17         {
18             Console.WriteLine("Left is " + m_testContext.DataRow["Left"].ToString());
19
20             Log.Comment("In CSharpDataDrivenTests.First");
21         }
22
23         [TestMethod]
24         public void Second()
25         {
26             Log.Comment("In CSharpDataDrivenTests.Second");
27             Verify.IsTrue(true);
28         }
29
30         public TestContext TestContext
31         {
32             get { return m_testContext; }
33             set { m_testContext = value; }
34         }
35
36         private TestContext m_testContext;
37     }
38 }

Asociar la tabla XML con un método de prueba determinado en código administrado es muy similar al código nativo; simplemente aplique los metadatos "DataSource". Como antes, consta de tres partes:

  1. 'Table:': para identificar el origen de datos como una tabla XML.
  2. 'CSharpDataDrivenTests.xml': el archivo que contiene la tabla XML.
  3. '#FirstTable': después del delimeter '#', el valor 'FirstTable' identifica la tabla concreta dentro del documento XML que se va a usar. TAEF examinará el archivo XML de un elemento Table con un atributo "Id" que coincida con el valor especificado.

Observe que la función Second no está controlada por datos. Puede optar por tener solo algunas de las pruebas para que estén controladas por datos. También tiene la opción de hacer que cada prueba tenga su tabla definida en un archivo XML diferente.

En la línea 36, se define una propiedad TestContext privada, como VSTS, recomienda la clase TestContext. También se definen evaluadores públicos para esta propiedad (líneas 30 a 34). TAEF internamente carga la propiedad de diccionario de TestContext con el conjunto de datos correspondiente en el foco.

TestContext se define en Microsoft.VisualStudio.TestTools.UnitTesting. Vea la línea 3 en el ejemplo anterior. Ya debería incluir esto como referencia en la creación de pruebas administradas. Por lo tanto, no se requieren referencias adicionales para crear pruebas controladas por datos.

En la línea 18 del ejemplo anterior, se muestra cómo recuperar datos en la función . Observe que los datos están disponibles en m_testContext.DataRow.

Nombre en lugar de Index para identificar un dataRow

TAEF le permite tener una propiedad 'Name' más significativa en lugar del Índice para identificar cualquier DataRow en el origen de datos. Para ello, basta con agregar metadatos de "Nombre" en el nivel de fila del origen de datos. Nuestro primer ejemplo en esta página se puede modificar para usar esta característica de la siguiente manera:

1  <?xml version="1.0"?>
2  <Data>
3  <Table id ="Table1">
4          <ParameterTypes>
5                  <ParameterType Name="Size">Int32</ParameterType>
6                  <ParameterType Name="Color">String</ParameterType>
7                  <ParameterType Name="Transparency">Boolean</ParameterType>
8          </ParameterTypes>
9          <Row Name='BlueTransparent' Priority="1" Owner="C2">
10                 <Parameter Name="Size">12</Parameter>
11                 <Parameter Name="Color">Blue</Parameter>
12                 <Parameter Name="Transparency">True</Parameter>
13         </Row>
14         <Row Priority="2" Owner="wex">
15                 <Parameter Name="Size">4</Parameter>
16                 <Parameter Name="Color">White</Parameter>
17                 <Parameter Name="Transparency">False</Parameter>
18         </Row>
19         <Row Name='BlackTransparent' Owner="C2">
20                 <Parameter Name="Size">9</Parameter>
21                 <Parameter Name="Color">Black</Parameter>
22                 <Parameter Name="Transparency">True</Parameter>
23         </Row>
24 </Table>
25 ...
39 </Data>

En el ejemplo anterior modificado, "BlueTransparent" corresponde al índice 0. La fila con el índice 1 no tiene ningún nombre especial y la fila con el índice 2 tiene el nombre 'BlackTransparent asociado a él. Todavía puede usar una consulta de selección para buscar el índice 0 o 2 en "Table1", y encontrará la fila correcta. Pero, al ejecutar o enumerar el archivo DLL, en lugar de ver:

<qualified name of the test method>#<index>

en su lugar verá lo siguiente:

<qualified name of the test method>#<name property provided at Row level>

para las filas donde se proporciona el atributo "Name" en el nivel De fila. Si la propiedad "Name" no se proporciona para ninguna fila, como en el caso del índice 1 anterior, tendrá como valor predeterminado <#index> en el nombre completo del método.

Tenga en cuenta que, a modo de proporcionar un atributo "Name" en el nivel de fila, básicamente está cambiando la forma en que TAEF interpreta el nombre de la instancia de la invocación del método con los datos row correspondientes.

DataSource como parámetro en tiempo de ejecución

TAEF admite el suministro del origen de datos como parámetro en tiempo de ejecución. La sintaxis para esto es la siguiente:

te <test dll names> /p:<DataSource runtime name>=Table:<DataSoure XML file>#<Table Id>

Al crear la prueba en cuestión, debe especificar el "nombre> en tiempo de ejecución p:<DataSource" como origen de datos. Tenga en cuenta que debe especificar la cadena completa ( el nombre de archivo XML, así como el identificador de tabla juntos ) en tiempo de ejecución. No se espera que el tableId se proporcione como metadatos de prueba si el origen de datos se proporciona en tiempo de ejecución. El prefijo "Table:" especifica que busca un origen de datos de tabla.

Puede probar esto con uno de los ejemplos disponibles en el recurso compartido de versión:

te Examples\CPP.RuntimeDataSource.Example.dll /p:MyDataSource=Table:RuntimeDataSourceExample.xml#SimpleTable

DataSource como un recurso

TAEF le permite agregar su DataSource como un recurso del módulo de prueba siempre que se ajuste a lo siguiente:

En el caso de los módulos de prueba nativos, puede hacerlo especificando dataSource como el identificador de recurso o el nombre del recurso. Este es un ejemplo de código:

BEGIN_TEST_METHOD(ResourceNameDataSource)
    TEST_METHOD_PROPERTY(L"DataSource", L"Table:MyResourceName#SimpleTable")
END_TEST_METHOD()

"MyResourceName" es el nombre del recurso tal y como se define en el archivo ResourceDataSource.rc en este caso:

MyResourceName DATASOURCE_XML "ResourceDataSource.xml"

En el caso de los módulos de prueba administrados, el recurso solo se puede especificar de una manera determinada, como se muestra en el fragmento de código de archivo de orígenes que se muestra a continuación:

LANGUAGE_NEUTRAL_MANAGED_RESOURCES = CSharpAdvancedDataDrivenTests.xml

La especificación de metadatos dataSource seguirá siendo la misma que en el caso de especificar el archivo XML dataSource. De forma similar al caso en el código administrado, podría hacer que el nombre del recurso sea el mismo que el nombre de archivo XML. Por lo tanto, es importante comprender que TAEF buscará primero la presencia del archivo real con el nombre DataSource. Si no se encuentra este archivo XML, solo continuará con la búsqueda de recursos de prueba en el módulo de prueba con el nombre o el identificador de recurso especificados. Dado que la especificación de DataSource como un recurso requiere volver a compilar, puede aprovechar este diseño copiando el archivo XML dataSource en la misma ubicación que el archivo DLL de prueba mientras desarrolla (y asigna un nombre al nombre del recurso para que sea el mismo que el nombre del archivo XML). Una vez que haya terminado de probar, vuelva a copiar el XML en el directorio de código y vuelva a compilarlo como un recurso. No olvide eliminar el archivo XML del directorio de ejecución. :)

Tutoriales de ejemplo

Para comprender varios aspectos de las pruebas basadas en datos basados en tablas, lea algunos tutoriales de ejemplo más: