In de jaren zestig van de vorige eeuw werd het in de software engineering als een goede basispraktijk beschouwd om je code te testen terwijl je hem schreef. De pioniers van softwareontwikkeling in die tijd waren voorstanders van verschillende niveaus van testen; sommigen waren voorstander van “unit” testen en anderen niet, maar allen erkenden het belang van het testen van code.

Uitvoerbare testen zijn wellicht voor het eerst geïntroduceerd door Margaret Hamilton op het Apollo-project in het midden van de jaren zestig, waar zij de aanzet gaf tot een vorm van uitvoerbare controle die we nu “statische code-analyse” noemen. Zij noemde het “hogere-orde software”, waarmee zij bedoelde software die werkt tegen andere software in plaats van rechtstreeks tegen het probleemdomein. Haar hogere-orde software onderzocht broncode om te zoeken naar patronen waarvan bekend was dat ze leidden tot integratieproblemen.

Tegen 1970 was men uitvoerbaar testen grotendeels vergeten. Natuurlijk, mensen draaiden applicaties en poke op hen hier en daar met de hand, maar zolang het gebouw niet afbranden om hen heen, ze dachten dat de code was “goed genoeg”. Het resultaat is meer dan 35 jaar code in productie wereldwijd die onvoldoende is getest, en in veel gevallen niet helemaal werkt zoals bedoeld, of op een manier die de klanten tevreden stelt.

Het idee van programmeurs die testen terwijl ze gaan maakte een come-back vanaf het midden van de jaren 1990, hoewel tot op de dag van vandaag de overgrote meerderheid van de programmeurs het nog steeds niet doen. Infrastructuur ingenieurs en systeembeheerders testen hun scripts nog minder ijverig dan programmeurs hun applicatiecode testen.

Als we naar een tijdperk gaan waar snelle inzet van gecompliceerde oplossingen bestaande uit tal van autonome componenten de norm wordt, en “cloud” infrastucturen vereisen dat we duizenden come-and-go VM’s en containers beheren op een schaal die niet kan worden beheerd met behulp van handmatige methoden, kan het belang van uitvoerbaar, geautomatiseerd testen en controleren tijdens het hele ontwikkelings- en leveringsproces niet worden genegeerd; niet alleen voor applicatieprogrammeurs, maar voor iedereen die betrokken is bij IT-werk.

Met de komst van devops (kruisbestuiving van ontwikkelings- en operationele vaardigheden, methoden en hulpmiddelen), en trends zoals “infrastructuur als code” en “automatiseer alle dingen,” unit testen is een basisvaardigheid geworden voor programmeurs, testers, systeembeheerders, en infrastructuur engineers gelijk.

In deze serie van berichten, introduceren we het idee van unit testing van shell scripts, en dan zullen we verschillende unit test frameworks verkennen die kunnen helpen om die taak praktisch en duurzaam te maken op schaal.

Een andere praktijk die onbekend kan zijn voor veel infrastructuur engineers is versiebeheer. Later in deze serie zullen we ingaan op versiebeheersystemen en werkstromen die applicatie-ontwikkelaars gebruiken, en die ook effectief en nuttig kunnen zijn voor infrastructuur-engineers.

Een Script om te testen

Vivek Gite publiceerde een voorbeeld van een shellscript om schijfgebruik te monitoren en een e-mailnotificatie te genereren wanneer bepaalde bestandssystemen een drempel overschrijden. Zijn artikel staat hier: https://www.cyberciti.biz/tips/shell-script-to-watch-the-disk-space.html. Laten we dat als test gebruiken.

De eerste versie van zijn script, met de toevoeging van de -P optie op het df commando om regelafbrekingen in de uitvoer te voorkomen, zoals voorgesteld in een commentaar van Per Lindahl, ziet er als volgt uit:

#!/bin/shdf -HP | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print  " "  }' | while read output;do usep=$(echo $output | awk '{ print }' | cut -d'%' -f1 ) partition=$(echo $output | awk '{ print  }' ) if ; then echo "Running out of space \"$partition ($usep%)\" on $(hostname) as on $(date)" | mail -s "Alert: Almost out of disk space $usep%" [email protected] fidone

Vivek gaat verder met het verfijnen van het script voorbij dat punt, maar deze versie zal dienen voor de doeleinden van dit bericht.

Geautomatiseerde functionele controles

Een paar vuistregels over geautomatiseerde functionele controles, of we nu applicatiecode of een script of een ander soort software controleren:

  • de controle moet elke keer identiek worden uitgevoerd, zonder handmatige aanpassingen ter voorbereiding op elke run; en
  • het resultaat mag niet kwetsbaar zijn voor veranderingen in de uitvoeringsomgeving, of gegevens, of andere factoren buiten de geteste code.

Pass, Fail, and Error

Je zou erop kunnen wijzen dat het mogelijk is dat het script helemaal niet wordt uitgevoerd. Dat is normaal voor elk soort unit test framework voor elke soort applicatie. Drie uitkomsten, in plaats van twee, zijn mogelijk:

  • De geteste code vertoont het verwachte gedrag
  • De geteste code loopt, maar vertoont niet het verwachte gedrag
  • De geteste code loopt niet

Voor praktische doeleinden is de derde uitkomst hetzelfde als de tweede; we zullen moeten uitzoeken wat er fout ging en dat oplossen. Dus, we denken over het algemeen aan deze dingen als binair: Pass or fail.

Wat moeten we controleren?

In dit geval willen we controleren of het script zich gedraagt zoals verwacht, gegeven verschillende invoerwaarden. We willen onze unit checks niet vervuilen met andere controles.

Als we de geteste code bekijken, zien we dat wanneer het schijfgebruik een drempel van 90% bereikt, het script mail oproept om een bericht naar de systeembeheerder te sturen.

In overeenstemming met de algemeen aanvaarde goede praktijken voor unit checks, willen we afzonderlijke gevallen definiëren om elk gedrag te controleren dat we verwachten voor elke set van initiële condities.

Het opzetten van onze “tester” hoed, zien we dat dit een randvoorwaarde soort ding is. We hoeven niet elk individueel percentage van schijfgebruik te controleren. We hoeven alleen het gedrag op de grenzen te controleren. Daarom zal de minimale set van gevallen om een zinvolle dekking te bieden zijn:

  • Het stuurt een e-mail als het schijfgebruik de drempel bereikt
  • Het stuurt geen e-mail als het schijfgebruik onder de drempel is

Wat moeten we niet controleren?

In overeenstemming met de algemeen aanvaarde goede praktijken voor unit test isolatie, willen we ervoor zorgen dat elk van onze gevallen kan falen om precies één reden: Het verwachte gedrag gebeurt niet. Voor zover praktisch uitvoerbaar, willen we onze controles zo instellen dat andere factoren de case niet zullen doen falen.

Het is misschien niet altijd kosteneffectief (of zelfs mogelijk) om te garanderen dat externe factoren onze geautomatiseerde controles niet zullen beïnvloeden. Soms kunnen we een extern element niet controleren, of zou dat meer tijd, moeite en kosten vergen dan de waarde van de controle, en/of gaat het om een obscuur randgeval waarvan de kans dat het zich voordoet zeer klein is, of waarvan het effect zeer gering is wanneer het zich voordoet. Het is een kwestie van uw professionele oordeel. Als algemene regel geldt dat u moet proberen te voorkomen dat u afhankelijkheden creëert van factoren buiten het bereik van de te testen code.

We hoeven niet te controleren of de commando’s df, grep, awk, cut, en mail werken. Dat valt buiten het bereik van onze doelstellingen. Degene die de hulpprogramma’s onderhoudt, is daarvoor verantwoordelijk.

We willen wel weten of de uitvoer van het commando df niet wordt verwerkt zoals we verwachten door grep of awk. Daarom willen we dat de echte grep en awk commando’s worden uitgevoerd in onze controles, gebaseerd op uitvoer van het df commando dat overeenkomt met de bedoeling van elke test case. Dat is in scope omdat de command-line argumenten voor df onderdeel zijn van het script, en het script is de code die getest wordt.

Dat betekent dat we een nep-versie van het df commando nodig hebben om te gebruiken met onze unit checks. Zo’n nep-component wordt vaak een mock genoemd. Een mock vervangt een echte component en levert voorgedefinieerde output om het systeemgedrag op een gecontroleerde manier aan te sturen, zodat we het gedrag van de geteste code betrouwbaar kunnen controleren.

We zien dat het script een e-mail notificatie stuurt wanneer een bestandssysteem het drempelgebruiksniveau bereikt. We willen niet dat onze unit checks een hoop nutteloze emails uitspuwen, dus willen we het mail commando ook mocken.

Dit script is een goed voorbeeld om het mocken van deze commando’s te illustreren, omdat we het op een andere manier doen voor mail dan voor df.

Mocken van het df commando

Het script is gebouwd rond het df commando. De relevante regel in het script is:

df -HP | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print  " "  }'

Als je alleen df -HP uitvoert, zonder in grep te pipen, zou je uitvoer zien zoals dit:

Filesystem Size Used Avail Use% Mounted onudev 492M 0 492M 0% /devtmpfs 103M 6.0M 97M 6% /run/dev/sda1 20G 9.9G 9.2G 52% /tmpfs 511M 44M 468M 9% /dev/shmtmpfs 5.3M 0 5.3M 0% /run/locktmpfs 511M 0 511M 0% /sys/fs/cgrouptmpfs 103M 8.2k 103M 1% /run/user/1000

De grep en awk commando’s brengen de uitvoer terug tot dit:

0% udev52% /dev/sda1

We moeten de uitvoer van df controleren om onze testgevallen aan te sturen. We willen niet dat het resultaat van de controle varieert op basis van het werkelijke schijfgebruik op het systeem waar we de testsuite uitvoeren. We controleren niet het schijfgebruik; we controleren de logica van het script. Wanneer het script in productie draait, zal het het schijfgebruik controleren. Wat we hier doen is voor validatie, niet voor productie-operaties. Daarom hebben we een nep of “mock” df commando nodig waarmee we de “test data” voor elk geval kunnen genereren.

Op een *nix platform is het mogelijk om het echte df commando te overschrijven door een alias te definiëren. We willen dat het alias-commando testwaarden uitzendt in hetzelfde formaat als df -HP uitvoert. Hier is een manier om dat te doen (dit is allemaal één regel; het is hieronder opgedeeld voor de leesbaarheid):

alias df="shift;echo -e 'Filesystem Size Used Avail Use% Mounted on'; echo -e 'tempfs 511M 31M 481M 6% /dev/shm'; echo -e '/dev/sda1 20G 9.9G 9.2G 52% /'"

De verschuiving slaat het ‘-HP’ argument over wanneer het script wordt uitgevoerd, zodat het systeem niet zal klagen dat -HP een onbekend commando is. Het ge-aliaste df commando geeft uitvoer in dezelfde vorm als df -HP.

De testwaarden worden in grep en dan in awk gepijpt als het script wordt uitgevoerd, zodat we alleen het minimale mocken dat nodig is om onze testgevallen te controleren. We willen dat onze testgevallen zo dicht mogelijk bij het “echte werk” liggen, zodat we geen valse positieven krijgen.

Mocks die via een mocking-bibliotheek zijn gemaakt, kunnen een vooraf gedefinieerde waarde retourneren wanneer ze worden aangeroepen. Onze aanpak voor het mocken van het df commando weerspiegelt die functie van een mock; we specificeren vooraf gedefinieerde output die moet worden geretourneerd wanneer de geteste code df aanroept.

Mocking the mail Command

We willen weten of het script onder de juiste omstandigheden een e-mail probeert te versturen, maar we willen niet dat het ergens een echte e-mail verstuurt. Daarom willen we het mail commando een alias geven, net zoals we eerder het df commando deden. We moeten iets opzetten dat we na elke test kunnen controleren. Een mogelijkheid is om een waarde naar een bestand te schrijven wanneer mail wordt aangeroepen, en dan de waarde te controleren in onze testgevallen. Dit wordt getoond in het voorbeeld hieronder. Andere methoden zijn ook mogelijk.

Mocks gemaakt via een mocking library kunnen het aantal keren tellen dat ze worden aangeroepen door de code die wordt getest, en we kunnen het verwachte aantal aanroepen bevestigen. Onze aanpak voor het mocken van het mail commando weerspiegelt die functie van een mock; als de tekst “mail” aanwezig is in het bestand mailsent nadat we het diskusage.sh script hebben uitgevoerd, betekent dit dat het script het mail commando heeft aangeroepen.

Patroon voor het uitvoeren van geautomatiseerde controles

Geautomatiseerde of uitvoerbare controles op elk abstractieniveau, voor elk soort applicatie of script, in elke taal, bestaan gewoonlijk uit drie stappen. Deze hebben gewoonlijk de namen:

  • Arrange
  • Act
  • Assert

De reden hiervoor is waarschijnlijk dat iedereen van alliteratie houdt, vooral op de letter A, aangezien het woord “alliteratie” zelf met de letter A begint.

Wat de reden ook is, in de arrange stap stellen we de randvoorwaarden op voor onze test case. In de act stap roepen we de te testen code aan. In de assert stap geven we het resultaat aan dat we verwachten te zien.

Wanneer we een test framework of library gebruiken, handelt de tool de assert stap netjes voor ons af, zodat we niet veel omslachtige if/else logica in onze test suites hoeven te coderen. In ons eerste voorbeeld gebruiken we geen test framework of library, dus controleren we de resultaten van elke case met een if/else blok. In de volgende aflevering zullen we spelen met unit test frameworks voor shell talen, en zien hoe dat eruit ziet.

Hier is ons ruwe-maar-effectieve testscript voor het testen van Vivek’s shell script, dat we diskusage.sh hebben genoemd:

#!/bin/bashshopt -s expand_aliases# Before allalias mail="echo 'mail' > mailsent;false"echo 'Test results for diskusage.sh' > test_resultstcnt=0# It does nothing when disk usage is below 90%# Before (arrange)alias df="echo 'Filesystem Size Used Avail Use% Mounted on';echo '/dev/sda2 100G 89.0G 11.0G 89% /'"echo 'no mail' > mailsent# Run code under test (act). ./diskusage.sh# Check result (assert)((tcnt=tcnt+1))if ]; then echo "$tcnt. FAIL: Expected no mail to be sent for disk usage under 90%" >> test_resultselse echo "$tcnt. PASS: No action taken for disk usage under 90%" >> test_resultsfi # It sends an email notification when disk usage is at 90%alias df="echo 'Filesystem Size Used Avail Use% Mounted on';echo '/dev/sda1 100G 90.0G 10.0G 90% /'"echo 'no mail' > mailsent. ./diskusage.sh((tcnt=tcnt+1))if ]; then echo "$tcnt. PASS: Notification was sent for disk usage of 90%" >> test_resultselse echo "$tcnt. FAIL: Disk usage was 90% but no notification was sent" >> test_resultsfi # After allunalias dfunalias mail# Display test results cat test_results

Hier is een walkthrough van het testscript.

First, je ziet dat we bash gebruiken om een gewoon oud .sh bestand te testen. Dat is perfect in orde. Het is niet nodig, maar het is prima.

Volgende, zie je een shopt commando. Dat zorgt ervoor dat de shell onze test aliassen uitbreidt wanneer de subshell wordt aangeroepen om het diskusage.sh script uit te voeren. In de meeste gevallen zouden we geen aliassen doorgeven aan subshells, maar unit testen is een uitzondering.

De opmerking, “Before all,” is voor mensen die bekend zijn met unit test frameworks die set up en tear down commando’s hebben. Deze worden vaak genoemd zoiets als “before” en “after,” en er is meestal een paar dat de hele testsuite omvat en een ander paar dat individueel wordt uitgevoerd voor elke testcase.

We wilden laten zien dat het definiëren van de alias voor mail, het initialiseren van het testresultatenbestand, en het initialiseren van de testcase-teller allemaal precies één keer worden gedaan, aan het begin van de testsuite. Dit soort dingen is normaal in uitvoerbare testsuites. Het feit dat we een shell script testen in plaats van een applicatie programma verandert daar niets aan.

De volgende opmerking, “Het doet niets…” geeft het begin aan van onze eerste individuele test case. De meeste unit test frameworks bieden een manier om elke case een naam te geven, zodat we kunnen bijhouden wat er aan de hand is en zodat andere tools test cases kunnen zoeken, filteren en extraheren om verschillende redenen.

Volgende, er is een opmerking die luidt, “Before (regelen)”. Deze vertegenwoordigt een opstelling die alleen van toepassing is op die ene testzaak. We stellen de df alias in om de uitvoer te genereren die we nodig hebben voor dit specifieke geval. We schrijven ook de tekst, “no mail”, naar een bestand. Zo kunnen we zien of het diskusage.sh script geprobeerd heeft een notificatie email te sturen.

De volgende stap is het oefenen van de geteste code. In dit geval betekent dat het uitvoeren van het diskusage.sh script zelf. We sourceen het in plaats van het direct uit te voeren.

Nu doen we de assert stap, die we in dit voorbeeld op de moeilijke manier doen omdat we nog geen test framework hebben geïntroduceerd. We verhogen de testteller, zodat we de testgevallen in het resultatenbestand kunnen nummeren. Anders, als we een groot aantal gevallen hadden, zou het moeilijk kunnen worden om uit te zoeken welke gefaald hadden. Test frameworks handelen dit voor ons af.

De alias die we gedefinieerd hebben voor het mail commando schrijft de tekst ‘mail’ naar het mailsent bestand. Als diskusage.sh mail aanroept, dan zal het mailsent bestand ‘mail’ bevatten in plaats van de initiële waarde, ‘geen mail’. Je kunt zien wat de pass en fail condities zijn door de strings te lezen die geëchood worden in het test resultaten bestand.

Beginnend met de opmerking, “Het stuurt een email notificatie…” herhalen we de arrange, act, assert stappen voor een andere test case. We laten ons nep df commando deze keer andere gegevens uitzenden, om ander gedrag van de geteste code te veroorzaken.

Waar de “After all” opmerking verschijnt, ruimen we na onszelf op door de definities te elimineren die we hebben gemaakt in de “Before all” opstelling boven aan het testscript.

Ten slotte, dumpen we de inhoud van het test_results bestand zodat we kunnen zien wat we hebben. Het ziet er als volgt uit:

Test results for diskusage.sh1. PASS: No action taken for disk usage under 90%2. PASS: Notification was sent for disk usage of 90%

Waarom een Test Framework/Bibliotheek?

We hebben zojuist een paar unit test cases geschreven voor een shell script zonder gebruik te maken van een test framework, mocking library, of assertion library. We ontdekten dat systeemcommando’s kunnen worden gemocked door aliassen te definiëren (tenminste op *nix systemen), dat asserties kunnen worden geïmplementeerd als conditionele statements, en dat de basisstructuur van een unit test eenvoudig met de hand op te zetten is.

Het was niet moeilijk om dit te doen zonder een framework of bibliotheek. Wat is dan het voordeel?

Test frameworks en bibliotheken vereenvoudigen en standaardiseren de testcode en maken veel leesbaardere testsuites mogelijk dan met de hand gemaakte scripts met veel conditionele statements. Sommige bibliotheken bevatten nuttige extra functies, zoals de mogelijkheid om uitzonderingen op te vangen of de mogelijkheid om tabelgedreven en datagedreven testgevallen te schrijven. Sommige zijn op maat gemaakt om specifieke producten te ondersteunen die interessant zijn voor infrastructuur engineers, zoals Chef en Puppet. En sommige bevatten functionaliteit om code coverage bij te houden en/of testresultaten te formatteren in een vorm die bruikbaar is voor tooling in de CI/CD pijplijn, of op zijn minst een web browser.

Unit Test Frameworks for Scripts

In deze serie zullen we verschillende unit test frameworks voor shell scripts en scripting talen onderzoeken. Hier is een overzicht:

  • shunit2 is een zeer solide Open Source project met een geschiedenis van tien jaar. Oorspronkelijk ontwikkeld door Kate Ward, een Site Reliability Engineer en Manager bij Google gevestigd in Zürich, wordt het actief ontwikkeld en ondersteund door een team van zes mensen. Van een bescheiden begin als een point solution om een logging library voor shell scripts te testen, is het doelbewust ontwikkeld tot een general-purpose unit test framework dat meerdere shell talen en besturingssystemen ondersteunt. Het bevat een aantal nuttige functies die verder gaan dan eenvoudige assertions, inclusief ondersteuning voor data-driven en tabel-driven tests. Het gebruikt de traditionele “assertThat” stijl van assertions. De project site bevat uitstekende documentatie. Voor algemene unit testen van shell scripts, is dit mijn top aanbeveling.
  • BATS (Bash Automated Testing System) is een unit test framework voor bash. Het is ongeveer zeven jaar geleden gemaakt door Sam Stephenson, en heeft een tiental bijdragers gehad. De laatste update was vier jaar geleden, maar dit is niets om je zorgen over te maken, aangezien dit soort gereedschap geen frequente updates of onderhoud nodig heeft. BATS is gebaseerd op het Test Anything Protocol (TAP), dat een consistente tekst-gebaseerde interface definieert tussen modules in elk soort test harnas. Het staat een schone, consistente syntaxis in testgevallen toe, hoewel het niet veel syntactische suiker lijkt toe te voegen buiten gewone bash statements. Er is bijvoorbeeld geen speciale syntaxis voor asserties; je schrijft bash commando’s om resultaten te testen. Met dat in gedachten, kan de belangrijkste waarde liggen in het organiseren van testsuites en -gevallen op een logische manier. Merk ook op dat het schrijven van testscripts in bash ons er niet van weerhoudt om niet-bash scripts te testen; dat deden we eerder in deze post. Het feit dat de BATS syntax zo dicht bij de gewone bash syntax ligt geeft ons veel flexibiliteit om met verschillende shell talen om te gaan in onze testsuites, ten koste van de leesbaarheid (afhankelijk van wat je “leesbaar” vindt; het beoogde publiek voor deze post vindt de gewone shell taal syntax waarschijnlijk vrij leesbaar). Een bijzonder interessante functie (naar mijn mening) is dat u uw tekstverwerker kunt instellen met syntax highlighting voor BATS, zoals gedocumenteerd op de project wiki. Emacs, Sublime Text 2, TextMate, Vim, en Atom werden ondersteund op de datum van dit bericht.
  • zunit (niet die van IBM, die andere) is een unit test framework voor zsh ontwikkeld door James Dinsdale. De project site zegt dat zunit is geïnspireerd door BATS, en het bevat de zeer nuttige variabelen $state, $output, en $lines. Maar het heeft ook een definitieve assertion syntax die het patroon volgt, “assert actual matches expected”. Elk van deze frameworks heeft enkele unieke eigenschappen. Een interessante eigenschap van ZUnit, naar mijn mening, is dat het alle testgevallen die geen assertion bevatten als “riskant” zal markeren. Je kunt dit opheffen en de cases forceren om te draaien, maar standaard helpt het framework je herinneren om een assertion in elke test case op te nemen.
  • bash-spec is een behavioral-style test framework dat alleen bash ondersteunt (of tenminste, het is alleen getest tegen bash scripts). Het is een bescheiden zijproject van mij dat al meer dan vier jaar bestaat en een paar “echte” gebruikers heeft. Het wordt niet veel bijgewerkt, omdat het momenteel doet waarvoor het bedoeld was. Een van de doelstellingen van het project was om bash functies te gebruiken in een “vloeiende” stijl. Functies worden achtereenvolgens aangeroepen, waarbij elke functie de volledige argumentenlijst doorgeeft aan de volgende nadat het zoveel argumenten heeft gebruikt als het nodig heeft om zijn taak uit te voeren. Het resultaat is een leesbare testsuite, met statements als “expect package-name to_be_installed” en “expect arrayname not to_contain value”. Wanneer het gebruikt wordt om test-eerst ontwikkeling van scripts te begeleiden, leidt het ontwerp de ontwikkelaar ertoe om functies te schrijven die het idee van “modulariteit” of “enkele verantwoordelijkheid” of “scheiding van belangen” (noem het wat je wilt) ondersteunen, wat resulteert in onderhoudsgemak en gemakkelijk herbruikbare functies. “Gedragsstijl” betekent dat asserties de vorm hebben van, “verwacht dat dit overeenkomt met dat.”
  • korn-spec is een port van bash-spec voor de korn shell.
  • Pester is het unit test framework bij uitstek voor Powershell. Powershell ziet eruit en voelt meer als een applicatie programmeertaal dan puur een scripting taal, en Pester biedt een volledig consistente ontwikkelaar ervaring. Pester wordt geleverd met Windows 10 en kan worden geïnstalleerd op elk ander systeem dat Powershell ondersteunt. Het heeft een robuuste assertion library, ingebouwde ondersteuning voor mocking, en verzamelt code coverage metrics.
  • ChefSpec bouwt voort op rspec om een behavioral-style test framework te bieden voor Chef recepten. Chef is een Ruby applicatie, en ChefSpec maakt volledig gebruik van rspec mogelijkheden plus ingebouwde ondersteuning voor Chef-specifieke functionaliteit.
  • rspec-puppet is een behavioral-style framework voor Puppet, functioneel vergelijkbaar met ChefSpec.

admin

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.

lg