
De nombreux développeurs de tests iOS UI connaissent probablement le problème de l'exécution des tests. Badoo exécute plus de 1 400 tests de bout en bout pour les applications iOS pour chaque exécution de régression. Ce sont plus de 40 heures de tests machine qui passent en 30 minutes réelles.
Nikolai Abalov de Badoo a
expliqué comment il avait réussi à accélérer l'exécution du test de 1,5 heure à 30 minutes; comment ils démêlent les tests étroitement liés et l'infrastructure iOS en allant sur le serveur de l'appareil; comment il a facilité l'exécution de tests en parallèle et facilité la prise en charge et la mise à l'échelle des tests et de l'infrastructure.
Vous découvrirez à quel point il est facile d'exécuter des tests en parallèle avec des outils tels que fbsimctl, et comment la séparation des tests et de l'infrastructure peut faciliter l'hébergement, la prise en charge et la mise à l'échelle de vos tests.
Initialement, Nikolai a présenté un rapport lors de la conférence de Heisenbug (vous pouvez regarder la
vidéo ), et maintenant pour Habr, nous avons fait une version texte du rapport. Vient ensuite un récit à la première personne:
Bonjour à tous, aujourd'hui, je vais parler des tests de mise à l'échelle pour iOS. Je m'appelle Nicholas, je m'occupe principalement de l'infrastructure iOS chez Badoo. Avant cela, il a travaillé pour 2GIS pendant trois ans, s'est engagé dans le développement et l'automatisation, en particulier, il a écrit Winium.Mobile - une implémentation de WebDriver pour Windows Phone. J'ai été emmené à Badoo pour travailler sur l'automatisation de Windows Phone, mais après un certain temps, l'entreprise a décidé de suspendre le développement de cette plate-forme. Et on m'a proposé des tâches intéressantes pour l'automatisation d'iOS, à ce sujet je vais vous le dire aujourd'hui.
De quoi allons-nous parler? Le plan est le suivant:
- Un exposé informel du problème, une introduction aux outils utilisés: comment et pourquoi.
- Tests parallèles sur iOS et son évolution (en particulier, selon l'histoire de notre entreprise, depuis que nous avons commencé à travailler dessus en 2015).
- Le serveur de périphériques est la partie principale du rapport. Notre nouveau modèle de parallélisation des tests.
- Les résultats que nous avons obtenus avec le serveur.
- Si vous n'avez pas 1500 tests, vous n'avez peut-être pas vraiment besoin d'un serveur de périphériques, mais vous pouvez toujours en tirer des choses intéressantes, et nous en parlerons. Ils peuvent être appliqués si vous avez 10 à 25 tests, ce qui donnera toujours une accélération ou une stabilité supplémentaire.
- Et enfin, un débriefing.
Les outils
Le premier est un peu sur qui utilise quoi. Notre pile est un peu non standard, car nous utilisons à la fois Calabash et WebDriverAgent (ce qui nous donne de la vitesse et des backdoors Calabash lors de l'automatisation de notre application et en même temps un accès complet au système et aux autres applications via WebDriverAgent). WebDriverAgent est une implémentation Facebook de WebDriver pour iOS qui est utilisée en interne par Appium. Et Calabash est un serveur intégré pour l'automatisation. Nous écrivons les tests eux-mêmes sous une forme lisible par l'homme en utilisant Cucumber. Autrement dit, dans notre société pseudo-BDD. Et parce que nous avons utilisé Cucumber et Calabash, nous avons hérité de Ruby, tout le code est écrit dessus. Il y a beaucoup de code et vous devez continuer à écrire en Ruby. Pour exécuter des tests en parallèle, nous utilisons
parallel_cucumber , un outil écrit par un de mes collègues de Badoo.
Commençons par ce que nous avions. Lorsque j'ai commencé à préparer le rapport, il y avait 1200 tests. Au moment où ils ont été terminés, il était 1300. Pendant que je suis arrivé ici, il y avait déjà 1400 tests, ce sont des tests de bout en bout, pas des tests unitaires et des tests d'intégration. Ils représentent 35 à 40 heures de temps informatique sur un seul simulateur. Ils sont passés plus tôt dans une heure et demie. Je vais vous dire comment ils ont commencé à passer en 30 minutes.
Nous avons un flux de travail dans notre entreprise avec des succursales, des examens et des tests en cours sur ces succursales. Les développeurs créent environ 10 requêtes vers le référentiel principal de notre application. Mais il a également des composants qui sont partagés avec d'autres applications, donc parfois il y en a plus de dix. En conséquence, 30 tests par jour au moins. Depuis que les développeurs poussent, ils se rendent compte qu'ils ont commencé avec des bugs, recharger, et tout cela commence une régression complète, simplement parce que nous pouvons l'exécuter. Sur la même infrastructure, nous lançons des projets supplémentaires, tels que Liveshot, qui prend des captures d'écran de l'application dans les principaux scripts utilisateur dans toutes les langues, afin que les traducteurs puissent vérifier l'exactitude de la traduction, qu'elle s'adapte à l'écran, etc. En conséquence, environ un millier et demi d'heures de temps machine sortent actuellement.
Tout d'abord, nous voulons que les développeurs et les testeurs fassent confiance à l'automatisation et s'appuient sur elle pour réduire la régression manuelle. Pour que cela se produise, il est nécessaire d'obtenir un fonctionnement rapide et, surtout, stable et fiable à partir de l'automatisation. Si les tests réussissent dans une heure et demie, le développeur se lassera d'attendre les résultats, il commencera à faire une autre tâche, sa concentration changera. Et quand certains tests tomberont, il ne sera pas très content qu'il doive revenir, changer son attention et réparer quelque chose. Si les tests ne sont pas fiables, au fil du temps, les gens commencent à les percevoir uniquement comme une barrière. Ils tombent constamment, bien qu'il n'y ait pas de bogues dans le code. Ce sont des tests Flaky, une sorte d'obstacle. En conséquence, ces deux points ont été divulgués dans ces exigences:
- Les tests devraient prendre 30 minutes ou plus.
- Ils doivent être stables.
- Ils doivent être évolutifs afin que nous puissions ajouter une demi-heure pour ajouter une centaine de tests supplémentaires.
- L'infrastructure doit être facilement entretenue et développée.
- Sur les simulateurs et les appareils physiques, tout devrait commencer de la même manière.
Nous effectuons principalement des tests sur des simulateurs, et non sur des appareils physiques, car c'est plus rapide, plus stable et plus facile. Les appareils physiques ne sont utilisés que pour les tests qui l'exigent vraiment. Par exemple, appareil photo, notifications push et similaires.
Comment satisfaire ces exigences et tout bien faire? La réponse est très simple: nous supprimons les deux tiers des tests! Cette solution tient en 30 minutes (car il ne reste qu'un tiers des tests), évolue facilement (d'autres tests peuvent être supprimés) et augmente la fiabilité (car la première chose que nous supprimons est les tests les moins fiables). C’est tout pour moi. Des questions?
Mais sérieusement, il y a du vrai dans chaque blague. Si vous avez beaucoup de tests, vous devez les revoir et comprendre ceux qui apportent de réels avantages. Nous avions une tâche différente, nous avons donc décidé de voir ce qui pouvait être fait.
La première approche consiste à filtrer les tests en fonction de la couverture ou des composants. Autrement dit, sélectionnez les tests appropriés en fonction des modifications de fichiers dans l'application. Je n'en parlerai pas, mais c'est l'une des tâches que nous résolvons actuellement.
Une autre option consiste à accélérer et à stabiliser les tests eux-mêmes. Vous passez un test spécifique, voyez quelles étapes prennent le plus de temps et si elles peuvent être optimisées d'une manière ou d'une autre. Si certains d'entre eux sont très instables très souvent, vous les corrigez, car cela réduit les redémarrages de test, et tout va plus vite.
Et, enfin, une tâche complètement différente: paralléliser les tests, les distribuer sur un grand nombre de simulateurs et fournir une infrastructure évolutive et stable pour qu'il y ait beaucoup à paralléliser.
Dans cet article, nous parlerons principalement des deux derniers points et à la fin, dans les trucs et astuces, nous aborderons le point sur la vitesse et la stabilisation.
Test parallèle pour iOS
Commençons par l'histoire des tests parallèles pour iOS en général et Badoo en particulier. Pour commencer, arithmétique simple, ici, cependant, il y a une erreur dans la formule si l'on compare les dimensions:

Il y a eu 1300 tests pour un simulateur, il s'avère que 40 heures. Puis Satish, mon chef, vient et dit qu'il a besoin d'une demi-heure. Vous devez inventer quelque chose. X apparaît dans la formule: combien de simulateurs exécuter, pour que tout se passe en une demi-heure. La réponse est 80 simulateurs. Et immédiatement la question se pose, où mettre ces 80 simulateurs, car ils ne rentrent nulle part.
Il existe plusieurs options: vous pouvez accéder à des clouds tels que SauceLabs, Xamarin ou AWS Device Farm. Et vous pouvez penser à tout à la maison et bien faire. Étant donné que cet article existe, nous avons tout bien fait à la maison. Nous l'avons décidé, car un cloud avec une telle échelle serait assez cher, et il y avait aussi une situation où iOS 10 est sorti et Appium a pris en charge le support pendant près d'un mois. Cela signifie que dans SauceLabs pendant un mois, nous n'avons pas pu tester automatiquement iOS 10, ce qui ne nous convenait pas du tout. De plus, tous les nuages sont fermés et vous ne pouvez pas les affecter.
Nous avons donc décidé de tout faire en interne. Nous avons commencé quelque part en 2015, puis Xcode n'a pas pu exécuter plus d'un simulateur. Il s'est avéré qu'il ne peut pas exécuter plus d'un simulateur sous un même utilisateur sur la même machine. Si vous avez de nombreux utilisateurs, vous pouvez exécuter autant de simulateurs que vous le souhaitez. Mon collègue Tim Bawerstock a proposé un modèle sur lequel nous avons vécu assez longtemps.

Il y a un agent (TeamCity, Jenkins Node et similaires), il exécute parallel_cucumber, qui va simplement aux machines distantes via ssh. La photo montre deux voitures pour deux utilisateurs. Tous les fichiers nécessaires tels que les tests sont copiés et exécutés sur des machines distantes via ssh. Et les tests exécutent déjà le simulateur localement sur le bureau actuel. Pour que cela fonctionne, vous devez d'abord aller sur chaque machine, créer, par exemple, 5 utilisateurs, si vous voulez 5 simulateurs, créer un utilisateur une connexion automatique, ouvrir le partage d'écran pour le reste, afin qu'ils aient toujours un bureau. Et configurez le démon ssh pour qu'il ait accès aux processus sur le bureau. D'une manière si simple, nous avons commencé à exécuter des tests en parallèle. Mais il y a plusieurs problèmes dans cette image. Premièrement, les tests contrôlent le simulateur, ils sont au même endroit que le simulateur lui-même. Autrement dit, ils doivent toujours être exécutés sur des coquelicots, ils consomment des ressources qui pourraient être dépensées pour exécuter des simulateurs. En conséquence, vous avez moins de simulateurs sur la machine et ils coûtent plus cher. Un autre point est que vous devez aller sur chaque machine, configurer les utilisateurs. Et puis vous tombez simplement sur l'ultime limite mondiale. S'il y a cinq utilisateurs et qu'ils soulèvent beaucoup de processus, à un moment donné, les descripteurs se termineront dans le système. Après avoir atteint la limite, les tests commenceront à tomber lors de l'ouverture de nouveaux fichiers et du démarrage de nouveaux processus.

En 2016-2017, nous avons décidé de passer à un modèle légèrement différent. Nous avons regardé un
rapport de Lawrence Lomax de Facebook - ils ont présenté fbsimctl, et ont partiellement expliqué comment fonctionne l'infrastructure sur Facebook.
Viktor Koronevich a également
publié un
rapport sur ce modèle. L'image n'est pas très différente de la précédente - nous venons de nous débarrasser des utilisateurs, mais c'est un grand pas en avant, car maintenant il n'y a qu'un seul bureau, moins de processus sont lancés, les simulateurs sont devenus moins chers. Il y a trois simulateurs dans cette image, pas deux, car les ressources ont été libérées pour en lancer un autre. Nous avons vécu avec ce modèle pendant très longtemps, jusqu'à la mi-octobre 2017, lorsque nous avons commencé à passer à notre serveur d'appareils distants.

Cela ressemblait donc à du fer. À gauche, une boîte avec des macbooks. Pourquoi nous avons effectué tous les tests sur eux est une grande histoire distincte. Exécuter les tests sur les macbooks que nous avons insérés dans la boîte en fer n'était pas une bonne idée, car quelque part dans l'après-midi, ils ont commencé à surchauffer, car la chaleur ne part pas bien lorsqu'ils sont en surface. Les tests sont devenus instables, en particulier lorsque les simulateurs ont commencé à planter lors du chargement.
Nous l'avons décidé simplement: nous avons mis les ordinateurs portables «dans des tentes», la zone de circulation d'air a augmenté et la stabilité de l'infrastructure a soudainement augmenté.

Donc, parfois, vous n'avez pas à vous occuper de logiciels, mais faites tourner des ordinateurs portables.
Mais si vous regardez cette image, il y a un désordre de fils, d'adaptateurs et généralement d'étain. C'est la partie en fer, et c'était toujours bon. Dans le logiciel, une imbrication complète des tests avec l'infrastructure était en cours, et il était impossible de continuer à vivre comme ça.
Nous avons identifié les problèmes suivants:
- Le fait que les tests soient étroitement liés à l'infrastructure, lancent des simulateurs et gèrent l'ensemble de leur cycle de vie.
- Cela a rendu la mise à l'échelle difficile, car l'ajout d'un nouveau nœud impliquait sa configuration pour les tests et l'exécution de simulateurs. Par exemple, si vous souhaitez mettre à jour Xcode, vous devez ajouter une solution de contournement directement aux tests, car ils s'exécutent sur différentes versions de Xcode. Certains si des tas semblent exécuter le simulateur.
- Les tests sont liés à la machine où se trouve le simulateur, et cela coûte un sou, car ils doivent être exécutés sur des coquelicots au lieu de * nix, qui sont moins chers.
- Et c'était toujours très facile de se plonger dans le simulateur. Dans certains tests, nous sommes allés dans le système de fichiers du simulateur, avons supprimé certains fichiers ou les avons modifiés, et tout s'est bien passé jusqu'à ce qu'il soit fait de trois manières différentes dans trois tests différents, puis de manière inattendue, le quatrième a commencé à planter s'il n'avait pas de chance de démarrer après ces trois-là.
- Et le dernier moment - les ressources n'ont pas été fouillées en aucune façon. Par exemple, il y avait quatre agents TeamCity, cinq machines étaient connectées à chacun et les tests ne pouvaient être exécutés que sur leurs cinq machines. Il n'y avait pas de système centralisé de gestion des ressources, de ce fait, lorsqu'une seule tâche arrive, elle est allée sur cinq machines, et les 15 autres étaient inactives. Pour cette raison, les builds ont pris très longtemps.
Nouveau modèle
Nous avons décidé de passer à un beau nouveau modèle.

Suppression de tous les tests sur une seule machine, où l'agent TeamCity. Cette machine peut maintenant être sur * nix ou même sur Windows si vous le souhaitez. Ils communiqueront via HTTP avec quelque chose que nous appellerons serveur d'appareil. Tous les simulateurs et les appareils physiques seront situés quelque part là-bas, et les tests s'exécuteront ici, demander l'appareil via HTTP et continuer à travailler avec. Le diagramme est très simple, il n'y a que deux éléments dans le diagramme.

En réalité, bien sûr, ssh et plus sont restés derrière le serveur. Mais maintenant, cela ne dérange personne, car les gars qui écrivent les tests sont en haut de ce diagramme, et ils ont une sorte d'interface spécifique pour travailler avec un simulateur local ou distant, donc ils vont bien. Et maintenant je travaille en dessous, et j'ai tout comme ça. Nous devons vivre avec.
Qu'est-ce que ça donne?
- Tout d'abord, la répartition des responsabilités. À un moment donné du test de l'automatisation, vous devez le considérer comme un développement normal. Il utilise les mêmes principes et approches que les développeurs utilisent.
- Le résultat est une interface strictement définie: vous ne pouvez pas faire quelque chose directement avec le simulateur, pour cela, vous devez ouvrir un ticket dans le serveur de périphériques, et nous allons voir comment le faire de manière optimale sans casser d'autres tests.
- L'environnement de test est devenu moins cher parce que nous l'avons augmenté dans * nix, qui sont beaucoup moins chers que les coquelicots de service.
- Et le partage des ressources est apparu, car il y a une seule couche avec laquelle tout le monde communique, il peut planifier la distribution des machines situées derrière, c'est-à-dire partager les ressources entre les agents.

Ci-dessus est représenté, comme c'était le cas auparavant. À gauche, des unités de temps conventionnelles, disons des dizaines de minutes. Il y a deux agents, 7 simulateurs sont connectés à chacun, au moment où 0 build arrive et prend 40 minutes. Après 20 minutes, un autre arrive et prend le même temps. Tout semble super. Mais là, et il y a des carrés gris. Ils signifient que nous avons perdu de l'argent parce que nous n'avons pas utilisé les ressources disponibles.

Vous pouvez le faire: la première version arrive et voit tous les simulateurs gratuits, est distribuée et les tests sont accélérés deux fois. Il n'y avait rien à faire. En réalité, cela se produit souvent parce que les développeurs poussent rarement leurs brunchs au même moment. Bien que cela se produise parfois, les "pions", les "pyramides" et similaires commencent. Cependant, dans la plupart des cas, une accélération gratuite peut être obtenue deux fois en installant simplement un système de gestion centralisé pour toutes les ressources.
Autres raisons de passer à cela:
- Boxe noire, c'est-à-dire que maintenant le serveur de périphérique est une boîte noire. Lorsque vous écrivez des tests, vous ne pensez qu'aux tests et pensez que cette boîte noire fonctionnera toujours. Si cela ne fonctionne pas, vous allez juste frapper qui devrait le faire, c'est-à-dire moi. Et je dois le réparer. Non seulement moi, en fait, plusieurs personnes sont impliquées dans l'ensemble de l'infrastructure.
- Vous ne pouvez pas gâcher l'intérieur du simulateur.
- Vous n'avez pas besoin de mettre un million d'utilitaires sur la machine pour que tout démarre - il vous suffit de mettre un utilitaire qui masque tout le travail sur le serveur de périphériques.
- Il est devenu plus facile de mettre à jour l'infrastructure, dont nous parlerons quelque part à la fin.
Une question raisonnable: pourquoi pas Selenium Grid? Premièrement, nous avions beaucoup de code hérité, 1 500 tests, 130 000 lignes de code pour différentes plates-formes. Et tout cela a été contrôlé par parallel_cucumber, qui a créé le cycle de vie du simulateur en dehors du test. Autrement dit, il y avait un système spécial qui chargeait le simulateur, attendant qu'il soit prêt et le soumettant au test. Afin de ne pas tout réécrire, nous avons décidé d'essayer de ne pas utiliser Selenium Grid.
Nous avons également de nombreuses actions non standard et nous utilisons très rarement WebDriver. La partie principale des tests sur Calabash, et WebDriver uniquement auxiliaire. Autrement dit, nous n'utilisons pas de sélénium dans la plupart des cas.
Et, bien sûr, nous voulions que tout soit flexible, facile à prototyper. Parce que tout le projet a commencé simplement avec une idée qu'ils ont décidé de tester, mise en œuvre en un mois, tout a commencé et c'est devenu la décision principale de notre entreprise. Soit dit en passant, nous avons d'abord écrit en Ruby, puis réécrit le serveur de périphériques sur Kotlin. Les tests se sont avérés être sur Ruby et le serveur sur Kotlin.
Serveur d'appareil
Maintenant, en savoir plus sur le serveur de périphériques lui-même, comment il fonctionne. Lorsque nous avons commencé à étudier ce problème, nous avons utilisé les outils suivants:
- xcrun simctl et fbsimctl - utilitaires de ligne de commande pour gérer les simulateurs (le premier est officiellement d'Apple, le second de Facebook, il est un peu plus pratique à utiliser)
- WebDriverAgent, également de Facebook, afin de lancer des applications en dehors du processus lorsque la notification push arrive ou quelque chose comme ça
- ideviceinstaller, pour mettre l'application sur des appareils physiques puis automatiser en quelque sorte sur l'appareil.
, device server, . , fbsimctl , xcrun simctl ideviceinstaller, , fbsimctl WebDriverAgent. - . : - , Facebook . , fbsimctl . :

, .

, .
? , curl list, :

JSON, , . , .

, approve — , . open deep links . , , fbsimctl. , :

, . - . : . , , .
- — . liveshot' iPhone X, iPhone 5S, iPhone 6s. .
- - WebDriverAgent XCUI- , .
- . - iOS 8 , , . device server iOS 8, , , - . fbsimctl.
- , cookies , , , .
- — . , device server , , , , . , . , .

, - , . — , . — , , , .

: Test Runner, ; Device Provider, Device Server, ; Remote Device — ; Device Server — -. , - - fbsimctl WebDriverAgent.
? Test Runner capability, iPhone 6. Device Provider, device server, , - , , , . Device Server . RemoteDevice .
, fbsimctl. , , headless-. , , headless-. - , . , , , syslog SpringBoard .
, XCTest, WebDriverAgent, healthCheck, WebDriverAgent , . , «ready» . healthCheck. , .

fbsimctl. . , WebDriverAgent, . .
— , device server, , , . (release), , , . . , device server , Test Runner . , -, , - .
— . . 30 60. , . , 30 . : , ?
. — . , .
. , , . Separation of Concerns — , , .
. , , Xcode 9, . Xcode 9.2, , — . , - .
Nous avons grandement simplifié le Test Runner, qui comprenait rsync, ssh et d'autres logiques. Maintenant, tout cela est jeté et fonctionne quelque part sur * nix, dans des conteneurs Docker.Les prochaines étapes: préparer le serveur de périphériques pour l'open source (après le rapport, il a été publié sur GitHub ) , et nous pensons à supprimer ssh, car cela nécessite une configuration supplémentaire sur les machines et complique dans la plupart des cas la logique et le support de l'ensemble du système. Mais maintenant, vous pouvez prendre le serveur de périphériques, l'activer sur toutes les machines ssh, et les tests fonctionneront vraiment sans problème.
Trucs et astuces
Maintenant, la chose la plus importante est toutes sortes d'astuces et de choses utiles que nous avons trouvées lors de la création d'un serveur de périphériques et de cette infrastructure.
Le premier est le plus simple. Comme vous vous en souvenez, nous avions un MacBook Pro, tous les tests ont été exécutés sur des ordinateurs portables. Nous les lançons maintenant sur Mac Pro.

Voici deux configurations. Ce sont en fait les meilleures versions de chacun des appareils. Sur le MacBook, nous pourrions exécuter de manière stable 6 simulateurs en parallèle. Si vous essayez de charger plus en même temps, les simulateurs commencent à échouer car ils chargent fortement le processeur, ils ont des verrous mutuels, etc. Vous pouvez exécuter 18 sur le Mac Pro - c'est très facile à calculer, car au lieu de 4, il y a 12 cœurs. Nous multiplions par trois - vous obtenez environ 18 simulateurs. En fait, vous pouvez essayer d'exécuter un peu plus, mais ils doivent en quelque sorte être séparés dans le temps, vous ne pouvez pas, par exemple, exécuter en une minute. Bien qu'il y ait un truc avec ces 18 simulateurs, ce n'est pas si simple.

Et c'est leur prix. Je ne me souviens pas combien il est en roubles, mais il est clair que cela coûte cher. Le coût de chaque simulateur pour le MacBook Pro coûte près de 400 £ et pour le Mac Pro près de 330 £. C'est déjà environ 70 £ d'économies sur chaque simulateur.
De plus, ces macbooks devaient être installés d'une certaine manière, ils devaient être chargés sur des aimants, qui devaient être collés sur du ruban adhésif, car parfois ils tombaient. Et vous avez dû acheter un adaptateur pour connecter Ethernet, car tant d'appareils à proximité dans la boîte de fer sur le Wi-Fi ne fonctionnent pas, il devient instable. L'adaptateur coûte également environ 30 £, lorsque vous divisez par 6, vous obtiendrez alors 5 £ supplémentaires pour chaque appareil. Mais si vous n'avez pas besoin de cette super-parallélisation, vous n'avez que 20 tests et 5 simulateurs, il est en fait plus facile d'acheter un MacBook, car vous pouvez le trouver dans n'importe quel magasin, et vous devrez commander et attendre le Mac Pro haut de gamme. Soit dit en passant, ils nous ont coûté un peu moins cher, car nous les avons pris en vrac et il y avait une sorte de réduction. Vous pouvez également acheter un Mac Pro avec une petite mémoire, puis vous mettre à niveau, en économisant encore plus.
Mais avec le Mac Pro, il y a une astuce. Nous avons dû les diviser en trois machines virtuelles, y mettre ESXi. Il s'agit de la virtualisation bare metal, c'est-à-dire d'un hyperviseur installé sur une machine nue, et non sur le système hôte. Il est l'hôte lui-même, nous pouvons donc exécuter trois machines virtuelles. Et si vous installez une sorte de virtualisation normale sur macOS, par exemple Parallels, vous ne pourrez exécuter que 2 machines virtuelles en raison des restrictions de licence Apple. J'ai dû le casser car CoreSimulator, le principal service gérant les simulateurs, s'est avéré avoir des verrous internes, et en même temps plus de 6 simulateurs n'étaient tout simplement pas chargés, ils ont commencé à attendre quelque chose dans la file d'attente, et le temps de chargement total de 18 simulateurs est devenu inacceptable. Au fait, ESXi coûte 0 €, c'est toujours bien quand quelque chose ne vaut rien, mais ça marche bien.
Pourquoi n'avons-nous pas mis en commun? En partie parce que nous avons accéléré la réinitialisation du simulateur. Supposons que le test se bloque, vous souhaitez nettoyer complètement le simulateur afin que le suivant ne se bloque pas en raison de fichiers obscurs restants dans le système de fichiers. La solution la plus simple consiste à arrêter le simulateur, à effacer explicitement (effacer) et à démarrer (démarrage).

Très simple, une ligne, mais prend 18 secondes. Et il y a six mois ou un an, cela a pris près d'une minute. Merci à Apple d'avoir optimisé cela, mais vous pouvez le faire plus compliqué. Téléchargez le simulateur et copiez ses répertoires de travail dans le dossier de sauvegarde. Et puis vous éteignez le simulateur, supprimez le répertoire de travail et copiez la sauvegarde, démarrez le simulateur.

Il s'avère que 8 secondes: le téléchargement s'est accéléré plus de deux fois. En même temps, il n'y avait rien de compliqué à faire, c'est-à-dire que dans le code Ruby, cela prend littéralement deux lignes. Dans l'image, je donne un exemple sur un bash afin qu'il puisse être facilement traduit dans d'autres langues.
La prochaine astuce. Il existe une application Bumble, elle est similaire à Badoo, mais avec un concept légèrement différent, beaucoup plus intéressant. Là, vous devez vous connecter via Facebook. Dans tous nos tests, puisque nous utilisons à chaque fois un nouvel utilisateur du pool, nous avons dû nous déconnecter du précédent. Pour ce faire, en utilisant WebDriverAgent, nous avons ouvert Safari, sommes allés sur Facebook, avons cliqué sur Déconnexion. Cela semble bien, mais cela prend presque une minute à chaque test. Une centaine de tests. Cent minutes supplémentaires.
De plus, Facebook aime parfois faire des tests A / B, afin qu'ils puissent changer les localisateurs, le texte sur les boutons. Soudain, un tas de tests tombera et tout le monde sera extrêmement mécontent. Par conséquent, via fbsimctl, nous créons list_apps, qui trouve toutes les applications.

Trouvez MobileSafari:

Et il y a un chemin vers le DataContainer, et il a un fichier binaire avec des cookies:

Nous le supprimons simplement - cela prend 20 ms. Les tests ont commencé à passer 100 minutes plus vite, sont devenus plus stables, car ils ne peuvent pas tomber à cause de Facebook. La parallélisation n'est donc parfois pas nécessaire. Vous pouvez trouver des endroits pour l'optimisation, c'est facile moins 100 minutes, rien n'a besoin d'être fait. Dans le code, ce sont deux lignes.
Ensuite: comment préparer les machines hôtes à exécuter des simulateurs.

Avec le premier exemple, beaucoup de ceux qui ont lancé Appium connaissent bien la désactivation du clavier dur. Le simulateur a l'habitude de connecter le clavier matériel sur l'ordinateur lors de la saisie de texte dans le simulateur et de masquer complètement le virtuel. Et Appium utilise un clavier virtuel pour saisir du texte. Par conséquent, après un débogage local des tests d'entrée, d'autres tests peuvent commencer à échouer en raison de l'absence de clavier. Avec cette commande, vous pouvez désactiver le clavier dur, et nous le faisons avant de soulever chaque nœud de test.

Le paragraphe suivant est plus pertinent pour nous, car l'application est liée à la géolocalisation. Et très souvent, vous devez exécuter des tests pour qu'il soit initialement désactivé. Vous pouvez définir 3101 dans le LocationMode. Pourquoi? Il y avait un article dans la documentation d'Apple, mais ils l'ont supprimé pour une raison quelconque. Maintenant, c'est juste une constante magique dans le code pour laquelle nous prions tous et espérons qu'il ne se cassera pas. Parce que dès qu'il se casse, tous les utilisateurs seront à San Francisco, car fbsimctl met un tel emplacement lors du chargement. D'un autre côté, nous le saurons facilement, car tout le monde sera à San Francisco.

La prochaine consiste à désactiver Chrome, un cadre autour du simulateur qui a divers boutons. Lors de l'exécution d'autotests, ce n'est pas nécessaire. Auparavant, la désactiver vous permettait de placer plus de simulateurs de gauche à droite pour voir comment tout se passe en parallèle. Maintenant, nous ne le faisons pas, car tout est sans tête. Combien ne vont pas dans la voiture, les simulateurs eux-mêmes ne seront pas visibles. Si cela est nécessaire, vous pouvez diffuser à partir du simulateur souhaité.

Il existe également un ensemble de différentes options que vous pouvez activer / désactiver. Parmi ceux-ci, je ne mentionnerai que SlowMotionAnimation, car j'ai eu un deuxième ou troisième jour très intéressant au travail. J'ai exécuté les tests, et ils ont tous commencé à tomber dans les délais d'attente. Ils n'ont pas trouvé les éléments dans l'inspecteur, bien qu'il l'ait été. Il s'est avéré qu'à ce moment-là, j'ai commencé Chrome, j'ai appuyé sur cmd + T pour ouvrir un nouvel onglet. À ce stade, le simulateur est devenu actif et a intercepté l'équipe. Et pour lui, cmd + T est un ralentissement de toutes les animations de 10 fois pour déboguer l'animation. Cette option doit également toujours être automatiquement désactivée si vous souhaitez exécuter des tests sur des machines auxquelles les utilisateurs ont accès, car ils peuvent interrompre accidentellement les tests en ralentissant les animations.
La chose probablement la plus intéressante pour moi, puisque je l'ai fait il n'y a pas si longtemps, est la gestion de toute cette infrastructure. 60 hôtes virtuels (en fait 64 + 6 agents TeamCity) que personne ne veut déployer manuellement. Nous avons trouvé l'utilitaire
xcversion - maintenant il fait partie de fastlane, un joyau Ruby qui peut être utilisé comme un utilitaire de ligne de commande: il automatise partiellement l'installation de Xcode. Ensuite, nous avons pris Ansible, écrit des playbooks, pour lancer fbsimctl partout dans la version souhaitée, Xcode et déployer des configurations pour le serveur de périphérique lui-même. Et Ansible pour supprimer et mettre à jour les simulateurs. Lorsque nous passons à iOS 11, nous quittons iOS 10. Mais lorsque l'équipe de test dit qu'elle abandonne complètement les tests automatiques sur iOS 10, nous passons simplement par Ansible et nettoyons les anciens simulateurs. Sinon, ils occupent beaucoup d'espace disque.

Comment ça marche? Si vous venez de prendre xcversion et de l'appeler sur chacune des 60 machines, cela prendra beaucoup de temps, car il va sur le site Web d'Apple et télécharge toutes les images. Pour mettre à jour les machines qui se trouvent dans le parc, vous devez sélectionner une machine qui fonctionne, exécutez xcversion install dessus avec la version nécessaire de Xcode, mais n'installez rien et ne supprimez rien. Le package d'installation sera téléchargé dans le cache. La même chose peut être faite pour n'importe quelle version du simulateur. Le package d'installation est placé dans ~ / Library / Caches / XcodeInstall. Ensuite, vous chargez tout avec Ceph, et s'il n'est pas là, démarrez une sorte de serveur Web dans ce répertoire. Je suis habitué à Python, donc je lance un serveur Python Python sur des machines.

Maintenant, sur n'importe quelle autre machine du développeur ou du testeur, vous pouvez faire installer xcversion et spécifier le lien vers le serveur surélevé. Il téléchargera xip à partir de la machine spécifiée (si le réseau local est rapide, cela se produira presque instantanément), déballez le package, confirmez la licence - en général, il fera tout pour vous. Il y aura un Xcode entièrement fonctionnel dans lequel il sera possible d'exécuter des simulateurs et des tests. Malheureusement, ils n'étaient pas si pratiques avec les simulateurs, vous devez donc faire curl ou wget, télécharger un package de ce serveur sur votre ordinateur local dans le même répertoire, exécuter les simulateurs xcversion --install. Nous avons placé ces appels dans des scripts Ansible et mis à jour 60 machines en une journée. Le temps principal a été pris par la copie de fichiers réseau. De plus, nous nous déplacions à ce moment-là, c'est-à-dire que certaines voitures ont été éteintes. Nous avons redémarré Ansible deux ou trois fois pour rattraper les voitures absentes lors du déménagement.
Un petit débriefing. Dans la première partie: il me semble que les priorités sont importantes. Autrement dit, vous devez d'abord avoir la stabilité et la fiabilité des tests, puis la vitesse. Si vous ne poursuivez que la vitesse, commencez à tout paralléliser, alors les tests fonctionneront rapidement, mais personne ne les regardera jamais, ils recommenceront tout jusqu'à ce que tout passe soudainement. Ou même marquer sur les tests et pousser vers le maître.
Le point suivant: l'automatisation est le même développement, vous pouvez donc simplement prendre les modèles que vous avez déjà pensés pour nous et les utiliser. Si maintenant votre infrastructure est étroitement liée aux tests et que la mise à l'échelle est planifiée, c'est le bon moment pour diviser d'abord, puis pour évoluer.
Et le dernier point: si la tâche est d'accélérer les tests, la première chose qui me vient à l'esprit est d'ajouter plus de simulateurs pour l'accélérer d'un facteur. En fait, très souvent, vous n'avez pas besoin d'ajouter, mais d'analyser soigneusement le code et d'optimiser tout avec quelques lignes, comme dans l'exemple avec les cookies. C'est mieux que la parallélisation, car 100 minutes ont été enregistrées avec deux lignes de code, et pour la parallélisation, vous devrez écrire beaucoup de code, puis prendre en charge la partie de fer de l'infrastructure. Pour l'argent et les ressources, cela coûtera beaucoup plus.
Ceux qui sont intéressés par ce rapport de la conférence de Heisenbug peuvent également être intéressés par le Heisenbug suivant: il se tiendra à Moscou du 6 au 7 décembre, et le site Web de la conférence contient déjà des descriptions d'un certain nombre de rapports (et, soit dit en passant, l' acceptation des demandes de rapports est toujours ouverte).