mandag 12. april 2010 Testing Samtidighet C#
Lenge siden jeg har hatt noe C#-kode på bloggen nå.., la meg gjøre noe med det. På jobben i forrige uke lagde vi to små extension methods jeg har lyst til å dele med verden. Det er ikke noe rocket science, men kan være greit om du har samme behovet som oss, og du ikke har tenkt på det selv.
Systemene vi jobber med inneholder MYE asynkronitet / samtidighet. Når vi skal lage automatiserte tester – spesielt integrasjonstester – må vi forholde oss til at vi ikke øyeblikkelig får det resultatet vi forventer (eventual consistency). En test kan f.eks. sende en melding som plukkes opp og behandles av en annen tråd. Dette fører til endel kompleksitet i testene; ofte legger vi inn en sleep før vi kontrollerer resultatet.
Her er en tenkt test hvor vi har en publisher og en subscriber. Vi publiserer en melding, og kontrollerer at subscriberen har mottatt:
Ett av problemene med dette er at faktorer utenfor vår kontroll kan føre til at tiden vi må vente av og til øker ganske mye. Vi bruker da endel tid på å finne den optimale ventetiden, for vi vil ikke at testene skal bruke for lang tid. Men fra tid til annen feiler likevel en og annen test pga. stor belastning på bygg-serveren. Dette er ikke bra – vi må kunne stole på stabiliteten på builden!
For å bedre dette har vi kommet opp med en abstraksjon vi kan bruke i stedet for en hardkodet sleep. Disse extensionmetodene sjekker om et predikat er tilfredstilt helt til det er det, eller til vi har nådd en timeout-verdi:
Med disse på plass kan vi skive om testen slik:
Testen er nå mye mere lesbar (i min mening). I tillegg kjører testene gjevnt over raskere, men uten å feile de gangene maskinen trenger litt mere tid på å gjøre seg ferdig.
PS: When og Then-nøkkelordene i testene stammer fra min Ultra-tiny given-when-then DSL-snippet. ShouldEqual-metoden i den første versjonen av testen kommer fra coreTDD, som vi bruker i alle tester i stedet for vanlige nUnit asserts.