Eenheid testen van privé-methoden in Xcode

Ik probeer testgestuurde ontwikkeling uit in een speelgoedproject. Ik kan de tests voor de openbare interface naar mijn lessen laten werken (hoewel ik nog steeds op het hek zit omdat ik meer testcode schrijf dan er is in de methoden die worden getest).

Ik heb de neiging om veel privé-methoden te gebruiken omdat ik de openbare interfaces graag schoon houd; ik zou echter nog steeds graag tests op deze methoden willen gebruiken.

Omdat Cocoa een dynamische taal is, kan ik deze privémethoden nog steeds aanroepen, maar ik krijg waarschuwingen in mijn tests dat mijn klas mogelijk niet op deze methoden reageert (hoewel dit duidelijk wel het geval is). Aangezien ik graag compileer zonder waarschuwingen, volgen hier mijn vragen:

  1. Hoe schakel ik deze waarschuwingen in Xcode uit?
  2. Kan ik nog iets anders doen om deze waarschuwingen uit te schakelen?
  3. Doe ik iets verkeerd bij het testen van ‘white box’?

Antwoord 1, autoriteit 100%

Onthoud dat er eigenlijk niet zoiets bestaat als “privémethoden” in Objective-C, en dat is niet alleen omdat het een dynamische taal is. Door het ontwerp heeft Objective-C zichtbaarheidsmodifiers voor ivars, maar niet voor methoden – het is niet per ongeluk dat je elke gewenste methode kunt aanroepen.

@Peter‘s suggestie is een goede. Om zijn antwoord aan te vullen, is een alternatief dat ik heb gebruikt (wanneer ik geen header wil/heb alleen voor privémethoden nodig) het declareren van een categorie in het unit-testbestand zelf. (Ik gebruik @interface MyClass (Test)als naam.) Dit is een geweldige manier om methoden toe te voegen die onnodig opzwellen in de releasecode, zoals voor toegang tot ivars die de geteste klasse heeft toegang tot. (Dit is duidelijk minder een probleem wanneer eigenschappen worden gebruikt.)

Ik heb gemerkt dat deze aanpak het gemakkelijk maakt om de interne status bloot te leggen en te verifiëren, en ook om alleen-testmethoden toe te voegen. In dit unit-testbestandschreef ik bijvoorbeeld een -isValidmethode voor het verifiëren van de juistheid van een binaire heap. In productie zou deze methode een verspilling van ruimte zijn, omdat ik aanneem dat een heap geldig is – ik geef er alleen om als ik test op regressies van eenheidstests als ik de code aanpas.


Antwoord 2, autoriteit 71%

Hoe schakel ik deze waarschuwingen in Xcode uit?

Niet doen.

Kan ik nog iets anders doen om deze waarschuwingen uit te schakelen?

Niet doen.

Doe ik iets verkeerd bij het testen van ‘white box’?

Nee.

De oplossing is om uw privémethoden naar een categorie in zijn eigen koptekst te verplaatsen. Importeer deze header in zowel de real class als de testcase class implementatiebestanden.


Antwoord 3, autoriteit 3%

Het lijkt erop dat een andere vraag het antwoord heeft: Is er een manier om waarschuwingen in Xcode te onderdrukken?


Antwoord 4, autoriteit 3%

Ik had hetzelfde probleem toen ik een paar dagen geleden begon met TDD. Ik heb dit zeer interessante standpunt gevonden in Testgestuurde iOS-ontwikkelingboek:

Mij is vaak gevraagd: “Moet ik mijn privémethoden testen?” of de gerelateerde vraag “Hoe moet ik mijn privémethoden testen?” Mensen die de tweede vraag stellen, gaan ervan uit dat het antwoord op de eerste “Ja” is en zijn nu op zoek naar een manier om de privé-interfaces van hun klassen in hun testsuites bloot te leggen.

Mijn antwoord is gebaseerd op observatie van een subtiel feit: je hebt je privémethoden al getest. Door de rood-groen-refactorbenadering te volgen die gebruikelijk is in testgestuurde ontwikkeling, hebt u de openbare API’s van uw objecten ontworpen om het werk te doen dat die objecten moeten doen. Met dat werk gespecificeerd door de tests – en de voortdurende uitvoering van de tests die je verzekeren dat je niets hebt gebroken – ben je vrij om het interne sanitair van je lessen te organiseren zoals je wilt.

Je privémethoden zijn al getest, omdat je alleen maar gedrag refactoreert waarvoor je al tests hebt uitgevoerd. Je mag nooit in een situatie terechtkomen waarin een privémethode niet of onvolledig getest is, omdat je ze pas maakt als je een kans ziet om de implementatie van openbare methodes op te schonen. Dit zorgt ervoor dat de privémethoden alleen bestaan ​​om de klassen te ondersteunen die ze tijdens het testen moeten aanroepen, omdat ze zeker worden aangeroepen vanuit openbare methoden.


Antwoord 5, autoriteit 2%

Hoewel het hebben van een privé-header of het definiëren van uw eigen categorie waarschijnlijk meer correcte oplossingen zijn, is er ook een andere, zeer eenvoudige oplossing: cast het object naar (id) voordat u de methode aanroept.


Antwoord 6, autoriteit 2%

Als u uw implementaties van privémethoden niet over meerdere bronbestanden wilt verspreiden, is een verfijning van de categorieoplossing het definiëren van een extensie (in wezen een anonieme categorie – raadpleeg Apple’s documentatie) in een headerbestand dat wordt geïmporteerd door zowel de implementatie van uw bestaande klas als de relevante bronbestanden voor unit-tests.

Door een extensie te gebruiken, kan de compiler u waarschuwen als de implementatie van de private methode niet aanwezig is in het hoofd @implementation-blok. Deze linkillustreert het mooi.


Antwoord 7

Eenvoudig werk. Stappen:
1. Je hebt -(NSString*)getTestString; in uw doel m-bestand voor interface Foo

  1. Voeg een categorie toe aan uw eenheidstestbestand:

    @interface DemoHomeViewController()
    -(NSString*)getTestString;
    @end

Doe dan nu alles wat je wilt.

Other episodes