Continuous Delivery i en ikke perfekt verden

I mit forrige indlæg skrev jeg om de ting jeg synes er vigtigst for at få testen til at være effektiv når man kører continuous delivery. Nogle af de råd forudsætter dog, at man ikke har alt for mange afhængigheder, teknisk gæld og lign. Det er jo desværre ikke altid tilfældet. Så hvad gør man, når man ikke har et nyt projekt fyldt med microservices, featuretoggles og containere, men derimod arbejder i en reguleret industri med regler om hvem der kan få adgang til produktion, hvordan der skal dokumenteres, sikkerhedskrav osv.? Jeg har fire bud på det:

Bud 1: Erstat det der ikke kan lade sig gøre

Nogle gange er man i den situation, at et element i agile eller continuous delivery ikke kan lade sig gøre. Det kan være pga. love, konventioner, tidligere tiders synder, eller noget helt fjerde. Min erfaring er dog, at hvis man finder ud af, hvorfor det element er der, så kan man normalt godt finde på noget, der opfylder det samme formål. Det bliver ofte dyrere, eller kræver lidt mere bureaukrati, men kan trods alt lade sig gøre. Et eksempel kunne være adgang til produktion. Hvis det kun er udvalgte personer fra driften, der kan få adgang til produktion og man ikke kan få en af dem på teamet, så må man finde på noget andet. Ved at booke en person fra driften til at deltage i stand-up hver dag, kan man opnå næsten det samme, som hvis teamet selv havde adgang. Hvis det ikke kan være hver dag, så hver anden dag - osv. Det er sup-optimale løsninger, men man opnår trods alt nogenlunde det samme, som hvis teamet havde adgang, men det koster lidt mere både i tid og penge.

På længere sigt er det også en god ide at arbejde på, at få fjernet begrænsningen. Hvis det er lovkrav kan det være svært, men det er ret få gange jeg har oplevet at det er juraen der sætter begrænsningerne. Langt de fleste gange er det et spørgsmål om kapacitet, økonomi eller “sådan plejer vi ikke at gøre”.

Bud 2: Få styr på ansvarsfordelingen af test - hvem tester hvad

En af de problemer jeg oftest ser i agile setups er, at teams ikke er uafhængige, og derfor bliver nødt til at release sammen. Når man laver store komplekse systemer, kan det være svært at undgå, men det gør desværre også at man ikke kan holde testen inden i teamet.  Det er derfor vigtigt at få afklaret, hvem der tester på tværs. Teams tester selvfølgelig deres egen software, men hvem tester integrationerne?

En strategi kunne være, at det team der er afhængig af en anden integration står for testen. Det kræver dog at de vender tilbage til testen, når komponenten i den anden ende ændrer sig. Det kan endda også være, at komponenten slet ikke klar, når det afhængige team koder deres integration (mod en stub). Endelig er der også end-to-end-testen, der går på tværs af hele løsningen. Hvem skal teste den?

SAFe har nogle løsningsforslag, der dog ikke er særlig specifikke. Det ene er shared services, og det andet er systemteams. Shared services er specialister og services, som ikke er tilknyttet et bestemt team, og typisk skal bookes på forhånd. Systemteams er specielle teams der oprettes for at opfylde en bestemt funktion. F.eks. tværgående test. Personligt hælder jeg mod systemteams, men det vigtige er sådan set bare at man får det aftalt. Både hvem der designer testcases, finder testdata og udfører testen.

Bud 3: Overblik over afhængigheder

For at vide hvad der skal testes på tværs, er det nødvendigt at have overblik over, hvilke afhængigheder, der er mellem løsningens komponenter. Det lyder måske åbenlyst, men når et system har eksisteret i 30 år, kan man nemt have mistet overblikket, og nogle gange opstår integrationer simpelthen uden at nogen opdager det. F.eks. kan et system skrive et CPR-nummer med bindestreger i databasen, hvorefter det bliver replikeret over i et datawarehouse, hvor et andet system læser det. Hvis man nu fjerner bindestregerne, vil det andet system måske fejle, hvis man har kodet det lidt sjusket.

Det er en afhængighed, der er svær at opdage, og jeg har ikke nogen fremragende løsning på problemet udover tæt samarbejde og et par gode råd:

  • Hvis det er muligt, så undgå at bruge databasen som integrationspunkt. Brug i stedet webservices, hvor man i højere grad specificerer strukturen af data, og kan validere at den overholdes.

  • Hvis man bruger databasen som integrationspunkt, så få styr på hvilke systemer der har login til dem. Giv dem hver deres, hvis de tidligere har benyttet et fælles. På den måde ved man, hvem der skal potentielt skal koordineres med. Det kan dog desværre ofte blive en lang liste.

Bud 4: Få styr på testdata

Testdata er næsten altid besværligt, men når man skal teste på tværs af mange teams der løbende laver ændringer, bliver det ekstra slemt. Mange forsøger at løse problemet, ved at bruge en kopi af produktionsdatabasen, men pga. af datamængderne kan det ofte være et problem og efter GDPR er kommet, kan man næsten ikke slippe afsted med det. (Pseudo)anonymisering af produktionsdata er en mulighed, men det er typisk ret dyrt og komplekst og det er også svært at holde opdateret.

Min foretrukne metode er sæt statiske grunddata, der er tilpas varieret til at dække alle testscenarier og så genereret data for resten. Det betyder, at hvert team løbende skal vedligeholde et sæt testdata, der repræsenterer deres komponent og basere dem på et fast sæt nøgler som alle bruger (f.eks. cpr/cvr-numre). På den måde har man f.eks. 100 kunder som alle kan teste på, og hvis man vil teste noget specielt (f.eks. load)  så må testen generere data først. Det kræver noget koordination mellem teams, specielt i starten, for at få og bevare den nødvendige variation, men metoden gør det nemt at teste og man skal ikke jonglere rundt med meget store databaser i testmiljøerne.

Det var så de fire bud jeg har på, hvordan man kan mitigere nogle af de problemer man løber ind i, hvis ens kontekst ikke er helt perfekt. Det er ikke tænkt som at være udtømmende, men jeg håber det kan inspirere.