17
.NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę. Jeśli jesteś zainteresowany wydaniem tego tytułu to proszę o kontakt z autor em: Marcin Kawalerowicz [email protected] http://www.kawalerowicz.net/ Ten dokument został wydany na licencji Creative Commons Attribution-Non-Commercial-No Derivative Works 2.5 Poland Licence. http://creativecommons.org/licenses/by-nc-nd/2.5/pl/

NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

  • Upload
    vukhanh

  • View
    230

  • Download
    0

Embed Size (px)

Citation preview

Page 1: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

.NET Continuous Integration za pół darmo

Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę. Jeśli jesteś

zainteresowany wydaniem tego tytułu to proszę o kontakt z autorem:

Marcin Kawalerowicz

[email protected]

http://www.kawalerowicz.net/

Ten dokument został wydany na licencji Creative Commons Attribution-Non-Commercial-No Derivative Works

2.5 Poland Licence.

http://creativecommons.org/licenses/by-nc-nd/2.5/pl/

Page 2: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

Spis treści

1. Dlaczego continuous integration?

a. Automatyzacja = oszczędnośd

b. Nie najnowszy wynalazek

c. Bądź zawsze gotowy

2. Automatyzacja

a. Kompilacja w jednym kroku

b. NAnt kontra MSBuild

c. Automatyzacja procesu budowy za pomocą MSBuild

3. System kontroli wersji

a. Sine qua non

b. VSS kontra SVN

c. Subversion w akcji

d. Dobre rady w sprawie porządku w projekcie

4. Serwer ciągłej integracji

a. Bez niego ani rusz

b. TFS kontra CC.NET

c. CruiseControl.NET w akcji

5. Testy jednostkowe

a. Testy najbliższe materii

b. VSTS kontra NUnit

c. NUnit w akcji

d. Badanie pokrycia testami za pomocą NCover

6. Kontrola procesu ciągłej integracji

a. Wiedzied, co w trawie piszczy

b. CCTray kontra Dashboard

c. Obaj w akcji

d. Integracja raportów (NUnit, NCover) z Dashboardem

7. Testy akceptacyjne, integracyjne i systemowe

a. Z tysiąca stóp

b. Web: Selenium

c. Windows: NUnitForms

d. Testy Fitnesse

8. Analiza kodu

a. Konwencje są ważne

b. Statyczna analiza kodu w FxCop i StyleCop

9. Wersjonowanie

a. Gdzie ja jestem?

b. Rozszerzanie MSBuild

10. Dokumentacja

a. Nie lubiane dziecko projektu

b. Generowanie dokumentacji w Sandcastle

11. Dostawa

a. Zawsze gotowy

b. Publikacja za pomocą ClickOnce

Page 3: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

c. Tworzenie instalatora w Visual Studio i WiX

Page 4: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

2. Automatyzacja W tym rozdziale zastanowimy się, dlaczego proces ciągłej integracji niemożliwy jest bez jednego centralnego

"punktu" służącego do budowy całej aplikacji. Dowiemy się, dlaczego wspomniany "punkt" powinien mieć

formę tekstową i przybrać postać skryptu. Zastanowimy się, jakie narzędzie do automatyzacji procesu budowy

wybrać dla naszego projektu. Wyjaśnimy, dlaczego dobrym wyborem jest MSBuild i stworzymy za jego pomocą

nasz pierwszy skrypt automatycznej integracji.

Każdy dobrze zaprojektowany proces ciągłej integracji powinien posiadać jeden centralny „przycisk”

pozwalający w „jednym kroku” przeprowadzić pełny proces „budowy” oprogramowania. Całkiem dużo

cudzysłowów jak na tekst z gatunku inżynierskiego. Na pierwszy rzut oka wystarczy Visual Studio. "Przycisk"

F6 trzeba "jednorazowo" nacisnąć i proces "budowy" startuje. Czy to wystarczy? Niestety nie. Kluczem do

odpowiedzi jest pojęcie automatyzacji, czyli wyeliminowania czynnika ludzkiego.

Pamiętajmy, do czego dążymy. Naszym celem jest takie przygotowanie procesu ciągłej integracji by mógł on

funkcjonować zupełnie samodzielnie na dedykowanym do tego zadania urządzeniu. Do realizacji tak

postawionego celu idealnie nadają się tak zwane platformy automatyzacyjne.

2.1. Wszystkie dzieci make Platforma automatyzujące budowę oprogramowania biją wiekiem większość dzisiejszych programistów.

Protoplastą większości narzędzi tego typu był unixowy make. Powstały pod koniec lat siedemdziesiątych, ma

się bardzo dobrze do dzisiaj. Jest powszechnie używany w na systemach linuxopodobnych. Doczekał się on

również swej wersji windowsowej zwanej nmake oraz całkiem udanego klona w postaci OPus Make.

Wszystkie one używają plików tekstowych zwanych makefile do definiowania zadań potrzebnych do budowy

oprogramowania. Zmianę w tym podejściu przyniosły takie produkty jak Jam czy Cook. Ich autorzy chcieli

ukryć przed użytkownikiem te bardziej niskopoziomowe aspekty budowy plików makefile, zastępując je innymi

konstrukcjami. Platformy automatycznej budowy oprogramowania przekształcały się powoli w coraz

potężniejsze narzędzia, które powoli nazywane były systemami. Jednym z ich przedstawicieli jest GNU

Automake ze swym GNU Build System. GBS to raczej zbiór programów popularny podczas tworzenia

pakietów oprogramowania dla systemów z rodziny unixa. By domknąć tą szybką wycieczkę w świat potomków

make trzeba wspomnieć o produktach używających określonych języków programowania do opisu procesu

budowy oprogramowania. I tak na przykład w SCons posługujemy się Pythonem a w rake używamy Ruby.

Wszystkie te narzędzia nadają się do urządzenia procesu ciągłej integracji. My przyjrzymy się jednak

awangardzie wśród narzędzi automatyzujących proces budowy oprogramowania. Są to oparte na XMLu Ant

(Nant) i MSBuild.

W przeciwieństwie do wcześniejszych narzędzi tego typu, które do opisu procesu budowy oprogramowania

używały dość skomplikowanego systemu komend lub nawet języków programowania te nowe oparte są na

XMLu. Ciąg komend z pliku makefile lub program w Ruby czy Pythonie zastąpiony został opisem w postaci

skryptu, w którym deklarujemy poszczególne kroki w procesie budowy. Co ważne, zadania deklarowane w

skrypcie można łatwo rozszerzać i adoptować.

2.2. To nie jest mrówka Najpierw był Ant (z ang. mrówka). To dobrze znane ze świata Javy narzędzie zostało przystosowane do pracy w

.NET i nazwane NAnt (z ang. nie mrówka). Po poprzedniku pozostała koncepcja deklaratywnego opisu procesu

w postaci skryptu XML.

Przyjrzyjmy się NAntowi przez pryzmat bardzo prostego przykładu. Załóżmy, że nasze oprogramowanie

zamyka się w tym oto pełnoprawnym programie.NET Framework

Page 5: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

public class HelloNAnt

{

public static void Main()

{

System.Console.WriteLine("Hello NAnt!");

}

}

Ten, jakże błyskotliwy program umieszczamy w dowolnym katalogu pod nazwą HelloNAnt.cs. W tym samym

katalogu umieszczamy plik o nazwie HelloNAnt.build i wypełniamy w następujący sposób:

<?xml version="1.0"?>

<project name="Hello NAnt" default="build" basedir=".">

<property name="debug" value="true" overwrite="false" />

<target name="clean">

<delete file="HelloNAnt.exe" failonerror="false" />

<delete file="HelloNAnt.pdb" failonerror="false" />

</target>

<target name="build" depends="clean">

<csc target="exe" output="HelloNAnt.exe" debug="${debug}">

<sources>

<include name="HelloNAnt.cs" />

</sources>

</csc>

</target>

</project>

Pakiet NAnta pobieramy ze strony producenta1 i rozpakowujemy do podkatalogu lib/NAnt (o zaleceniach w

sprawie składowania projektów, plików i narzędzi powiem jeszcze w następnym rozdziale przy okazji

omawiania systemów kontroli wersji).

Uruchamiamy wiersz poleceń systemu operacyjnego. Przechodzimy do katalogu, w którym umieściliśmy nasz

program oraz skrypt NAnt i wykonujemy następującą komendę:

lib\nant\bin\nant

1 http://nant.sourceforge.net/

Page 6: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

Rysunek 2.1. Wynik działania skryptu NAnt

Magii stało się zadość. Możemy wykonać HelloNAnt.exe i podziwiać program powstały w pełni

zautomatyzowanym procesie budowy.

NAnt ma jednak jedną podstawową wadę. Praca nad nim została porzucona. Ostatnia dostępna wersja powstała

w 2007 roku i od tego czasu projekt pozostaje w stagnacji. Tak więc każdy ewentualny błąd jaki napotkamy

podczas pracy z NAnt będziemy musieli naprawić samemu. Technicznie rzecz biorąc nie stanowi to dużego

problemu, bo NAnt dystrybuowany na zasadach otwartego kodu. NAnt pozostanie z pewnością dobrą

alternatywą dla osób znających jego javowego poprzednika i dla zapiekłych przeciwników Microsoftu. Bo to ze

stajni tego producenta pochodzi zyskujący coraz większą popularność MSBuild.

2.3. Budowniczy z Microsoftu Microsoft po raz pierwszy wprowadził własne narzędzie do automatyzacji procesu budowy oprogramowania na

platformie .NET o nazwie MSBuild drugą odsłoną .NET Framework. Kolejnego wydania doczekaliśmy się wraz

z wersją 3.5 platformy. Tak więc, jeśli już masz zainstalowaną któraś z tych wersji .NET Framework to MSBuild

jest gotowy do działania i znajduje się w katalogu

C:\Windows\Microsoft.NET\Framework\v2.0.50727

lub

C:\Windows\Microsoft.NET\Framework\v3.5

Warto dodać ścieżkę MSBuilda do zmiennej systemowe PATH. Jeśli masz zainstalowane Visual Studio 2005 lub 2008 to możesz użyć Visual Studio 2008 Command Prompt, który znajdziesz w Start | Programy | Microsoft Visual Studio 2008 | Visual Studio Tools.

Page 7: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

Rysunek 2.2. Microsoft Visual Studio 2008 Command Prompt

Na rozgrzewkę wykonamy analogiczne zadanie jak w przypadku przykładu NAnta. Napiszemy prosty program i

zapiszemy go w pliku HelloMSBuild.cs

public class HelloMSBuild

{

public static void Main()

{

System.Console.WriteLine("Hello MSBuild!");

}

}

Skompilujemy go za pomocą skryptu MSBuild, którego nazwiemy build.msbuild. Skrypt uzupełnimy

czyszczeniem katalogu przed kolejną kompilacją.

<?xml version="1.0" encoding="utf-8"?>

<Project DefaultTargets="Build"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>

<Debug Condition="'$(Delete)'==''">true</Debug>

</PropertyGroup>

<ItemGroup>

<CompileFiles Include="HelloMSBuild.cs" />

<DeleteFiles Include="HelloMSBuild.exe;HelloMSBuild.pdb" />

</ItemGroup>

<Target Name="Clean">

<Delete Files="@(DeleteFiles)" />

</Target>

<Target Name="Build" DependsOnTargets="Clean">

<Csc Sources="@(CompileFiles)"

OutputAssembly="HelloMSBuild.exe"

EmitDebugInformation="$(Debug)" />

</Target>

Page 8: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

</Project>

Jeśli MSBuild znajduje się w systemowych ścieżkach dostępu to wywołanie naszego skryptu sprowadza się do

wpisania następującej komendy z poziomy znaku zachęty systemu operacyjnego:

msbuild build.msbuild

Rysunek 2.3. MSBuild w domyślnym trybie jest mniej rozmowny niż NAnt

2.4. Projekty, cele, zadania, ... MSBuild jest darmowy. Dystrybuowany automatycznie wraz z platformą .NET. Stoi za nim cała maszyneria

Microsoftu więc o zasięg oddziaływania i popularność nie ma się co martwić. Rzesza użytkowników ciągle się

powiększa, a producent ma dyżurujących na forach inżynierów, więc wsparcie jest zapewnione. MSBuild jest

rozszerzalny i dość dobrze udokumentowany. Wydaje on się być w tej chwili najlepszym wyborem dla

programistów .NET pragnących stworzyć swoją własną linie produkcyjną w technice ciągłej integracji.

Przyjrzyjmy się mu więc bardziej dokładnie i rozbijmy na części pierwsze skrypt z poprzedniego podrozdziału.

Skrypt MSBuild to najzwyklejszy dokument XML i jako taki musi posiadać definicję

<?xml version="1.0" encoding="utf-8"?>

Głównym elementem skryptu MSBuild jest znacznik projektu — Project. Zamyka on w logiczną całość proces

budowy. Deklarujemy w nim przestrzeń nazw dokumentu XML xmlns. W przypadku MSBuild w obecnej

wersji musi być to http://schemas.microsoft.com/developer/msbuild/2003. Częścią definicji

projektu mogą być domyślne cele. Można je podać w atrybucie DefaultTargets. W naszym przypadku będzie

to jeden cel o nazwie Build.

Cel (Target) zbiera w całość grupę zadań. Nasz domyślny cel posiada nazwę (Build) i jego przeprowadzenie

zależy od pomyślnego wykonania innego celu o nazwie Clean (atrybut DependsOnTargets). W ten sposób

można budować hierarchie wykonania celów w skrypcie MSBuild.

Build zawiera jedno zadanie, a mianowicie CSC. Zadanie to wywołuje kompilator języka C# z parametrami.

Jako pierwszy parametr Sources podajemy pozycję (item) zawierającą nazwy plików do skompilowania. W

drugim parametrze OutputAssembly określamy nazwę zestawu wynikowego. W ostatnim

EmitDebugInformation określamy czy interesują nas informacje dla programu uruchomieniowego. Wartość

logiczna przechowywana jest we właściwości Debug.

Każda pozycja (item) posiada nazwę i może zawierać referencje do zbioru plików. Definiujemy je w tak

zwanych grupach pozycji ItemGroup. W naszym przypadku zdefiniowaliśmy dwie pozycje. Pierwsza o nazwie

Page 9: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

CompileFiles zawiera listę plików do kompilacji (w naszym przypadku jeden HelloMSBuild.cs). Druga

pozycja DeleteFiles zawiera listę plików, jaką cel Clean korzystający z zadania Delete ma usunąć. Jako, że

cel ten wykonany zostanie przed celem Build wyczyści on katalog z ewentualnych zbędnych plików przed

każdą kompilacją.

Właściwości (property) to rodzaj zmiennych. Każda właściwość posiada nazwę i wartość. Właściwości

definiowane są w grupach (PropertyGroup). My zdefiniowaliśmy tylko jedną właściwość o nazwie Debug.

Zawiera ona wartość logiczną (true lub false), którą używamy w zadaniu csc do określenia czy kompilator

powinien stworzyć dodatkowo plik pdb przydatny do debugowania programu. Nasza właściwość posiada jeden

atrybut Condition. Dzięki zastosowaniu tego warunku będzie możliwe określanie wartości właściwości z

poziomu linii komend. Zasada działania warunków jest bardzo prosta. Wartość właściwości zostanie ustawiona

jedynie, jeśli wyrażenie podane w warunku będzie spełnione. Spróbujmy ustawić wartość właściwości z

poziomu linii komend. Wywołajmy MSBuild w następujący sposób:

msbuild build.msbuild /property:Debug=false

Po takim wywołaniu warunek '$(Delete)'=='' nie będzie spełniony bo MSBuild pobierze właściwość

Debug=false podaną z linii komend i wartość właściwości o tej nazwie nie zostanie nadpisana. Dzięki temu

otrzymamy kompilację bez dodatkowych informacji dla debugera.

Możliwość przekazywania wartości właściwości od zewnątrz będziemy wykorzystywać dość często w tworzeniu

procesu ciągłej integracji.

2.5. Predefiniowane zadania MSBuild dostarczany jest z całą gamą predefiniowanych zadań. Dwa już poznaliśmy. Były to kompilator c# csc

oraz zadanie usuwające pliki delete. Inne to na przykład:

1. kopiowanie plików — Copy,

2. tworzenie katalogów — MakeDir,

3. usuwanie katalogów — RemoveDir,

4. wypisywanie informacji na ekran — Message,

5. startowanie dowolnego programu — Exec.

Wykorzystajmy je do rozszerzenia naszego projektu. Stworzymy coś na kształt procesu ciągłej integracji w

pigułce. Za pomoc MSBuild wyczyścimy plac budowy, skompilujemy to, co trzeba, wynik skopiujemy w

określone miejsce i jako swoisty test wystartujmy nowo utworzony program.

<?xml version="1.0" encoding="utf-8"?>

<Project DefaultTargets="Build;Deploy;Execute"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>

<Debug Condition="'$(Delete)'==''">false</Debug>

<OutputFile>HelloMSBuild.exe</OutputFile>

<OutputDirectory>Output</OutputDirectory>

</PropertyGroup>

<ItemGroup>

<CompileFiles Include="HelloMSBuild.cs" />

<DeleteFiles Include="HelloMSBuild.exe;HelloMSBuild.pdb" />

</ItemGroup>

<Target Name="Clean">

<Delete Files="@(DeleteFiles)" />

<Delete Files="$(OutputDirectory)\**\*" />

Page 10: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

<RemoveDir Directories="$(OutputDirectory)" />

</Target>

<Target Name="Build" DependsOnTargets="Clean">

<Csc Sources="@(CompileFiles)"

OutputAssembly="$(OutputFile)"

EmitDebugInformation="$(Debug)" />

</Target>

<Target Name="Deploy">

<MakeDir Directories="Output" />

<Copy SourceFiles="$(OutputFile)" DestinationFolder="$(OutputDirectory)" />

</Target>

<Target Name="Execute">

<Message Text="Starting:

$(MSBuildProjectDirectory)\$(OutputDirectory)\$(OutputFile)"

Importance="low" />

<Exec WorkingDirectory="$(OutputDirectory)" Command="$(OutputFile)"></Exec>

</Target>

</Project>

Pierwsze, co rzuca się w oczy to rozszerzona lista DefaultTargets naszego projektu. Okrelilimz w niej aż trzy

zadania dzielone średnikiem. Zadania te zostaną wykonane w kolejności w jakiej pojawiają się w atrybucie

DefaultTargets. Najpierw wykonany zostanie cel Build (który nadal zależy od celu Clean). Po nim nastąpi

wykonanie celu Deploy. Cały proces zakończy się po wykonaniu celu Execute.

Cel Build pozostał bez zmian. Natomiast cel Deploy odpowiedzialny jest za stworzenie katalogu wynikowego

(zadanie MakeDir) oraz skopiowanie (zadanie Copy) pliku wykonywalnego określonego we właściwości

$(OutputFile) do nowo utworzonego katalogu.

Cel Execute, korzystając z zadania Message, wypisze na ekran informację. Będzie ona zawierała ciąg znaków

informujący jaki dokładnie program zostanie wykonany. Skorzystamy tutaj z jednej z wielu predefiniowanych

właściwości MSBuild. Nosi ona nazwę $(MSBuildProjectDirectory) i zawiera ścieżkę katalogu, w którym

znajduje się aktualny projekt MSBuild. Inne predefiniowane zmienne MSBuild podane są w dodatkach na końcu

książki. Zadanie Message ma jeszcze jeden parametr o nazwie Importance. Parametr ten służy do określenia

przy jakim poziomie ekspresyjności MSBuild dany komunikat ma być pokazany. Za chwilę dowiemy się co to

dokładnie oznacza i przyjrzymy się jak uruchomić MSBuild w różnych poziomach ekspresyjności. Po pokazaniu

informacji tekstowej wystartujemy świeżo skompilowany program. Wykorzystamy do tego zadanie Exec, które

wykonuje dowolny program określony w atrybucie Command korzystając z katalogu roboczego określonego w

WorkingDirectory.

W końcu rozszerzamy nasz cel Clean o zadania mające na celu posprzątanie nowych katalogów (RemoveDir) i

plików (Delete).

Wykonajmy nasz nowy skrypt. Dla zachowania czystości eksperymentu najpierw postarajmy się jednak

wyczyścić katalog z plików, które pozostały po naszych wcześniejszych zabawach. Można tego dokonać

poprzez uruchomienie MSBuild z określonym celem. Służy do tego parametr linii komend /target.

msbuild build.msbuild /target:Clean

Page 11: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

Rysunek 2.4. Czyszczenie katalogu docelowego

Front robót jest czysty. Wykonajmy teraz nasz nowy projekt:

msbuild build.msbuild

Rysunek 2.5. Budowa za pomocą MSBuild

Świetnie, ale co stało się z naszym zadaniem Message w celu Execute. Jego wynik został pominięty ze

względu na to, że uruchomiliśmy MSBuild w domyślnym poziomie ekspresywności. Poziom ten steruje

"gadatliwością" MSBuild. Im jest on wyższy tym więcej informacji zobaczymy na ekranie. By zobaczyć

komunikaty z wartością oznaczoną, jako niska trzeba poziom ten zwiększyć. Poziomem ekspresywności steruje

się poprzez parametr verbosity (domyślnie ustawiony on jest na normal). Można tego dokonać w następujący

sposób:

msbuild build.msbuild /verbosity:detailed

Page 12: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

Rysunek 2.6. MSBuild z kontrolą "gadatliwości"

Jak widać teraz nasz proces jest o wiele bardziej "gadatliwy". Wśród potoku informacji mamy i wynik naszego

zadania Message.

Inne parametry linii komend MSBuild i ich znaczenie wyjaśnione zostały w dodatkach na końcu książki.

2.6. Zadania wspólnotowe Korzystając z MSBuild nie jesteśmy ograniczeni do zestawu dostarczonych wraz z platformy zadań. Zestaw

dostępnych funkcjonalności można stosunkowo łatwo rozbudowywać. Można to robić samodzielnie pisząc

własne zadania tak jak to zrobimy w rozdziale 9. Wersjonowanie. Tymczasem przyjrzymy się bardzo

ciekawemu darmowemu pakietowi MSBuild Community Tasks2. Ten dystrybuowany na zasadach wolnego

oprogramowania pakiet zawiera bardzo wiele gotowych do użycia zadań.

Najprostszym sposobem przygotowania MSBuild Community Tasks do działania jest pobranie pakietu

instalacyjnego msi i zainstalowanie go w systemie. Nie jest to jednak odpowiedni sposób, jeśli w perspektywie

mamy tworzenie z jego pomocą skryptów napędzających serwer ciągłej integracji. Zainstalowanie pakietu

spowoduje to, że dodatkowe zadania będą natychmiast dostępne na danym komputerze. Niestety instalację tą

będziemy musieli wkrótce powtórzyć na serwerze ciągłej integracji. Podobnie, jeśli pracujemy w grupie i

planujemy używanie Community Tasks również na innych komputerach. Dodatkowo każda aktualizacja pakietu

pociągać za sobą będzie konieczność reinstalacji na wielu maszynach. Lepiej tego uniknąć pobierając archiwum

z kodem źródłowym. W katalogu Build zawiera ono biblioteki z zadaniami. Pliki najlepiej skopiować do

katalogu lib/MSBuildCommunityTasks.

Dokładniej o zaleceniach dotyczących przechowywania i używania komponentów procesu ciągłej integracji

powiemy w kolejnym rozdziale. Tymczasem nasz przygotowany katalog powinien wyglądać tak:

2 http://msbuildtasks.tigris.org/

Page 13: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

Rysunek 2.7. Struktura katalogu projektu

Spośród wielu dostępnych zadań skorzystajmy z trzech. Powiedzmy, że jako część celu Deploy chcemy nasz

program zarchiwizować, nadać archiwum jednoznaczną nazwę i przesłać pod określony adres poczty

elektronicznej.

<?xml version="1.0" encoding="utf-8"?>

<Project DefaultTargets="Build;Deploy;Execute"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<UsingTask AssemblyFile="lib\MSBuildCommunityTasks\MSBuild.Community.Tasks.dll"

TaskName="MSBuild.Community.Tasks.Zip" />

<UsingTask AssemblyFile="lib\MSBuildCommunityTasks\MSBuild.Community.Tasks.dll"

TaskName="MSBuild.Community.Tasks.Mail" />

<UsingTask AssemblyFile="lib\MSBuildCommunityTasks\MSBuild.Community.Tasks.dll"

TaskName="MSBuild.Community.Tasks.Time" />

<PropertyGroup>

<!--Zgodnie z poprzednim przykładem-->

</PropertyGroup>

<ItemGroup>

<!--Zgodnie z poprzednim przykładem-->

<DeleteFiles Include="*.zip" />

</ItemGroup>

<Target Name="Clean">

<!--Zgodnie z poprzednim przykładem-->

</Target>

<Target Name="Build" DependsOnTargets="Clean">

<!--Zgodnie z poprzednim przykładem-->

</Target>

<Target Name="Deploy">

<MakeDir Directories="Output" />

<Copy SourceFiles="$(OutputFile)" DestinationFolder="$(OutputDirectory)" />

<Time Format="yyyyMMddHHmmss">

<Output TaskParameter="FormattedTime" PropertyName="BuildDate" />

</Time>

<Zip Files="$(OutputFile)" ZipFileName="HelloMSBuild.$(BuildDate).zip" />

Page 14: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

<Mail

SmtpServer="adres"

To="email"

From="email"

Subject="New build!"

Body="This is an automated message."

Attachments="HelloMSBuild.$(BuildDate).zip"/>

</Target>

<Target Name="Execute">

<!--Zgodnie z poprzednim przykładem-->

</Target>

</Project>

Na wstępie musimy poinformować MSBuild, że będziemy używać dodatkowych zadań. Robimy to poprzez

znacznik UsingTask, w którego atrybutach podajemy ścieżkę do biblioteki MSBuild Community Tasks oraz

specyfikujemy, jakiego celu będziemy używać. My użyjemy trzech: Zip, Mail oraz Time. Wszystkie użyte

zostały w celu Deploy. Jako pierwszy używamy Time. Zadanie to doczytuje aktualną datę i czas oraz zapisuje

ją w nowej właściwości. Jako argument tego zadania można podać format w jakim ma być przedstawiana data i

czas. Wynik działania zostaje zapisany we właściwości $(BuildDate), której używamy w kolejnym zadaniu

Zip. Zadanie to tworzy archiwum o nazwie zdefiniowanej w atrybucie ZipFileName zawierające pliki

określone w atrybucie Files. Ostatnim krokiem jest wysłanie pliku archiwum pocztą elektroniczną na

określony adres. Zadanie Mail wykonuje dla nas to zadanie. Pamiętajmy by określić nazwę serwera smtp

(dodatkowo ewentualnie użytkownika i hasło) oraz nadawcę i adresata poczty.

Rysunek 2.8. Wynik działania rozszerzonego skryptu

Page 15: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

2.7. Visual Studio, MSBuild i ich cele Pliki projektów Visual Studio to począwszy od wersji 2005 nic innego jak skrypty MSBuild. Wystarczy

utworzyć dowolny projekt i podejrzeć zwartość pliku csproj. Wypróbujmy to. W Visual Studio utwórzmy nowy

projekt File | New | Project... i z listy dostępnych typów projektów w obszarze Visualm C# | Windows

wybieramy Console Application i nazwijmy go na przykład HelloVisualStudio. By póki, co nie wychylać się

specjalnie z kręgu projektów, jakie realizowaliśmy do tej pory stworzymy taki program:

using System;

namespace HelloVisualStudio

{

class Program

{

static void Main(string[] args)

{

Console.WriteLine("Hello Visual Studio 2008!");

}

}

}

Wspomniana już w poprzednim rozdziale konieczność zachowania szczególnego porządku w projektach

objętych procesem ciągłej integracji wymusi na nas teraz kilka dodatkowych kroków. Warto od razu posprzątać

niepotrzebne referencje. Wpisać odpowiednie dane w informacjach zestawu (Assembly Information). I poprawić

domyśle ustawienia dotyczące traktowania ostrzeżeń kompilatora (Threat warning as errors). Czystość i

porządek jest ważny w każdym projekcie. Jeśli jednak planujesz uruchomienie dla niego procesu ciągłej

integracji to jest on wręcz nieodzowny!

Gdy projekt będzie już gotowy to zapisz całość zamknij Visual Studio i otwórz plik HelloVisualStudio.csproj na

przykład w notatniku.

Visual Studio to świetny edytor plików MSBuild. Oferuje on kolorowanie składni i IntelliSense. Trudno jednak otworzyć w nim pliki projektów w trybie tekstowym. Można to zmienić instalując PowerCommands for Visual Studio 2008. Dzięki temu użytecznemu rozszerzeniu będziesz mógł łatwo otworzyć plik projektu w edytorze XML.

<?xml version="1.0" encoding="utf-8"?>

<Project ToolsVersion="3.5" DefaultTargets="Build"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>

<!-- Domyślne właściwości konfiguracyjne -->

</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

<!-- Właściwości konfiguracyjne dla trybu Debug|AnyCPU -->

</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

<!-- Właściwości konfiguracyjne dla trybu Release|AnyCPU -->

</PropertyGroup>

<ItemGroup>

<Compile Include="Program.cs" />

<Compile Include="Properties\AssemblyInfo.cs" />

</ItemGroup>

<ItemGroup>

<Reference Include="System" />

</ItemGroup>

Page 16: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

<!-- To modify your build process, add your task inside one of the targets below and

uncomment it.

Other similar extension points exist, see Microsoft.Common.targets.

<Target Name="BeforeBuild">

</Target>

<Target Name="AfterBuild">

</Target>

-->

</Project>

Wygląda całkiem znajomo prawda? Domyślny cel o nazwie Build, grupa właściwości itd. Ale zaraz! Gdzie jest

definicja celu Build? Odpowiedzią na tą zagadkę jest import standardowego zestawu celów C# w tej linii

MSBuild:

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

Jak pamiętamy właściwość $(MSBuildToolPath) zawiera ścieżkę do domyślnej instalacji pakiety MSBuild.

Zajrzyjmy więc do pliku, który najpewniej znajduje się tutaj:

C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.CSharp.targets

Plik ten definiuje standardowe cele w procesie kompilacji projektu C# i zawiera kolejną referencję do pliku

Microsoft.Common.targets, w którym z kolei zdefiniowano standardowe cele wspólne dla różnych projektów.

Nic nie stoi na przeszkodzie by te cele przesłaniać i redefiniować. Trzeba pamiętać tylko ogólną zasadę, że liczy

się ta definicja celu, która jest bliżej naszego projektu. W związku z tym można przesłonić standardową definicję

celu BeforeBuild lub AfterBuild dla których to miejsce przewidziano już w pliku projektu (to ten

zakomentowany fragment na końcu skryptu).

Podobnie ma się sprawa ze znanych z Visual Studio zdarzeń pre-build i post-build. Te edytowalne we

właściwościach projektu zdarzenia wykonywane są w predefiniowanych celach PreBuildEvent i

PostBuildEvent.

Rysunek 2.9. Zdarzenia pre i post build.

Page 17: NET Continuous Integration za pół darmo · .NET Continuous Integration za pół darmo Dokument ten zawiera spis treści i drugi rozdział książki, która czeka na swojego wydawcę

Nic jednak nie stoi na przeszkodzie by przesłonić inne również inne cele. Listę predefiniowanych celów, które

możesz wykorzystać zamieszczono w dodatkach.

Niechlubnym wyjątkiem od reguły, zakładającej oparcie procesu budowy oprogramowania w Visual Studio na

MSBuild, są pliki rozwiązań sln Visual Studio. Nie są to pliki MSBuild. Na szczęście są to jednak pliki, z

którymi MSBuild się "rozumie". Można na nich użyć predefiniowanego zadania o nazwie MSBuild . Dokona

ono na pliku rozwiązania tego, czego dokonałby Visual Studio. Stwórzmy więc skrypt build.msbuild dla naszego

projektu. Dodamy go jako element rozwiązania klikając prawym przyciskiem myszy na Solution Items i dodając

nowy element (Add | New Item...). Z listy wybierzmy plik tekstowy i nazwijmy go build.msbuild i wypełniamy

go zgodnie z następującym listingiem

<Project DefaultTargets="Build"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<Target Name="Build">

<MSBuild Targets="Clean;Rebuild" Projects="HelloVisualStudio.sln" />

</Target>

</Project>

Visual Studio "zorientuje się", że ma do czynienia z plikiem MSBuild (tzn. włączy kolorowanie składni i

IntelliSense) dopiero po jego zapisaniu i ponownym otwarciu.

W dalszej pracy pomocnym może okazać się zintegrowanie Visual Studio z MSBuild. Dzięki takiej integracji

będziemy mogli wykonywać skrypty MSBuild bezpośrednio ze środowiska Visual Studio. Z menu Tools

wybieramy pozycję External Tools.... Pod tym elementem kryje się menadżer zewnętrznych narzędzi Visual

Studio. Dołóżmy do niego MSBuild (przycisk Add) i wypełnijmy go zgodnie z poniższym rysunkiem

Rysunek 2.10. Integracja MSBuild z Visual Studio

Teraz, gdy załadowawszy wcześniej utworzony projekt, wybierzemy z menu Tools | MSBuild to wykonany

zostanie MSBuild ze skryptem build.msbuild a wyniki jego działania zostaną pokazane w okienku Output Visual

Studio.