Lorsque vous écrivez un lanceur de test, il est important de penser à l'évolutivité. Demander vous-même, « si mon lanceur de test a dû exécuter 200 000 scénarios de test » combien de temps cela prendrait-il ?
La segmentation est l'une des réponses disponibles au sein de la Fédération du commerce. Elle nécessite diviser tous les tests dont l'exécuteur a besoin en plusieurs fragments pouvant être en parallèle.
Cette page explique comment rendre votre exécuteur partitionnable pour Tradefed.
Interface d'implémentation
La seule interface la plus importante à implémenter pour être considérée comme pouvant être segmentée par
TF signifie
IShardableTest
qui contient deux méthodes: split(int numShard)
et split()
.
Si la segmentation dépend du nombre de segments demandés,
doit implémenter split(int numShard)
. Sinon, implémentez split()
.
Lorsqu'une commande de test TF est exécutée avec les paramètres de segmentation --shard-count
et
--shard-index
, TF parcourt tous les IRemoteTest
pour rechercher des uns
l'implémentation de IShardableTest
. S'il le trouve, il appellera split
pour
obtenir un nouvel objet IRemoteTest
afin d'exécuter un sous-ensemble de scénarios de test pour un
segment.
Que faut-il savoir à propos de l'implémentation du fractionnement ?
- Votre exécuteur peut partitionner sous certaines conditions uniquement : Dans ce cas, renvoyez
null
lorsque vous n'avez pas effectué la segmentation. - Essayez de diviser autant que nécessaire: divisez votre coureur en unité de une exécution qui a du sens. Cela dépend vraiment de votre coureur. Pour Exemple: Test hôte est segmentée au niveau de la classe, chaque classe de test est placée dans une partition distincte.
- Si c'est judicieux, ajoutez des options pour contrôler un peu la segmentation.
Par exemple:
AndroidJUnitTest
comporte un champ
ajur-max-shard
pour indiquer le nombre maximal de segments à répartir, quel que soit le nombre demandé.
Exemple détaillé d'implémentation
Voici un exemple d'extrait de code mettant en œuvre IShardableTest
que vous pouvez
référence. Le code complet est disponible à l’adresse
(https://android.googlesource.com/platform/tools/tradefederation/+/refs/heads/main/test_framework/com/android/tradefed/testtype/installedInstrumentationsTest.java)
/**
* Runs all instrumentation found on current device.
*/
@OptionClass(alias = "installed-instrumentation")
public class InstalledInstrumentationsTest
implements IDeviceTest, IResumableTest, IShardableTest {
...
/** {@inheritDoc} */
@Override
public Collection<IRemoteTest> split(int shardCountHint) {
if (shardCountHint > 1) {
Collection<IRemoteTest> shards = new ArrayList<>(shardCountHint);
for (int index = 0; index < shardCountHint; index++) {
shards.add(getTestShard(shardCountHint, index));
}
return shards;
}
// Nothing to shard
return null;
}
private IRemoteTest getTestShard(int shardCount, int shardIndex) {
InstalledInstrumentationsTest shard = new InstalledInstrumentationsTest();
try {
OptionCopier.copyOptions(this, shard);
} catch (ConfigurationException e) {
CLog.e("failed to copy instrumentation options: %s", e.getMessage());
}
shard.mShardIndex = shardIndex;
shard.mTotalShards = shardCount;
return shard;
}
...
}
Cet exemple crée simplement une instance de lui-même et définit la partition des paramètres. Cependant, la logique de fractionnement peut être totalement différente tester pour tester ; tant qu'il est déterministe et génère collectivement des sous-ensembles exhaustifs, ce n'est pas grave.
L'indépendance
Les segments doivent être indépendants ! Deux segments créés par votre implémentation de
Les split
de votre exécuteur ne doivent pas avoir de dépendances entre eux et ne doivent pas partager
ressources.
Le fractionnement des segments doit être déterministe. Cette étape est également obligatoire,
les mêmes conditions, votre méthode split
doit toujours renvoyer exactement la même liste de
segments dans le même ordre.
REMARQUE: Étant donné que chaque segment peut s'exécuter sur différentes instances TF, il est essentiel
vous assurer que la logique split
génère des sous-ensembles qui s'excluent mutuellement ;
collectivement exhaustives et de manière déterministe.
Segmenter un test en local
Pour segmenter un test sur un fichier TF local, il vous suffit d'ajouter l'option --shard-count
à
la ligne de commande.
tf >run host --class com.android.tradefed.UnitTests --shard-count 3
Ensuite, TF générera automatiquement des commandes pour chaque segment et les exécutera.
tf >l i
Command Id Exec Time Device State
3 0m:03 [null-device-2] running stub on build 0 (shard 1 of 3)
3 0m:03 [null-device-1] running stub on build 0 (shard 0 of 3)
3 0m:03 [null-device-3] running stub on build 0 (shard 2 of 3)
Agrégation des résultats de test
Étant donné que TF n'agrège pas les résultats des tests pour les appels segmentés, vous vous devez vous assurer que votre service de reporting le prend en charge.