E

Har du full kontroll på deres anlegg? Her får dere en sjekkliste som bør være til stor hjelp for å unngå å havne i unøde. kjhxzfjkhdasgjkh

sakjfbxakjfnkljax

xzlfknaflkjnxalkjnga


Sjekkliste:

  1. liste
  2. liste
  3. liste

Takk for at dere leste vår artikkel og meld dere på vårt nyhetsbrev for å motta info når vi publiserer nye artikler eller deler andre nyheter fra PQ.

Hva innebærer test av «Ikke-funksjonelle områder», hva betyr dette i praksis og ikke minst hva er risikoen ved å nedprioritere dette området?
En ofte brukt definisjon er «Test av områder som ikke dekkes av funksjonell testing», og dette er både ullent og litt feil. Dette er et område som dekker veldig mye og bredt og flere av de ikke-funksjonelle områdene testes direkte og indirekte gjennom test av funksjonalitet, integrasjoner og arbeidsprosesser.

Egentlig treffes «det ikke-funksjonelle» i alle testløp, kanskje uten at vi tenker over det. Vi i Promis Qualify anbefaler å ha større fokus på dette og ikke la tilfeldighetene styre. Vår erfaring tilsier at det er viktig å jobbe tidlig og mer med de ulike områdene og få planlegging og gjennomføring av test inn på agendaen, og inn i kontrakter og krav, på lik linje som funksjonalitet. Ofte ser vi at kravene i kontraktene er både klare og gode som grunnlag til test, men viktigheten forstås kanskje ikke og blir nedprioritert. Også for smidige og hybride organisasjoner må dette være tema, da det normalt kreves ressurser utenfor teamet til å stille krav og bidra.

Hvorfor skal vi prioritere tid og ressurser, dvs penger, til test av brukervennlighet, universell utforming, sikkerhet, GDPR, robusthet og feiltoleranse, logging, varsling og monitorering, backup og restore, ytelse, responstid, type PC, OS og nettlesere, tilganger osv osv? Det er fordi vi ikke ønsker hendelser i produksjon som betraktes som kritiske og alvorlige. Fortsatt er Test=Forebygging, uansett leveransemodell og produktutviklingsmetodikk.

Promis Qualifys testledere jobber basert på lang erfaring og anbefaler tidlig test med god nok testdekning på de områdene som peker seg ut som viktig og kritisk for aktuell leveranse. Dette skaper en god innledende dialog rundt området, og kan ende opp med en «god nok» testdekning av de områdene som prioriteres. I denne prosessen velger man bevisst bort flere områder, og dette bevisste valget er basert på erfaring, fagkompetanse og risikovurdering.

En eller annen gang og på en eller annen måte oppstår det spesielle situasjoner i løsninger i produksjon baser på «rare» feil. For disse mystiske feilene kan det være vanskelig å finne rotårsaken. Dette koster tid og tid er penger. Dette krever omprioritering av allerede opptatte fagpersoner. Det er derfor god kost-nytte i å finne disse feilene og problemene i test, i stedet for i produksjon. Det er ikke bare økonomien som treffes, men det oppstår press og stress i brukermiljøene og hos kunder, media henger seg på, ledelsen begynner å stille spørsmål (heldigvis!) osv.

Nesten daglig er det eksempler i media på problemer knyttet til IT løsninger og tjenester, og leser man mellom linjene er mange av disse knyttet til det vi i Promis Qualify definerer som det «Ikke-funksjonelle området».

Her er noen stikkord fra saker i media de siste ukene, noe hentet direkte ut fra teksten andre mellom linjene. Les gjennom og tenk hva dette kan bety for bedrift, organisasjon, renomme, kunder, konkurrenter, økonomi, samt interne og eksterne brukere. Ikke alle har monopol på sine tjenester og har råd til hendelser som i eksemplene under.

  • Følger ikke krav til sikkerhet, personvern, brudd på lovverk og forskrifter og brudd på personvern og GDPR
  • Støtter ikke krav til Universell utforming
  • Feil tilganger og tilgangsproblemer
  • Data blir borte eller havner hos feil mottaker, data som forsvinner er ikke mulig å finne igjen og uønsket deling av sensitive data
  • Alvorlig systemsvikt og løsning kollapser i perioder med mange brukere eller spesielt mye data og ytelsesproblemer skaper treghet, løsningen stoppet helt opp, brukere kastes ut, arbeid må gjøres på nytt (og på nytt)
  • Mangel på robusthet og feiltoleranse treffer brukerne daglig og skaper etterslep og manuelle grep for å levere på berørte tjenester
  • Løsningen taklet ikke endringer
  • Backup fungerer, men ikke restore – data blir borte
  • Tomt for lagringsplass (også i skyen) og minneproblemer som skaper bruk av feil data, synkroniseringsproblemer og behov for jevnlig refresh og restart
  • Logging og varsling har aldri fungert, historikken blir borte og tiden det tar å finne rotårsak til feil blir veldig lang. Bryter også med forskrifter og enkelte regelverk.

Alle bedrifter og organisasjoner vet hvor smertefullt det er når denne type hendelser inntreffer, og vår erfaring er at det etter denne type hendelser (spesielt de som har medieomtale, og det er nok et fåtall….) begynner man å fokusere mer på det ikke-funksjonelle.

Vi i Promis Qualify ønsker å bidra til at denne type hendelser avdekkes i test og ikke i produksjon. Vi har mange erfarne testledere innenfor området, og disse kan bidra med både rådgivning og mer operativt arbeid rundt «Test av ikke-funksjonelle områder».

Kontakt

Ta gjerne kontakt for å høre mer om hvordan vi kan hjelpe deg. Ved å velge Promis Qualify som din partner får du tryggheten fra fagpersoner som har ledet tilsvarende operasjoner tidligere. Vi kan vise til en rekke oppdragsgivere som gjennom vår bistand har fått et solid grunnlag for beslutningen om produksjonsstart.

Konfigurasjonskode?

Kodekonfigurasjon?

Systemparametre?

Parametersystem?

Kulturuke?

Kuruketul?

Vi testere blir ofte konfrontert med problemstillingen: “Dette er ikke en feil, det er jo bare konfigurasjon!”

Eller “Dette trenger vi ikke å teste, det er jo bare konfigurasjonsendringer”

Right! Vi testere har ofte meninger om det… Så hva er egentlig definisjonen på en konfigurasjonsendring og nøyaktig hvor går skillet mellom konfigurasjon og system?

Vår egen Richard Rostad har tanker og meninger om mangt, så også dette temaet!

En vanlig, teknokratisk definisjon er: “Alle endringer som ikke medfører at produktet må kompileres på nytt er en konfigurasjonsendring”

Da ender man fort opp med at et program skrevet i Python, som ikke skal kompileres, faktisk ikke er et program, men bare en lang rekke med konfigurasjonsparametre. Det gir åpenbart ikke noen fornuftig mening, så vi trenger noe annet.

Hva om vi både ser på hva som er systemet, og hva som er en systemendring som fører til en feil? La oss prøve med: “En feil er en endring som gjør at brukeropplevelsen forringes” (eller den litt mildere “… som gjør at brukeren ikke får utført oppgavene”)

Den møter også på en del problemere ganske fort: Særlig innen spillverdenen er det en hel del produkter som undertegnede ikke kan bruke rett å slett på grunn av manglende reaksjonsevne og hånd/øyekoordinasjon; mye på samme måte som jeg neppe noen gang vil kunne balansere mange tallerkener på kosteskaft.

Er det en ‘feil’ eller bør vi bytte bruker? Hva med farger? Er fargevalget i systemet vårt en feil siden det ikke kan brukes av fargeblinde eller skal vi kun ha kvinnelige ansatte fordi kvinner har gjennomgående bedre fargesyn?

Gitt kjønnsfordelingen blant programmerere vekker i hvert fall det siste spørsmålet ofte noen tanker. Det viser seg fort at begrepene ‘feil’, ‘system’, ‘konfigurasjon’ etc. er direkte vanskelige å sette skikkelig fast. Fenomenet vi har kommet borti er kjent som ‘systems boundary problems’ og er grundig behandlet i Jerry Weinbergs bøker om emnet General Systems Thinking. La oss ta et eksempel fra hans “Introduction To General Systems Thinking” (Gerald M. Weinberg, første gang utgitt i 1975)

The Appalachians er en fjellkjede som går langs Amerikas østkyst, fra langt nede i sørstatene og et godt stykke opp i Canada. I denne fjellkjeden lever det frosker. Er det en eller flere arter av frosker? Definisjonen av en art er at individer av samme art kan pare seg og få fruktbart avkom. Alle froskene langs hele kjeden kan gjøre dette med frosker som lever innenfor en avstand som en frosk kan vandre i sin levetid. Fra froskenes synspunkt er det med andre ord åpenbart samme art. På den annen side er klimaet i sørenden av fjellkjeden nærmest subtropisk, mens i nordenden begynner vi å snakke arktisk klima.

En frosk fra en av endene vil ikke engang kunne overleve i den andre, langt mindre produsere fruktbart avkom. Sett ‘utenfra’ er frosker fra hver ende av fjellkjeden åpenbart forskjellige arter. Men hvor går skillet? Det er ikke noe skille mellom froskeartene i Appalachia, men hvis man beveger seg langt nok er det allikevel opptil flere arter.

Det er en nøtt: Froskene er ikke ‘en art’ eller ‘flere arter’ men et system som har diffuse grenser – på samme måte som IT-systemer har diffuse grenser, konfigurasjon / kode har diffuse grenser og til og med systemfeil / brukerfeil har diffuse grenser. Å bli enige om en entydig definisjon av et system med diffuse grenser er ikke mulig fordi definisjonen avhenger av kontekst.

Froskenes kontekst er en ganske annen enn konteksten til forskerne som finner glede i å frakte frosker over mange breddegrader. En brukers opplevelse av ‘systemet’ er ganske annerledes enn en arkitekt som jobber med sammenhengen mellom subsystemer og enda lenger unna en programmerer som jobber med deler av et av subsystemene. Derfor er det ganske meningsløst å snakke om hva som er konfigurasjon og hva som er produkt uten først å definere hvilken kontekst vi snakker om.

Ofte, når vi kommer til spørsmålene som vi testere må forholde oss til er denne konteksten kjent som ‘kontrakten’*), hvor leverandør ønsker å definere mest mulig som konfigurasjon fordi rettinger da skjer for kundens regning, mens kunden ønsker å definere mest mulig av systemet som ‘kode’ fordi rettinger da faller på leverandør. Nye trender innen bransjen som ‘Infrastructure As Code’, ‘Security As Code’, etc. gjør ikke problemstillingen det grann enklere.

I brukerens kontekst er en ‘systemfeil’ noe som gjør at systemet ikke virker som jeg, som bruker, skulle ønske at det virket og som jeg med min kompetanseprofil ikke kan fikse selv. Hvorvidt feilen ligger i en konfigurasjonsfil, kompilert kode eller et bortgjemt kryss et eller annet sted i brukergrensesnittet er ganske uinteressant.

I maskinens kontekst er alt sammen, inklusive tastaturtrykk, musebevegelser eller taleinnput bare mange instanser av 0 eller 1 uansett.

Når det kommer til hvorvidt noe bør testes eller ikke så er vel et mer relevant spørsmål: “Kan en endring her føre til endret funksjonalitet eller forringet brukeropplevelse?” Hvis svaret er ja bør det testes uavhengig av om det er kode, konfigurasjon, dokumentasjon eller noe annet. Hvis det dukker opp et problem som fører til uønsket funksjonalitet eller forringet brukeropplevelse er jeg som tester mindre interessert i om det er en feil eller ikke og ganske mye mer interessert i om det blir fikset eller ikke.

Så får noen andre bekymre seg om hva som står i kontrakt og budsjett.

*) Dette motsetningsforholdet er grunnen til at undertegnede mener statens standardavtaler for IT anskaffelser er den største katastrofen som har truffet norsk IT miljø; gode systemer kommer ikke som følge av jurister som krangler om kontraktselementer, men fra godt samarbeid mellom alle parter. Hele konseptet ‘leverandør’ og ‘kunde’ står til hinder for gode brukeropplevelser.

La oss først snakke litt om Pizza:

Hvis vi lager en hjemmelaget pizza må vi holde styr på hele prosessen og er ansvarlige for alt fra ingredienser til at komfyren har strøm og helt frem til våre gode venner er gode og mette. Alternativt kan vi kjøpe en Grandiosa. Det blir ikke nødvendigvis det samme restultatet, men på den annen side trenger vi ikke tenke på ingredienser og sammensetning. Ovn, drikkevarer og gode venner må vi fremdeles sørge for.

Vi kan også bestille ferdig varm pizza levert på døren. Det blir ganske mye enklere og vi trenger bare å tenke på et sted å spise, god drikke og gode venner.

Hvis også det blir for mye å holde styr på kan vi be våre gode venner ut på en pizzarestaurant der utvalget av venner er det eneste vi trenger å tenke på. Dette kan vi fremstille slik:

Med skytjenester blir det nesten på samme måten: Vi kan ha det hele i kjelleren der vi er ansvarlige for at alt virker, vi kan bestille “Infrastructure As A Service” — der vi ikke trenger å holde styr på selve maskinparken, “Platform As A Service” — der vi egentlig bare har ansvar for våre egne applikasjoner og brukere eller “Software As A Service” der vi bare trenger å tenke på brukerne. De fleste kjenner den siste modellen i form av Office365.

For oss testere har dette både fordeler og ulemper; ting blir enklere fordi vi ikke har problemer med falske positive fordi noen har snublet i en nettverkskabel i kjelleren. På den annen side har vi en utfordring med ting som ytelsestester: Det eneste vi får testet med å kjøre en ytelsestest med stor belastning mot en Amazon PaaS er hvor stor regning Amazon kan sende oss — fordi plattformen skalerer sømløst uten vår innvirkning. Det er som regel en lite matnyttig test. Imidlertid er det fremdeles ønskelig å kjøre ytelsestester slik at vi kan avdekke flaskehalser for nettopp å redusere regningen fra Amazon, men de må kjøres på våre egne applikasjoner i isolasjon. Vi taper ikke så mye på det; all erfaring tilsier at flaskehalser, ineffektiv kode og bortkastede CPU sykluser ligger i den koden vi skriver selv — ikke den koden vi leier av Amazon. Når vi sier at vi ikke trenger å tenke på infrastruktur, er det som så mye annet en sannhet med modifikasjoner. Riktignok er leverandøren i de interessante scenariene ansvarlig for infrastruktur, men vi er ansvarlige for konfigurasjonen av infrastrukturen. Siden denne infrastrukturen styres av en skyplattform er det ikke lenger kabler som er plugget i riktig switch i kjelleren, men “Infrastructure as Code”

IaC er akkurat det det høres ut som; kode som styrer infrastrukturen vår. Som all annen kode bør også infrastrukturkode testes. Det er en ny og spennende problemstilling som ikke fryktelig mange testere har erfaring med enda.

Testing av infrastrukturkode

Infrastrukturkode har en del egenskaper som gjør at den normalt testes med andre metoder enn vanlig kode. Den viktigste forskjellen er at infrastrukturkode i all hovedsak er deklarativ hvilket vil si at den ikke er bygget opp rundt metoder og klasser men påstander om hvordan man ønsker verden skal se ut.

Eksempelvis: 

logstash:
  build:
     context: logstash/
     args:
        ELASTIC_VERSION: ${ELASTIC_VERSION}
     volumes:
– ./logstash/config/logstash.yml:/usr/share/ logstash/config/logstash.yml:ro,Z
– ./logstash/pipeline:/usr/share/logstash/ pipeline:ro,Z
     ports:
       – “5044:5044” – “5007:5000/tcp”
       – “5007:5000/udp”
       – “9600:9600”
     environment:
        LS_JAVA_OPTS: -Xms256m -Xmx256m
        LOGSTASH_INTERNAL_PASSWORD: $ {LOGSTASH_INTERNAL_PASSWORD:-}
     networks:
       – elk
     depends_on:
       – elasticsearch

For folk flest ser ikke dette umiddelbart ut som testbar kode; den gjør jo ingen ting! Men vi gir oss ikke så lett; all kode er testbar på ett eller annet vis. Det vanligste testforløpet for infrastrukturkode ser ut omtrent slik:

Først kjører vi noen statisk analyseverktøy og sjekker at dette faktisk er gyldig kode. Gjerne utvidet med en avsjekk av at skyplattformen vi ønsker å kjøre på faktisk støtter de parameterne og grensesnittene vi har definert (uten/m API validering). Så kan vi teste mot et mock API for å sjekke at innholdet i strengene vi sender inn også er gyldige.

Step 2 er å sjekke hvilke avhengigheter vi har og om de har noen fallgruver vi ikke har tenkt på. Hva om port 5044 i eksemplet over allerede er i bruk av en annen tjeneste vi har konfigurert? Vil vi oppdage det under test eller venter vi til en produksjonslogg fylles opp med “400: Bad Request” ?

Til slutt kjører vi noen enkle tester direkte mot plattformen i forhåndsvisningmodus, sjekker at ting faktisk dukker opp som planlagt og gjør til slutt en rask utforskende test av om resultatet faktisk er brukbart.

Mange av oss er vant til at tester er fordelt i en pyramideform; vi har mange enhetstester som understøtter noen færre integrasjonstester som kjøres før vi foretar noen få utforskende sesjoner for å finne de ‘dype’ feilene. Siden infrastrukturkode ikke har noen ‘enheter’ som sådan, og det aller meste av kompleksitet handler om avhengigheter på både kryss og tvers får testvolumet vårt en ganske annen fasong, kanskje som:

En annen ting er at tilsynelatende enkle tester kan ta fryktelig lang tid; en test som tester

   depends_on:
          – elasticsearch

vil faktisk installere og starte opp en komplett instans av elasticsearch. Det kan ta tid.

Derfor er det ikke uvanlig å ‘teste progressivt’ vet at man prioriterer testene etter hvor lang tid man forventer at testen kommer til å ta, ikke som normalt prioritert etter risiko.

Det betyr at man kjører de sjekkene som tar minst tid først og som sjekker at grunnleggende infrastruktur er på plass. Når disse har passert vet man at man har et grunnlag for å teste ‘dypere’ med mer kompliserte og tidkrevende tester.

En annen måte å teste progressivt på, eksempelvis dersom man ikke har erfaringstall som tilsier hvilket tidsforbruk man kan forvente er i økende grad av kompleksitet:

Først tester man internt i en container. Så tester man noen få avhengigheter på en nedskalert og/eller lokal plattform (Docker compose, minikube, podman e.l) før man tester på et ‘fullskala’ miljø med alle relevante avhengigheter. Normalt bør man tenke seg godt og lenge om før man gjentar en test — fordi en gjentatt test bare demonstrerer at det ikke har skjedd endringer siden sist — slik at det normalt er bedre med en ny og variert test enn repetisjon av en gammel. Ved denne formen for progressiv test av deklarativ kode er det dog ofte nyttig å repetere utvalgte tester fordi man vet at alt utenom testobjektet har endret seg siden forrige kjøring.

Som du kanskje kan gjette deg til har vi normalt høyere automatiseringsgrad på infrastrukturtester enn annen type testing. Mens vi snakker om automatisering; en vanlig måte å spesifisere en test på er Given-When-Then, som eksempelvis i verktøy som Cucumber:

given User{
     it { exists }
     it { has no subscription }
     }

Det blir fort litt snodig med deklarativ kode siden den ikke inneholder forretningslogikk. En typisk test vil da bare inneholde ‘Given’ biten:

when requests(discount) {}
then discount(value: “10%”)
given virtual_machine(name: “appserver-testcustomerAstaging”) {
   it { exists }
   it { is_running }
   it { passes_healthcheck }
   it { has_attached storage_volume(name: “app-storage-testcustomerA-staging”) }
}

For noen av oss som er vant til at testing er en aktivitet som faktisk utfører en handling er dette en ny og spennende måte å tenke på, dog forbausende nyttig.

Mange har hørt om Patterns og hvordan disse kan brukes til å gjenbruke effektive strategier i møte med kjente problemer. Men visste du at vi også kan snakke om Anti-patterns? Innenfor testområdet kan vi kalle det antiteststrategier, fordi det dreier seg om handlingsmønstre som vi følger selv om de er ineffektive og hemmende. Altså det motsatte av en god teststrategi.

Men hvorfor skulle noen velge en antiteststrategi, hvis de er ineffektive og lite egnet? Svaret er at dette ofte dreier seg om ubevisste handlingsmønstre. Kanskje følger vi dem fordi det er slik vi har lært at det skal være, eller det alltid har vært gjort slik der vi arbeider. Kanskje var antiteststrategien en gang hensiktsmessig, men endrede forutsetninger har gjort at den nå er ineffektiv.

Så hva er typiske antiteststrategier? Her er noen eksempler:

Lag gjerne en risikovurdering, men la i praksis inngrodde vaner og gamle leveranser være styrende i testgjennomføringen
Si at du har forankret en risikoanalyse, kanskje gjort grundige undersøkelser om testobjekter og skrevet testplan. Men når testen starter, leter testerne i stedet etter de tingene som gikk feil forrige gang dere produksjonssatte. Det hjelper ikke hvor mye dere er blitt enige om hvor feilene mest sannsynlig er eller hvor endringene kommer denne gangen, det er det som gikk feil forrige gang som teller. Noen ganger er det gode grunner til å teste det som feilet forrige gang. Men like ofte kan det skyldes gamle vaner. Vi gjør det fordi vi alltid har gjort det. Problemet med dette er at i verste fall tar vi dermed tid og krefter fra tiden vi kunne brukt på det som er den reelle risikoen i prosjektet og produktet.

Lag gjerne en risikovurdering, men la i praksis inngrodde vaner og gamle leveranser være styrende i testgjennomføringen
Si at du har forankret en risikoanalyse, kanskje gjort grundige undersøkelser om testobjekter og skrevet testplan. Men når testen starter, leter testerne i stedet etter de tingene som gikk feil forrige gang dere produksjonssatte. Det hjelper ikke hvor mye dere er blitt enige om hvor feilene mest sannsynlig er eller hvor endringene kommer denne gangen, det er det som gikk feil forrige gang som teller. Noen ganger er det gode grunner til å teste det som feilet forrige gang. Men like ofte kan det skyldes gamle vaner. Vi gjør det fordi vi alltid har gjort det. Problemet med dette er at i verste fall tar vi dermed tid og krefter fra tiden vi kunne brukt på det som er den reelle risikoen i prosjektet og produktet.

Det er alltids tid til ytelsestest og sikkerhetstest – bare gjør ferdig de funksjonelle testene først
Noen ganger kan vi ubevisst lage et A-lag og et B-lag av ulike testtyper. Alle ser verdiene av de funksjonelle testene, og det er ofte dem vi blir målt på. Men ikke-funksjonelle tester blir også viktigere og viktigere, og vi må behandle dem som likeverdige med de funksjonelle testene – f.eks. ting som sikkerhet, ytelse, tilgjengelighet. Her kan man for eksempel vurdere å legge ytelsene høyere i risikovurderingen når vi gjør risikoanalyser. Avhengig av hvor man er og kultur man er i – det kan være en kamp for å løfte fokus på enkelte testtyper.

Fra antiteststrategier til positive teststrategier

Gode teststrategier kjennetegnes gjerne av følgende:

  • Gir ønskede resultater
  • Er tilpasset og relevante
  • Gir mulighet for videreutvikling og nyskapning

Hvordan sikrer vi oss at arbeidet vårt er preget av slike strategier, og ikke ineffektive og uhensiktsmessige antiteststrategier?

En måte å se det på er at måten vi tenker, handler og føler på henger sammen. Endrer du på én av dem, vil det også skape bevegelse på de andre områdene:

Følelsene våre: Hvis vi tør å følge risikovurderingen våre og lykkes, vil det skape tillit og mestringsfølelse. Våg å stole på de vurderingene vi gjør av risiko nå, ikke bare dem vi gjorde forrige gang vi testet! Dette gjelder også hvis vi klarer å skape engasjement i testarbeidet. Hva med å ha mer fritesting eller arrangere bughunts med premier slik at testerne kan bruke sin faglige kunnskap og kjennskap til løsningen aktivt, og la kreativiteten slippe løs. Kanskje kan vi til og med sette av tid til slike aktiviteter i teststrategi og testplaner?

Tankene våre: Hvordan vi tenker om oss selv og omgivelsene våre gir ofte en selvforsterkende effekt. Klarer vi å sette testene våre inn en større sammenheng. Et eksempel er illustrert her:

Adferden vår: Ledelsesteori og -praksis har lært oss mye om hva som skaper mer positiv og hensiktsmessig atferd i prosjekter og organisasjoner. Å være konsekvent, drive aktiv ledelse og tydeliggjøre roller og ansvar skaper trygghet og forutsigbarhet, slik at vi kan bruke energien på en hensiktsmessige måte. Gode rutiner, for eksempel gode feilhåndteringsplaner og god møtepraksis er eksempler på dette.

Mest av alt handler det kanskje om at vi faktisk våger å følge det vi har skrevet i teststrategier og testplaner, og har disse som levende dokumenter slik at de faktisk reflekterer det vi gjør. Ofte vet vi av erfaring nemlig ganske mye om hva som er gode strategier, og hva som er antiteststrategier.

Er du klar til å kvitte deg med ineffektive og uhensiktsmessige antiteststrategier? Det er fullt mulig – lykke til!