Tests / spécifications iOS TDD / BDD et tests d'intégration et d'acceptation

229

Quelles sont les meilleures technologies à utiliser pour le développement axé sur le comportement sur iPhone? Et quels sont les exemples de projets open source qui démontrent une bonne utilisation de ces technologies? Voici quelques options que j'ai trouvées:


Tests unitaires

Test :: Style d' unité

  1. OCUnit / SenTestingKit comme expliqué dans le Guide de développement iOS: Applications de test d'unité et autres références OCUnit .
  2. CAPTURE
  3. GHUnit
  4. Google Toolbox pour Mac: tests unitaires iPhone

Style RSpec

  1. Kiwi (qui vient également avec moquerie et attentes)
  2. Cèdre
  3. Jasmine avec UI Automation comme indiqué dans les spécifications de test d'acceptation iOS habiles

Test d'acceptation

Style sélénium

  1. UI Automation (fonctionne sur l'appareil)

    MISE À JOUR: Zucchini Framework semble mélanger Cucumber & UI Automation! :)

    Anciens articles de blog:

  2. UISpec avec UISpecRunner

  3. FoneMonkey

Style de concombre

  1. Frank et iCuke (basé sur le discours Concombre et iPhone )

  2. KIF (Keep It Functional) par Square

  3. Zucchini Framework utilise la syntaxe Cucumber pour écrire des tests et utilise CoffeeScript pour les définitions d'étapes.

Ajouts

Conclusion

Eh bien, évidemment, il n'y a pas de bonne réponse à cette question, mais voici ce que je choisis d'aller avec actuellement:

Pour les tests unitaires, j'avais l'habitude d'utiliser OCUnit / SenTestingKit dans XCode 4. C'est simple et solide. Mais, je préfère le langage de BDD à TDD ( Pourquoi RSpec est-il meilleur que Test :: Unit ?) Parce que nos mots créent notre monde. Alors maintenant, j'utilise Kiwi avec la complétion / autocomplétion de code ARC et Kiwi . Je préfère le kiwi au cèdre car il est construit au-dessus d'OCUnit et est livré avec des appariements et des mocks / stubs de style RSpec. MISE À JOUR: J'examine maintenant OCMock car, actuellement, Kiwi ne prend pas en charge le tronçonnage des objets pontés sans frais .

Pour les tests d'acceptation, j'utilise UI Automation car c'est génial. Il vous permet d'enregistrer chaque scénario de test, ce qui rend l'écriture des tests automatique. De plus, Apple le développe et a donc un avenir prometteur. Il fonctionne également sur l'appareil et à partir d'Instruments, ce qui permet d'autres fonctionnalités intéressantes, comme l'affichage des fuites de mémoire. Malheureusement, avec UI Automation, je ne sais pas comment exécuter le code Objective-C, mais avec Frank & iCuke vous pouvez. Donc, je vais simplement tester les éléments Objective-C de niveau inférieur avec des tests unitaires, ou créer des UIButtons uniquement pour la TESTconfiguration de construction , qui, lorsque vous cliquez dessus, exécutera le code Objective-C.

Quelles solutions utilisez-vous?

questions connexes

mattdipasquale
la source
1
il y a au moins quelques mois, je sais que les laboratoires pivots utilisaient du cèdre. (euh je suppose que c'est évident étant donné son sur leur compte github). Avec le soutien d'une boutique comme celle-là, ce serait mon choix.
Jed Schneider
1
C'est un bon point. Mais là encore, Apple suggérerait d'utiliser son cadre de tests unitaires, pas Cedar, non? Alors, c'est Pivotal Vs. Pomme. Avec quoi aller?
ma11hew28
2
J'ai écrit un article comparant Frank, KIF et UIAutomation qui pourrait intéresser les lecteurs de ce fil sgleadow.github.com/blog/2011/10/26/…
Stew

Réponses:

53

tl; dr

Chez Pivotal, nous avons écrit Cedar parce que nous utilisons et aimons Rspec sur nos projets Ruby. Cedar n'est pas censé remplacer ou concurrencer OCUnit; il est destiné à offrir la possibilité de tests de style BDD à Objective C, tout comme Rspec a lancé les tests de style BDD dans Ruby, mais n'a pas éliminé Test :: Unit. Le choix de l'un ou de l'autre dépend en grande partie des préférences de style.

Dans certains cas, nous avons conçu Cedar pour surmonter certaines lacunes dans la façon dont OCUnit fonctionne pour nous. Plus précisément, nous voulions pouvoir utiliser le débogueur dans les tests, exécuter des tests à partir de la ligne de commande et dans les builds CI, et obtenir une sortie texte utile des résultats des tests. Ces choses peuvent vous être plus ou moins utiles.

Longue réponse

Décider entre deux cadres de test comme Cedar et OCUnit (par exemple) se résume à deux choses: style préféré et facilité d'utilisation. Je vais commencer par le style, car c'est simplement une question d'opinion et de préférence; la facilité d'utilisation tend à être un ensemble de compromis.

Les considérations de style transcendent la technologie ou le langage que vous utilisez. Les tests unitaires de type xUnit existent depuis bien plus longtemps que les tests de style BDD, mais ces derniers ont rapidement gagné en popularité, en grande partie grâce à Rspec.

Le principal avantage des tests de style xUnit est leur simplicité et leur large adoption (parmi les développeurs qui écrivent des tests unitaires); presque tous les langages dans lesquels vous pourriez envisager d'écrire du code ont un framework de style xUnit disponible.

Les cadres de style BDD ont tendance à avoir deux différences principales par rapport au style xUnit: la façon dont vous structurez le test (ou les spécifications) et la syntaxe pour écrire vos assertions. Pour moi, la différence structurelle est le principal différenciateur. Les tests xUnit sont unidimensionnels, avec une méthode setUp pour tous les tests dans une classe de test donnée. Cependant, les classes que nous testons ne sont pas unidimensionnelles; nous devons souvent tester des actions dans plusieurs contextes différents, potentiellement conflictuels. Par exemple, considérons une simple classe ShoppingCart, avec une méthode addItem: (pour les besoins de cette réponse, j'utiliserai la syntaxe Objective C). Le comportement de cette méthode peut différer lorsque le panier est vide par rapport au moment où le panier contient d'autres articles; il peut différer si l'utilisateur a entré un code de réduction; il peut différer si l'élément spécifié peut " t être expédié par la méthode d'expédition sélectionnée; etc. Comme ces conditions possibles se croisent, vous vous retrouvez avec un nombre géométriquement croissant de contextes possibles; dans les tests de style xUnit, cela conduit souvent à de nombreuses méthodes avec des noms comme testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. La structure des cadres de style BDD vous permet d'organiser ces conditions individuellement, ce qui, selon moi, facilite la couverture de tous les cas, ainsi que la recherche, la modification ou l'ajout de conditions individuelles. Par exemple, en utilisant la syntaxe Cedar, la méthode ci-dessus ressemblerait à ceci: dans les tests de style xUnit, cela conduit souvent à de nombreuses méthodes avec des noms comme testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. La structure des cadres de style BDD vous permet d'organiser ces conditions individuellement, ce qui, selon moi, facilite la couverture de tous les cas, ainsi que la recherche, la modification ou l'ajout de conditions individuelles. Par exemple, en utilisant la syntaxe Cedar, la méthode ci-dessus ressemblerait à ceci: dans les tests de style xUnit, cela conduit souvent à de nombreuses méthodes avec des noms comme testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. La structure des cadres de style BDD vous permet d'organiser ces conditions individuellement, ce qui, selon moi, facilite la couverture de tous les cas, ainsi que la recherche, la modification ou l'ajout de conditions individuelles. Par exemple, en utilisant la syntaxe Cedar, la méthode ci-dessus ressemblerait à ceci:

describe(@"ShoppingCart", ^{
    describe(@"addItem:", ^{
        describe(@"when the cart is empty", ^{
            describe(@"with no discount code", ^{
                describe(@"when the shipping method applies to the item", ^{
                    it(@"should add the item to the cart", ^{
                        ...
                    });

                    it(@"should add the full price of the item to the overall price", ^{
                        ...
                    });
                });

                describe(@"when the shipping method does not apply to the item", ^{
                    ...
                });
            });

            describe(@"with a discount code", ^{
                ...
            });
        });

        describe(@"when the cart contains other items, ^{
            ...
        });
    });
});

Dans certains cas, vous trouverez des contextes contenant les mêmes ensembles d'assertions, que vous pouvez sécher en utilisant des exemples de contextes partagés.

La deuxième différence principale entre les cadres de style BDD et les cadres de style xUnit, la syntaxe d'assertion (ou "matcher"), rend simplement le style des spécifications un peu plus agréable; certaines personnes l'aiment vraiment, d'autres pas.

Cela pose la question de la facilité d'utilisation. Dans ce cas, chaque framework a ses avantages et ses inconvénients:

  • OCUnit existe depuis bien plus longtemps que Cedar et est directement intégré à Xcode. Cela signifie qu'il est simple de créer une nouvelle cible de test et, la plupart du temps, la mise en place et l'exécution des tests «fonctionnent tout simplement». D'un autre côté, nous avons constaté que dans certains cas, tels que l'exécution sur un appareil iOS, il était presque impossible de faire fonctionner les tests OCUnit. La configuration des spécifications Cedar nécessite plus de travail que les tests OCUnit, car vous avez vous-même la bibliothèque et le lien contre elle (jamais une tâche triviale dans Xcode). Nous travaillons à rendre la configuration plus facile et toutes les suggestions sont les bienvenues.

  • OCUnit exécute des tests dans le cadre de la génération. Cela signifie que vous n'avez pas besoin d'exécuter un exécutable pour exécuter vos tests; si des tests échouent, votre build échoue. Cela rend le processus d'exécution des tests plus simple, et la sortie du test va directement dans votre fenêtre de sortie de génération, ce qui la rend facile à voir. Nous avons choisi d'intégrer les spécifications Cedar dans un exécutable que vous exécutez séparément pour plusieurs raisons:

    • Nous voulions pouvoir utiliser le débogueur. Vous exécutez les spécifications Cedar comme vous exécuteriez tout autre exécutable, vous pouvez donc utiliser le débogueur de la même manière.
    • Nous voulions que la console se connecte facilement aux tests. Vous pouvez utiliser NSLog () dans les tests OCUnit, mais la sortie va dans la fenêtre de construction où vous devez déplier l'étape de construction pour la lire.
    • Nous voulions un rapport de test facile à lire, à la fois sur la ligne de commande et dans Xcode. Les résultats OCUnit apparaissent bien dans la fenêtre de construction dans Xcode, mais la construction à partir de la ligne de commande (ou dans le cadre d'un processus CI) entraîne une sortie de test entremêlée avec beaucoup, beaucoup d'autres sorties de construction. Avec des phases de construction et d'exécution distinctes, Cedar sépare la sortie afin que la sortie de test soit facile à trouver. Le lanceur de test Cedar par défaut copie le style d'impression standard "." pour chaque spécification qui passe, «F» pour les spécifications qui échouent, etc. Cedar a également la possibilité d'utiliser des objets reporter personnalisés, de sorte que vous pouvez obtenir les résultats de sortie comme vous le souhaitez, avec un petit effort.
  • OCUnit est le cadre de test unitaire officiel pour Objective C et est pris en charge par Apple. Apple a essentiellement des ressources illimitées, donc si elles veulent que quelque chose soit fait, cela se fera. Et, après tout, c'est le bac à sable d'Apple dans lequel nous jouons. Le revers de cette médaille, cependant, est qu'Apple reçoit chaque jour des commandes de support et des rapports de bogues. Ils sont remarquablement bons pour les gérer tous, mais ils peuvent ne pas être en mesure de gérer les problèmes que vous signalez immédiatement ou pas du tout. Cedar est beaucoup plus récent et moins cuit qu'OCUnit, mais si vous avez des questions, des problèmes ou des suggestions, envoyez un message à la liste de diffusion Cedar ([email protected]) et nous ferons ce que nous pouvons pour vous aider. N'hésitez pas non plus à bifurquer le code de Github (github.com/pivotal/cedar) et à ajouter tout ce qui vous semble manquant.

  • L'exécution de tests OCUnit sur des appareils iOS peut être difficile. Honnêtement, je n'ai pas essayé cela depuis un certain temps, donc cela a peut-être été plus facile, mais la dernière fois que j'ai essayé, je n'ai tout simplement pas pu obtenir de tests OCUnit pour que la fonctionnalité UIKit fonctionne. Lorsque nous avons écrit Cedar, nous nous sommes assurés de pouvoir tester le code dépendant d'UIKit à la fois sur le simulateur et sur les appareils.

Enfin, nous avons écrit Cedar pour les tests unitaires, ce qui signifie qu'il n'est pas vraiment comparable à des projets comme UISpec. Cela fait un bon moment que j'ai essayé d'utiliser UISpec, mais j'ai compris qu'il se concentrait principalement sur la conduite par programme de l'interface utilisateur sur un appareil iOS. Nous avons spécifiquement décidé de ne pas essayer que Cedar prenne en charge ce type de spécifications, car Apple était (à l'époque) sur le point d'annoncer UIAutomation.

Adam Milligan
la source
Merci pour la réponse complète. Je vais lire le livre RSpec et essayer Ceder. J'ai déplacé UISpec vers la section Selenium et y ai ajouté UIAutomation. Je lis votre article de blog sur UIAutomation. Frank semble en fait beaucoup plus simple et plus lisible, et mieux documenté, alors je pense commencer par cela. J'espère juste que c'est aussi puissant que UIAutomation. Vous dites que l'UIAutomation peut tester les problèmes de cycle de vie. Je me demande si iCuke peut aussi ...
ma11hew28
8

Je vais devoir lancer Frank dans le mélange de tests d'acceptation. Il s'agit d'un ajout assez récent mais qui a très bien fonctionné jusqu'à présent. En outre, il est en fait activement travaillé, contrairement à icuke et aux autres.

raidfive
la source
5

Pour le développement piloté par les tests, j'aime utiliser GHUnit , c'est un jeu d'enfant à configurer, et fonctionne très bien pour le débogage aussi.

Richard J. Ross III
la source
Merci. J'ai vu celui-là mais j'ai oublié de le mentionner.
ma11hew28
PLus 1 pour GHUnit. utilisé beaucoup avec OCMock. C'est un jeu d'enfant de configurer, d'étendre et de travailler de manière très fiable.
drekka
4

Grande liste!

J'ai trouvé une autre solution intéressante pour tester l'interface utilisateur des applications iOS.

Cadre de courgettes

Il est basé sur UIAutomation. Le cadre vous permet d'écrire des scénarios centrés sur l'écran dans un style semblable à Cucumber. Les scénarios peuvent être exécutés dans Simulator et sur l'appareil à partir d'une console (il est compatible CI).

Les assertions sont basées sur des captures d'écran. Cela semble inflexible, mais il vous offre un bon rapport HTML, avec une comparaison d'écran en surbrillance et vous pouvez fournir des masques qui définissent les régions que vous souhaitez avoir une assertion exacte des pixels.

Chaque écran doit être décrit dans CoffeScriptet l'outil lui-même est écrit en rubis. C'est une sorte de cauchemar polyglotte, mais l'outil fournit une belle abstraction pour UIAutomationet lorsque les écrans sont décrits, il est gérable même pour une personne qualifiée.

utilisateur1129998
la source
Serré! Merci. J'ai ajouté ceci à la question ci-dessus.
ma11hew28
2

Je choisirais iCuke pour les tests d'acceptation et Cedar pour les tests unitaires. UIAutomation est un pas dans la bonne direction pour Apple, mais les outils ont besoin d'un meilleur support pour une intégration continue; par exemple, l'exécution automatique de tests UIAutomation avec des instruments n'est actuellement pas possible.

SamCee
la source
1

GHUnit est bon pour les tests unitaires; pour les tests d'intégration, j'ai utilisé UISpec avec un certain succès (github fork ici: https://github.com/drync/UISpec ), mais j'ai hâte d'essayer iCuke, car il promet d'être une configuration légère, et vous pouvez utilisez les rails testant la qualité, comme RSpec et Cucumber.

Rob
la source
1

J'utilise actuellement des spectres pour des configurations comme rspec et son partenaire (comme mentionné ci-dessus) attenda qui a des tonnes d'options de correspondance impressionnantes.

Keith Smiley
la source
0

Il se trouve que j'aime vraiment OCDSpec2 mais je suis partial, j'ai écrit OCDSpec et je contribue à la seconde.

Il est très rapide même sur iOS, en partie parce qu'il est construit à partir de zéro plutôt que d'être placé sur OCUnit. Il a également une syntaxe RSpec / Jasmine.

https://github.com/ericmeyer/ocdspec2

Eric Smith
la source