Prise en charge des appareils
Si votre automatisation de test dépend de la présence de dispositifs ou de ressources de test, veuillez consulter l’exemple, TestResourceExample, et suivre les instructions sur la façon de tirer parti du support de dispositif ou du support de ressource de test disponible dans TAEF. Assurez-vous que vous êtes familier avec la création de tests basiques en utilisant TAEF et l’exécution basique de TAEF avant de continuer.
Te.Common.lib est requis en plus des autres bibliothèques nécessaires pour créer un test dans TAEF.
Les utilisateurs sont responsables de créer leur propre définition de ressource de test (dispositif). Pour ce faire, vous devez implémenter ITestResource. ITestResource est défini dans le fichier d’en-tête publié ITestResource.h et ressemble à ceci :
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*/
Dans notre exemple, la classe MyTestResource implémente l’interface COM ITestResource. Dans ITestResource.h, vous trouverez également une liste de propriétés « indispensables » définies. Il devrait être possible d’obtenir le GUID pour la ressource de test en utilisant GetGuid(..) et le Nom, l’Id et le Type de la ressource en utilisant GetValue(...). Si l’une de ces informations manque dans une TestResource, TAEF la considérera comme invalide et ne maintiendra pas ses informations. (Voir la section « Construction de la liste de ressources » qui suit).
Afin de spécifier que le module de test a des méthodes de test dépendantes des ressources de test, une propriété de métadonnées au niveau du module « TestResourceDependent » doit être définie sur « true ». La propriété est héritée par toutes les classes du module de test et par toutes les méthodes de test de ces classes. Si l’une des méthodes de test dans le module n’est pas dépendante des ressources de test, elle doit explicitement réinitialiser la valeur des métadonnées à false. Toutes les autres méthodes de test qui dépendent des ressources de test doivent fournir une requête de sélection en utilisant l’« Id » et/ou le « Type » de la ressource de test.
Voici quelques exemples rapides de « ResourceSelection » pour notre liste de ressources d’exemple et ce que chacun d’eux implique :
- « @Id='HD*' » : correspond à chaque ressource avec un Id commençant par « HD »
- « @Type=’PCI’ » : correspond à chaque ressource de Type « PCI »
- « @Id='PCI*' OR @Id='HD*' » : correspond à chaque ressource commençant par « PCI » ou commençant par « HD »
- « @Type='PCI' et @id='*37' » : correspond à chaque ressource de type « PCI » avec un nom se terminant par « 37 »
Dans notre exemple de code, cela ressemble à ceci :
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()
...
};
Dans l’exemple ci-dessus, vous verrez que le module est marqué comme « TestResourceDependent ». La méthode NoTestResourceTest est explicitement marquée comme non dépendante de toute ressource de test en définissant les métadonnées « TestResourceDependent » à « false ». Toutes les autres méthodes de test spécifient un critère de sélection pour les ressources de test qu’elles souhaitent exécuter.
La grammaire des critères de sélection est très similaire à la grammaire de la requête de sélection en ligne de commande disponible pour TAEF. Dans le cas de la sélection des ressources, elle est cependant limitée à l’utilisation des Id et types de ressources. Comme l’Id de ressource est une chaîne, il doit être encadré par des guillemets simples. Vous pouvez utiliser les caractères génériques « * » ou « ? » dans la spécification de la valeur Id. Dans notre exemple ci-dessus, dans OneHDAudioTest, la sélection de ressource spécifie une correspondance à toute ressource dont l’Id commence par « HD ». De même, dans le cas de HDorPCITest, la sélection de ressource correspondra à toute ressource dont l’Id commence par « HD » ou commence par « PCI ». Il est important de noter que la sélection de ressource est insensible à la casse - c’est-à-dire que « pci », « Pci » et « PCI » seront tous traités de la même manière.
En fonction de la sélection des ressources, TAEF ré-invoquera la méthode de test ainsi que les méthodes de configuration et de nettoyage au niveau du test (si elles sont spécifiées) une fois pour chaque ressource de test correspondant à la sélection. Les sections suivantes examineront en détail comment spécifier la liste des ressources et la fournir à TAEF et comment la méthode de test peut récupérer les ressources dans la section suivante.
Dès que TAEF rencontre un module de test dépendant des ressources de test, il cherchera et invoquera la méthode exportée par la DLL BuildResourceList. C’est dans l’implémentation de BuildResourceList que les utilisateurs peuvent créer de nouvelles ressources de test et les ajouter à l’interface qui est passée en paramètre à BuildResourceList. Examinons l’implémentation de cette méthode dans notre exemple :
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 accepte une référence à WEX::TestExecution::ResourceList comme paramètre. ResourceList est défini dans le fichier d’en-tête publié ResourceList.h. En utilisant la méthode Add(...) sur le ResourceList, les utilisateurs peuvent ajouter toutes les ressources de test découvertes ou créées pour que TAEF les gère et les utilise. L’exemple ci-dessus a ajouté 5 de ces ressources de test.
La méthode Add échouera si la ressource de test à ajouter ne parvient pas à retourner soit le « Nom », l’« Id », le « Type » ou le GUID de la ressource.
Le ResourceList sera maintenu pendant toute la durée de vie du module de test - c’est-à-dire jusqu’à ce que toutes les méthodes de test et les méthodes de nettoyage soient exécutées. Si BuildResourceList retourne une valeur HRESULT FAILED, toutes les méthodes de test dépendantes des ressources dans le module de test sont enregistrées comme bloquées sans exécution. Toutes les ressources non testées seront exécutées quoi qu’il arrive.
BuildResourceList est invoqué avant toute autre méthode dans le module de test. Après la construction de la liste de ressources (dans BuildResourceList), les métadonnées « ResourceSelection » sont utilisées pour correspondre aux ressources disponibles dans la liste de ressources. Si une correspondance est trouvée, toutes les méthodes de configuration (module, classe, ordre de test) sont invoquées, suivies par la méthode de test elle-même. La méthode de nettoyage au niveau du test est appelée après chaque invocation de test.
En coulisses, TAEF conserve le ResourceList sur lequel la sélection de ressource est appliquée. Par exemple, pour la méthode de test OneHDAudioTest, les ressources de test avec les Id « HDAudio-deviceid-1 » et « HDAudio-deviceid-2 » correspondront toutes deux à « HD* » et pour chacune d’elles, la méthode de test sera ré-invoquée par TAEF (une fois pour chaque). Il y aura également un index implicite associé à chaque invocation du test. Ainsi, vous verrez <qualificateur de namespace>OneHDAudioTest#0 et <qualificateur de namespace>OneHDAudioTest#1 comme les deux invocations.
Les sections précédentes ont examiné comment ajouter les métadonnées nécessaires au niveau du module, de la classe et de la méthode de test. Elles ont également examiné comment définir des ressources de test personnalisées et comment les ajouter au ResourceList dans l’implémentation de BuildResourceList. La partie suivante concerne la récupération des ressources dans la méthode de test. Examinons l’une des méthodes de test simples dans notre exemple :
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 }
Dans OneHDAudioTest, la sélection de ressource sélectionne une ressource de test à la fois où l’Id de la ressource commence par « HD ». La classe statique Resources définie dans ResourceList.h fournit les API pour récupérer le nombre ainsi que la ressource réelle disponible lors de toute invocation de la méthode de test. Dans ce cas, comme vous pouvez le voir dans les lignes 4, 9 et 13 de l’exemple ci-dessus, Resources::Count() donne le nombre de ressources de test disponibles lors de l’invocation actuelle de la méthode de test. Dans cette méthode de test, cela devrait être 1. Vous pouvez vérifier cette valeur en utilisant les macros VERIFY disponibles dans TAEF (Verify.h). Comme vous le savez, si l’un des appels de vérification échoue dans un test TAEF basé sur des exceptions, l’exécution se terminera à ce moment-là et la méthode de test sera marquée comme échouée.
Ensuite, en utilisant l’API Resources::Item(...) et en passant un index pour récupérer la ressource (dans ce cas, puisqu’une seule ressource de test sera disponible lors d’une invocation, l’index sera toujours 0), vous pouvez récupérer la ressource de test. La méthode de test peut ensuite utiliser la ressource de test récupérée comme elle le souhaite pour ses tests.
Le même principe de base est suivi dans toutes les méthodes de test. Examinez les autres méthodes de test de l’exemple pour mieux comprendre.
Avec les tests dépendants des ressources de test désormais créés et construits, vous pouvez maintenant les exécuter en utilisant TAEF. Le point clé à noter est que les tests TestResourceDependent ne peuvent être exécutés qu’en mode inproc. Cela signifie que même si vous ne spécifiez pas explicitement « /inproc », il sera ajouté dès que TAEF découvrira le module de test dépendant des ressources de test. Comme vous le savez peut-être, les tests d’un seul module de test peuvent être exécutés dans une exécution TAEF donnée lorsque l’option « /inproc » est présente. Cela signifie que vous ne pouvez pas spécifier plus d’un module de test en ligne de commande si votre module de test est dépendant des ressources.
Pour exécuter réellement tous les tests dans notre module de test, vous pouvez simplement exécuter :
te Examples\Cpp.TestResource.Example.dll
Un moyen utile d’obtenir une liste de toutes les invocations de méthodes de test et des combinaisons de données et de métadonnées sans réellement exécuter les méthodes de test est d’utiliser l’option /listproperties en ligne de commande. Examinons la sortie.
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
Remarquez l’index implicite qui est ajouté au nom de la méthode de test lors de chaque invocation d’une méthode de test dépendant des ressources. La propriété ResourceSelection est affichée suivie d’une liste de toutes les ressources qui seront disponibles pour la méthode de test dans l’ordre où elles seront disponibles. Par exemple, dans le cas de la troisième invocation de HDAudioHDAudioPCITest (HDAudioHDAudioPCITest#2), HDAudio-deviceid-1 sera la ressource disponible à l’index 0 dans Resources::Item(...).
Vous pouvez être plus précis sur l’invocation de test qui vous intéresse en utilisant le langage de requête de sélection en ligne de commande disponible dans TAEF. Par exemple, pour sélectionner toutes les invocations de méthodes de test où les ressources de test « PCI-deviceid-3 » sont disponibles, vous pouvez utiliser les critères de sélection :
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 même, pour sélectionner une méthode de test particulière par nom (notez que les noms de méthodes de test sont entièrement qualifiés avec l’index d’invocation ajouté à la fin), vous pouvez utiliser une requête de sélection comme suit :
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
Notez l’avertissement d’ajout implicite de inproc dans la troisième ligne de l’exemple ci-dessus. La requête de sélection ci-dessus avait le même effet que la requête de sélection : /select:«@Name='*OneHDAudio*' And @Resource:Index=1». Il est également possible de sélectionner une ressource en utilisant son nom ou son type (ou Id comme montré ci-dessus). Par exemple, /select:« @Name='*PCIHDAudioTest*' et @Resource:Name='PCI3' » sélectionnera les méthodes de test PCIHDAudioTest#4 et PCIHDAudioTest#5.
Essayer ces requêtes de sélection et d’autres en ligne de commande est laissé comme un exercice pour le lecteur.