Compatibilidad con dispositivos
Si la automatización de pruebas se basa en la presencia de dispositivos o recursos de prueba, consulte el ejemplo TestResourceExample y siga las instrucciones para aprovechar la compatibilidad con dispositivos o recursos de prueba disponibles en TAEF. Asegúrese de estar familiarizado con la creación de pruebas básicas mediante TAEF y la ejecución básica de TAEF antes de continuar.
Creación para la compatibilidad con dispositivos: archivo de orígenes
Se requiere Te.Common.lib además de otras bibliotecas necesarias para crear una prueba en TAEF.
Creación para la compatibilidad con dispositivos: definición de recursos de prueba
Los usuarios son responsables de crear su propia definición de recurso de prueba (dispositivo). Para ello, debe implementar ITestResource. ITestResource se define en el archivo de encabezado publicado ITestResource.h y tiene el siguiente aspecto:
namespace WEX { namespace TestExecution
{
namespace TestResourceProperty
{
// the following are reserved and must have properties for any TestResource definition
static const wchar_t c_szName[] = L"Name";
static const wchar_t c_szId[] = L"Id";
static const wchar_t c_szGuid[] = L"GUID";
static const wchar_t c_szType[] = L"Type";
}
struct __declspec(novtable) __declspec(uuid("79098e4c-b78d-434b-854d-2b59f5c4acc5")) ITestResource : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetGuid(GUID* pGuid) = 0;
virtual HRESULT STDMETHODCALLTYPE SetGuid(GUID guid) = 0;
virtual HRESULT STDMETHODCALLTYPE GetValue(BSTR name, BSTR* pValue) = 0;
virtual HRESULT STDMETHODCALLTYPE SetValue(BSTR name, BSTR value) = 0;
};
} /*namespace TestExecution*/ } /*namespace WEX*/
En nuestro ejemplo, la clase MyTestResource implementa la interfaz ITestResource COM. En ITestResource.h, también encontrará una lista de propiedades "must-have" definidas. Debe ser posible obtener el GUID del recurso de prueba mediante GetGuid(..) y el nombre, el identificador y el tipo del recurso mediante GetValue(...). Si falta alguno de estos elementos en testResource, TAEF lo considerará no válido y no mantendrá su información. (Consulte la sección sobre la "creación de la lista de recursos" maś adelante).
Creación para la compatibilidad con dispositivos: especificación de metadatos dependientes del recurso
Para especificar que el módulo de prueba tiene métodos de prueba dependientes del recurso de prueba, una propiedad de metadatos de nivel de módulo 'TestResourceDependent" debe establecerse en "true". Todas las clases del módulo de prueba y por todos los métodos de prueba de estas clases heredan la propiedad. Si alguno de los métodos de prueba del módulo no depende del recurso de prueba, debe volver a establecer explícitamente el valor de metadatos en false. Todos los demás métodos de prueba que dependen del recurso de prueba deben proporcionar una consulta de selección utilizando "Id" o "Type" del recurso de prueba.
Estos son algunos ejemplos rápidos de "ResourceSelection" para nuestra lista de recursos de ejemplo y lo que implica cada uno de ellos:
- "@Id='HD*'": coincide con cada recurso con un identificador a partir de "HD"
- "@Type='PCI'": coincide con cada recurso de tipo "PCI"
- "@Id='PCI*' OR @Id='HD*'": coincide con cada recurso a partir de "PCI" o empezando por "HD"
- "@Type='PCI' and @id='*37'": oincide con cada recurso de tipo "PCI" con un nombre que termina en "37"
En nuestro código de ejemplo, esto se ve así:
BEGIN_MODULE()
MODULE_PROPERTY(L"TestResourceDependent", L"true")
END_MODULE()
class TestResourceExample
{
TEST_CLASS(TestResourceExample);
BEGIN_TEST_METHOD(NoTestResourceTest)
TEST_METHOD_PROPERTY(L"TestResourceDependent", L"false")
END_TEST_METHOD()
BEGIN_TEST_METHOD(OneHDAudioTest)
TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Id='HD*'")
END_TEST_METHOD()
...
BEGIN_TEST_METHOD(HDorPCITest)
TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Id='PCI*' OR @Id='HD*'")
END_TEST_METHOD()
...
};
En el ejemplo anterior, observe que el módulo está marcado como "TestResourceDependent". NoTestResourceTest se marca explícitamente como no dependiente de ningún recurso de prueba al estqblecer los metadatos "TestRssourceDependent" en "false". Todos los demás métodos de prueba especifican un criterio de selección para los recursos de prueba que están interesados en ejecutar.
La gramática de criterios de selección es muy similar a la gramática de consulta de selección de línea de comandos disponible para TAEF. Sin embargo, en el caso de la selección de recursos, está restringido al uso de los tipos y el identificador de recurso. Dado que el identificador de recurso es una cadena, debe incluirse entre comillas simples. Puede usar los caracteres comodín "*" o "?" en la especificación del valor Id. En el ejemplo anterior, en OneHDAudioTest, la selección de recursos especifica una coincidencia con cualquier recurso en el que identificador comienza por "HD". Del mismo modo, en el caso de HDorPCITest, la selección de recursos coincidirá con cualquier recurso en el que identificador comience por "HD" o comience por "PCI". Es importante tener en cuenta que la selección de recursos no distingue mayúsculas de minúsculas; es decir, "pci", "Pci" y "PCI" se tratarán de la misma manera.
En función de la selección de recursos, TAEF volverá a invocar el método de prueba junto con los métodos de configuración y limpieza del nivel de prueba (si se especifican) una vez para cada recurso de prueba que coincida con la selección. En la siguiente sección se examinarán los detalles sobre cómo especificar la lista de recursos y proporcionarla a TAEF y, en la sección siguiente a esa, cómo el método de prueba puede recuperar los recursos.
Creación para la compatibilidad con dispositivos: creación de la lista de recursos
En cuanto TAEF encuentre un módulo de prueba TestResourceDependent, buscará e invocará el método dll exportado BuildResourceList. Este método se encuentra en la implementación de BuildResourceList, donde los usuarios pueden crear nuevos recursos de prueba y agregarlos a la interfaz que se pasa como parámetro a BuildResourceList. Echemos un vistazo a la implementación de este método en el ejemplo:
using namespace WEX::TestExecution;
HRESULT __cdecl BuildResourceList(ResourceList& resourceList)
{
Log::Comment(L"In BuildResourceList");
GUID myGuid;
VERIFY_SUCCEEDED(::CoCreateGuid(&myGuid));
CComPtr<ITestResource> spTestResource;
spTestResource.Attach(new MyTestResource(L"HDAudio1", L"HDAudio-deviceid-1", myGuid, L"HD"));
resourceList.Add(spTestResource);
spTestResource.Attach(new MyTestResource(L"HDAudio2", L"HDAudio-deviceid-2", myGuid, L"HD"));
resourceList.Add(spTestResource);
spTestResource.Attach(new MyTestResource(L"PCI1", L"PCI-deviceid-1", myGuid, L"PCI"));
resourceList.Add(spTestResource);
spTestResource.Attach(new MyTestResource(L"PCI2", L"PCI-deviceid-2", myGuid, L"PCI"));
resourceList.Add(spTestResource);
spTestResource.Attach(new MyTestResource(L"PCI3", L"PCI-deviceid-3", myGuid, L"PCI"));
resourceList.Add(spTestResource);
return S_OK;
}
BuildResourceList acepta una referencia a WEX::TestExecution::ResourceList como parámetro. ResourceList se define en el archivo de encabezado publicado ResourceList.h. Con el método Add(...) en ResourceList, los usuarios pueden agregar todos los recursos de prueba detectados o creados para que TAEF los administre y trabaje con ellos. En el ejemplo anterior se agregaron 5 recursos de prueba.
Se producirá un error en el método Add si el recurso de prueba que se va a agregar no devuelve "Name", "Id", "Type" o GUID para el recurso.
ResourceList se mantendrá durante la vigencia del módulo de prueba, es decir, hasta que se ejecuten todos los métodos de prueba y los métodos de limpieza. Si BuildResourceList devuelve un valor de ERROR HRESULT, todos los métodos de prueba dependientes de recursos del módulo de prueba se registran como bloqueados sin ejecutarse. Todos los recursos que no son de prueba se ejecutarán independientemente.
BuildResourceList se invoca antes de cualquier otro método del módulo de prueba. Una vez creada la lista de recursos (en BuildResourceList), los metadatos de "ResourceSelection" se usan para hacer coincidir los recursos disponibles en la lista de recursos. Si se encuentra una coincidencia, se invocan todos los métodos de instalación (módulo, clase, orden de prueba) seguidos del propio método de prueba. El método de limpieza de nivel de prueba se llama después de cada invocación de prueba.
En segundo plano, TAEF conserva la lista de recursos en la que se aplica la selección de recursos. Por ejemplo, para el método de prueba OneHDAudioTest, los recursos de prueba con identificadores "HDAudio-deviceid-1" y "HDAudio-deviceid-2" coincidirán con "HD*" y, para cada uno de ellos, TAEF volverá a invocar el método de prueba (una vez por cada uno). También habrá un índice implícito asociado a cada invocación de la prueba. Por lo tanto, verá el <calificador de espacio de nombres>OneHDAudioTest#0 y el <calificador de espacio de nombres>OneHDAudioTest#1 como las dos invocaciones.
Creación para la compatibilidad con dispositivos: recuperación del dispositivo en un método de prueba
En las secciones anteriores se explicó cómo agregar los metadatos necesarios en el nivel de módulo, clase y método de prueba. También se analizó cómo definir recursos de prueba personalizados y cómo agregarlos a ResourceList en la implementación de BuildResourceList. Lo siguiente es recuperar los recursos en el método de prueba. Echemos un vistazo a uno de los métodos de prueba simples del ejemplo:
1 void TestResourceExample::OneHDAudioTest()
2 {
3 Log::Comment(L"In HD audio test");
4 size_t count = Resources::Count();
5 size_t index = 0;
6 VERIFY_ARE_EQUAL(count, (index + 1));
7
8 CComPtr<ITestResource> spTestResource;
9 VERIFY_SUCCEEDED(Resources::Item(index, &spTestResource));
10
11 // Get Resource Id
12 CComBSTR value;
13 VERIFY_SUCCEEDED(spTestResource->GetValue(CComBSTR(TestResourceProperty::c_szId), &value));
14 Log::Comment(L"Resource Id is " + String(value));
15 }
En OneHDAudioTest, la selección de recursos selecciona un recurso de prueba a la vez donde el identificador del recurso comienza con "HD". La clase estática Resources definida en ResourceList.h proporciona las API para recuperar el recuento, así como el recurso real disponible durante cualquier invocación dada de la prueba. En este caso, como se puede ver en las líneas 4, 9 y 13 del ejemplo anterior, Resources::Count() proporciona el recuento del número de recursos de prueba disponibles durante la invocación actual del método de prueba. En este método de prueba, debe ser 1. Puede comprobar este valor mediante las macros VERIFY que están disponibles en TAEF (Verify.h). Como sabe, si alguna de las llamadas de comprobación produce un error en una prueba de TAEF basada en excepciones, la ejecución finalizará en ese momento y el método de prueba se marcará como Error.
A continuación, con Resources::Item(...) API y pasando un índice en el cual recuperar el recurso (en este caso, dado que solo habrá un recurso de prueba disponible durante una invocación, el índice siempre será 0), puede recuperar el recurso de prueba. El método de prueba puede usar además el recurso de prueba recuperado según lo necesite para sus pruebas.
Se sigue el mismo principio básico en todos los métodos de prueba. Echemos un vistazo a otros métodos de prueba del ejemplo para comprenderlo mejor.
Ejecución de un módulo de prueba dependiente de un recurso de prueba
Una vez creadas y compiladas las pruebas dependientes del recurso de prueba, puede ejecutarlas mediante TAEF. El punto clave a tener en cuenta es que las pruebas TestResourceDependent solo se pueden ejecutaren inproc. Esto significa que incluso si no especifica explícitamente el modificador "/inproc", se agregará tan pronto como TAEF detecte el módulo de prueba dependiente del recurso de prueba. Como ya sabrá, las pruebas de un solo módulo de prueba se pueden ejecutar en una ejecución TAEF determinada cuando el modificador "/inproc" esté presente. Esto significa que no puede especificar más de un módulo de prueba en la línea de comandos si el módulo de prueba depende del recurso.
Para ejecutar realmente todas las pruebas del módulo de prueba, simplemente puede ejecutar:
te Examples\Cpp.TestResource.Example.dll
Una forma útil de obtener una lista de todas las invocaciones del método de prueba y las combinaciones de datos y metadatos sin ejecutar realmente los métodos de prueba es usar el modificador /listproperties en la línea de comandos. Echemos un vistazo al resultado.
te Examples\Cpp.TestResource.Example.dll /listproperties
Test Authoring and Execution Framework v2.9.3k for x86
In BuildResourceList
Verify: SUCCEEDED(::CoCreateGuid(&myGuid))
f:\toolsdev.binaries.x86chk\WexTest\CuE\TestExecution\Examples\Cpp.TestResource.Example.dll
Property[TestResourceDependent] = true
WEX::TestExecution::Examples::TestResourceExample
WEX::TestExecution::Examples::TestResourceExample::NoTestResourceTest
Property[TestResourceDependent] = false
WEX::TestExecution::Examples::TestResourceExample::OneHDAudioTest#0
Property[ResourceSelection] = @Id='HD*'
Resource#0
Id = HDAudio-deviceid-1
Name = HDAudio1
Type = HD
WEX::TestExecution::Examples::TestResourceExample::OneHDAudioTest#1
Property[ResourceSelection] = @Id='HD*'
Resource#0
Id = HDAudio-deviceid-2
Name = HDAudio2
Type = HD
WEX::TestExecution::Examples::TestResourceExample::OnePCIDeviceTest#0
Property[ResourceSelection] = @Id='PCI*'
Resource#0
Id = PCI-deviceid-1
Name = PCI1
Type = PCI
WEX::TestExecution::Examples::TestResourceExample::OnePCIDeviceTest#1
Property[ResourceSelection] = @Id='PCI*'
Resource#0
Id = PCI-deviceid-2
Name = PCI2
Type = PCI
WEX::TestExecution::Examples::TestResourceExample::OnePCIDeviceTest#2
Property[ResourceSelection] = @Id='PCI*'
Resource#0
Id = PCI-deviceid-3
Name = PCI3
Type = PCI
WEX::TestExecution::Examples::TestResourceExample::HDorPCITest#0
Property[ResourceSelection] = @Id='PCI*' OR @Id='HD*'
Resource#0
Id = HDAudio-deviceid-1
Name = HDAudio1
Type = HD
WEX::TestExecution::Examples::TestResourceExample::HDorPCITest#1
Property[ResourceSelection] = @Id='PCI*' OR @Id='HD*'
Resource#0
Id = HDAudio-deviceid-2
Name = HDAudio2
Type = HD
WEX::TestExecution::Examples::TestResourceExample::HDorPCITest#2
Property[ResourceSelection] = @Id='PCI*' OR @Id='HD*'
Resource#0
Id = PCI-deviceid-1
Name = PCI1
Type = PCI
WEX::TestExecution::Examples::TestResourceExample::HDorPCITest#3
Property[ResourceSelection] = @Id='PCI*' OR @Id='HD*'
Resource#0
Id = PCI-deviceid-2
Name = PCI2
Type = PCI
WEX::TestExecution::Examples::TestResourceExample::HDorPCITest#4
Property[ResourceSelection] = @Id='PCI*' OR @Id='HD*'
Resource#0
Id = PCI-deviceid-3
Name = PCI3
Type = PCI
WEX::TestExecution::Examples::TestResourceExample::PCI1AudioTest #0
Property[ResourceSelection] = @Id='PCI*' AND @Id='*1'
Resource#0
Id = PCI-deviceid-1
Name = PCI1
Type = PCI
Observe el índice implícito que se agrega al nombre del método de prueba durante cada invocación de un método de prueba que depende del recurso de prueba. La propiedad ResourceSelection se muestra seguida de una lista de todos los recursos que estarán disponibles para el método de prueba en el orden en que estarán disponibles. Por ejemplo, en el caso de la tercera invocación de HDAudioHDAudioPCITest (HDAudioHDAudioPCITest#2), HDAudio-deviceid-1 será el recurso disponible en el índice 0 en Resources::Item(...).
Puede ser más específico sobre qué invocación de prueba le interesa utilizando el lenguaje de consulta de selección de línea de comandos disponible en TAEF. Por ejemplo, para seleccionar todas las invocaciones de métodos de prueba donde los recursos de prueba "PCI-deviceid-3" están disponibles, puede usar los criterios de selección:
te Examples\Cpp.TestResource.Example.dll /list
/select:"@Resource:Id='PCI-deviceid-3'"
Test Authoring and Execution Framework v2.9.3k for x86
In BuildResourceList
Verify: SUCCEEDED(::CoCreateGuid(&myGuid))
f: \Examples\Cpp.TestResource.Example.dll
WEX::TestExecution::Examples::TestResourceExample
WEX::TestExecution::Examples::TestResourceExample::OnePCIDeviceTest#2
WEX::TestExecution::Examples::TestResourceExample::HDorPCITest#4
De manera similar, para seleccionar un método de prueba determinado por nombre (tenga en cuenta que los nombres de método de prueba están completamente calificados junto con el índice de invocación anexado al final), puede usar una consulta de selección como se indica a continuación:
te Examples\Cpp.TestResource.Example.dll /name:*OneHDAudioTest#1
Test Authoring and Execution Framework v2.2 Build 6.1.7689.0 (release.091218-1251) for x86
Discovered a test resource dependent test module. Assuming /InProc execution.
In BuildResourceList
Verify: SUCCEEDED(::CoCreateGuid(&myGuid))
StartGroup: WEX::TestExecution::Examples::TestResourceExample::OneHDAudioTest#1
In HD audio test
Verify: AreEqual(count, (index + 1))
Verify: SUCCEEDED(Resources::Item(index, &spTestResource))
Verify: SUCCEEDED(spTestResource->GetValue(CComBSTR(TestResourceProperty::c_szId), &value))
Resource Id is HDAudio-deviceid-2
WEX::TestExecution::Examples::TestResourceExample::OneHDAudioTest#1 [Passed]
Summary: Total=1, Passed=1, Failed=0, Blocked=0, Not Run=0, Skipped=0
Tenga en cuenta la advertencia implícita inproc agregada en la tercera línea del ejemplo anterior. La consulta de selección anterior tuvo el mismo efecto que la consulta de selección: /select:"@Name='*OneHDAudio*' And @Resource:Index=1". También es posible seleccionar un recurso con su nombre o tipo (o identificador como se mostró anteriormente). Por ejemplo, /select:"@Name='*PCIHDAudioTest*' y @Resource:Name='PCI3'" seleccionarán los métodos de prueba PCIHDAudioTest#4 y PCIHDAudioTest#5.
Probar estas y otras consultas de selección en el símbolo del sistema se deja como ejercicio para el lector.