Visual Studio 2015 Update 1: Forbedret ytelse, Parallel unit testing, og kontekst sensitiv test eksekvering

Visual Studio 2015 Update 1 inneholder en rekke forbedringer og bug-fixes.  Her er en bra oversikt.   

I denne posten skal vi i hovedsak se på parallel test eksekvering, men først litt generelt om ytelseforbedringen i Update 1.

Ytelse

Man kan aldri få nok ytelse, og man vil alltid at nye versjoner skal ha bedre ytelse enn den forrige.  Noen ganger går derimot nye features på tvers av dette ønsket, og det skjedde med Visual Studio 2015 RTM.  Ytelsen var ikke så god som ønsket, og spesielt ikke om man anvendte de nye Roslyn analysatorene.  Dessuten om man hadde mange varsler i feilvinduet, så ble Visual Studio veldig treg, og kunne også henge seg.  Spesielt ble dette synlig for de som også anvendte Resharper 10.

Dette problemet er det arbeidet veldig hardt med, og det er nå løst i Update 1 – ytelsen er vesentlig forbedret for disse scenarioene.  Dessuten har Jetbrain gjengen gjort sitt på sin side og i versjon 10.0.2 er ytelses problemene i Resharper også løst. 

Nuget

Sammen med Visual Studio 2015 kom Nuget 3, og den fikk også en litt trøblete start.  Dette er det også blitt jobbet mye med, og du bør sørge for at du har siste versjon av denne.  I Visual Studio 2015 blir mange av utvidelsene automatisk oppdatert, men det gjelder ikke for Nuget.  Ta en kikk på notifiseringsikonet oppe til høyre,  den sier fra om du har noe du bør installere. 

Når dette skrives er siste versjon av Nuget 3.3.0.167. 

Parallel test eksekvering

Visual Studio 2015 Update 1 har fått parallel eksekvering av tester i Test Explorer.  Dette kan gi deg en kraftig forbedret ytelse for test eksekveringen din.  I utgangspunktet er dette av, så du må aktivt slå det på per solution.

Systemet kjører selv test assembliene i parallel, på inntil så mange kjerner som du spesifiserer og maksimalt så mange som din maskin har.   Dersom du kun har ett test prosjekt og dermed kun ett test assembly så får du ingen effekt av dette, men dersom du har flere så får du – med opsjonen påslått – automatisk effekt av dette.

Dette er uavhengig av hva slags testframework du anvender og fungerer  derfor for både  MSTest, NUnit 2, NUnit 3 og XUnit.  

Denne paralleliseringsmekanismen fungerer altså uavhengig av om det underliggende frameworket selv har parallelkjøring. 

For å slå dette på må du anvende en runsettings fil, som du slår på i Visual Studio.  Den letteste måten å få inn riktig konfigurasjon på er å anvende disse runsettings item templatene, merk at du skal ha versjon 3.1 av disse.  Når du har installert denne har du 3 runsettings templater, og det beste er å anvende den som heter Parallel. 

Du gjør som følger:

 Velg Solution, Right click og velg Add/New item

Du får nå opp en liste, som skal se omtrent slik ut:

Velg Parallel og du får denne inn i løsningen din.

Og vips så har du skrudd på parallel testing !

PS:  Du må huske å aktivere templaten I Visual Studio Test menyen også selvfølgelig, det gjør du slik:

(1)  Velg Select Test Settings file fra topp menyen  Test/Test settings. 

(2)  Velg deretter ønsket Runsettings file, I dette tilfelle Parallel2.runsettings. 

(3) Sjekk menyen igjen, og da ser du at den er angitt over Select Test Settings file.

 

 Hva betyr parametrene:

Om vi ser på innholdet av runsettings filen, ser vi følgende:

Det er da MaxCpuCount som styrer hvor mange parallelle prosesser som kan kjøres.   Gis den verdien 0, så betyr det at den kjører så mye den kan, begrenset av antall kjerner du har tilsammen på din maskin.  Gis den verdien 1, blir det det samme som å kjøre sekvensielt, kun en prosess aktiveres.

Hvorfor er ikke Code Coverage med ?

Du la muligens merke til at beskrivelsen I Add Item for Parallel sa at denne kjører uten code coverage.  Det dette betyr er at når du aktiverer denne runsettingen så aktiverer du IKKE samtidig code coverage.  Det gjør nemlig de to andre templatene. 

Aktiverer du Code COverage vil ytelsen gå noe ned fordi Code COverage også skal kjøres og den kjører sekvensielt etter at testen er kjørt, og øker derfor tiden for hele testen.  Samtidig gir den deg lite du kan anvende.

Det at du ikke aktiverer Code Coverage i templaten betyr nemlig ikke at du ikke kan kjøre Code Coverage fra Team Explorer menyen – akkurat det fungerer like herlig.  Om du derimot aktiverer en av de to andre templatene, så blir også code coverage automatisk aktivert i bakgrunnen.  Du får ikke noe mer informasjon opp I Visual Studio, men det lages en code coverage fil som legges under Test Results folderen din.

Denne filen hjelper deg egentlig ikke noe, men er anvendelig dersom du skal importere disse resultatene inn et annet verktøy, f.eks. NDepend.

 Samtidig så tar jo oppsettet under Code coverage delen I runsettings filen effekt, og vil filterere resultatene dine.  Disse filtrene vil også fungere når du kjører code coverage fra Test Explorer.

Du finner mer informasjon om Code Coverage configurering I denne MSDN artikkelen.  Istedetfor å kopiere over xml’en herfra, er det bedre å anvende templaten CompleteRunsettings som inneholder dette, pluss de andre settingene som hører til.  XML’en I denne artikkelen er ikke komplett.

Templaten CompleteRunsettings setter MaxCpuCount til 0, altså vil den kjøre så parallelt den bare kan.

Templaten CoverageNoParallel er nesten helt identisk, den har nøyaktig de samme feltene, men MaxCpuCount er satt til 1.

Det finnes også en MSDN artikkel om konfigurering av unit tester som er mer korrekt, men den inneholder ikke den samme detaljerte informasjonen som artikkelen ovenfor.  I denne er derimot alle feltene forklart.

Test prosjekt for å teste parallel kjøring

Jeg har lagd et testprosjekt for å teste parallel kjøring.  Det har 4 testprosjekter, som hver har en test hver, og testene tar 5 sekunder hver å kjøre.  Du kan selv laste det ned og prøve.

(1)  Her kjører vi helt uten settings I det hele tatt.  Da kjøres det ikke parallelt, og vi ser at totaltiden er 26 sekunder, altså har vi et overhead på 6 sekunder i tillegg til 4 ganger 5 sekunder for testene.

(2) Her bruker vi enten CodeCoverageNoParallel eller den “gamle” runsettings filen, da får vi code coverage settingene men ingen parallel setting.  Tiden øker da til 31 sekunder.

(3) Så anvender vi den komplette settingen, den som har både CodeCoverage og Parallel.  Da synker kjøretiden til 18 sekunder.

(4) Og endelig kun Parallel uten code coverage, og vi får 12 sekunder. 

Maskinen jeg kjører på har flere kjerner, men jeg har også kjørt nå med ganske mange programmer oppe, så det er nok flere kjerner som er “opptatte”.  Dette blir litt som mobil-annonsene – “opplevd hastighet vil variere med forholdene”.  Men, bruken av parallel vil uansett forbedre ytelsen, og bør kunne gi deg mer en enn halvering av test tiden lokalt.

Parallel på build server

Fungerer dette på en build server ?  Ja, i en build definisjon kan du også angi runsettings, så dette vil også ha effekt på en build server.   Men bør du gjøre det ?   Det avhenger helt av hvordan du har satt opp buildserverene dine og hvor belastet de er.  Normalt setter man opp  en build agent per kjerne.  Dersom du har mange build definisjoner og det sjekkes inn kode ganske jevnlig, slik at buildserveren(e) dine er opptatt det meste av tiden, så er det neppe lurt å skru på parallel testing på build.  Da vil en enkelt build bli raskere ferdig, mens en annen rett og slett må vente, fordi kjernen er opptatt.  Her kan det også bli et overhead slik at gevinsten helt forsvinner. 

Dersom du derimot har en build maskin som er lite belastet med få builds gående, så ja – hvorfor ikke?  Da kan du fint hente ut litt ekstra ved å kjøre testene parallelt.

Det finnes forøvrig flere måter å kjøre tester parallelt på I en build, se denne artikkelen for en annen tilnærming.

Kontekst sensitiv test eksekvering

Kontekst sensitiv test eksekvering er nytt I Update 1 – hva er det ?   Jo,  under gitte forutsetninger  vil Test Explorer kun teste de assembliene som du har gjort endringer i.   

Dette betyr at om du arbeider med endringer I en gitt modul av koden din, og koden din er fordelt over mange assemblies, så vil du for hver bygging av koden kun bygge det som er endret.  Det er gammelt nytt, for compileren – men nytt for Test Exploreren er at den henger seg på dette og kun kjører de testene som tester denne koden.  Det kan gi en vesentlig forbedringer I testtid. 

Forutsetningen for at dette skal fungere er kun at du aktiverer “Run tests after build”. 

Det gjør du enten I Test Explorer (1) eller fra top menyen Test/Test Settings/Run Tests after Build (2).

 

Effekten av dette kan ses på bildet under:

(1) Aktiver “Run tests after build”

(2) Gjør dine kode endringer

(3) Kun velg Build , evt bruk keyboard shortcut 

(4) Kun angjeldene test blir kjørt, de andre vises dimmet grønt.  De kjørte altså forrige gang grønt, men  er ikke kjørt denne gangen, fordi ingen kode er endret for dem.

Dersom du har større prosjekter kan dette gi en vesentlig gevinst I ytelsen.  Det viktige er jo å raskest mulig komme tilbake til kodingen etter å ha starten en ny bygg.