Luboš Račanský
12.8.2011

Pokročilé integrační buildy



Pevně věřím, že continuous integration je již zažitý standard na všech, nebo alespoň na těch jednodušších, projektech. Chtěl bych rozptýlit případné obavy z konfigurace složitějších projektů. Ukážeme si, jak pouhým mvn clean verify nastartujeme celou SOA platformu a nad ní spustíme selenium testy.

SOA je buzzword, ale principy, které oprášil Roman Pichlík v článku Aplikace kontra Služba kontra Knihovna, stále platí. Jedním ze zmiňovaných aspektů je i loose coupling (volné provázání). To sice zjednodušuje deploy updatu, ale na druhou stranu kompletní rozchození prostředí na zelené louce, pokud byste ho snad prováděli ručně, vás rozhodně bavit nebude. Avšak lenost je matka pokroku a pro maven existuje plugin cargo. U zákazníka jsme implementovali webovou aplikaci, která volala další dva servery přes REST api a autentizace byla řešená přes SSO (konkrétně CAS server). I takto komplexní platforma je snadno testovatelná. Konfiguraci popíši na zjednodušeném příkladu dvou serverů Foo a Hoo. Možná máte někde v podvědomí zapsané, že na war souboru nelze záviset. Binárně nikoliv, ale pro potřeby našeho buildu ano. Přidejte tedy do závislostí servery potřebné pro test. Nezapomeňte, že tyto servery musí být nainstalované ve vaší maven repository (nejlépe, pokud spouštíte jejich integrační buildy s goalem deploy).

<dependency>
  <groupId>com.aspectworks.examples</groupId>
  <artifactId>foo</artifactId>
  <version>${foo.version}</version>
  <type>war</type>
</dependency>
<dependency>
  <groupId>com.aspectworks.examples</groupId>
  <artifactId>hoo</artifactId>
  <version>${hoo.version}</version>
  <type>war</type>
</dependency> 


Samotný deploy serverů na tomcat zajistí cargo plugin, configurace viz níže. Pozor, tomcat si budete muset přidat do maven repository sami.

<plugin>
  <artifactId>maven-failsafe-plugin</artifactId>
  <version>2.8.1</version>
  <executions>
    <execution>
      <goals>
        <goal>integration-test</goal>
        <goal>verify</goal>
      </goals>
    </execution>
  </executions>
</plugin>
<plugin>
  <groupId>org.codehaus.cargo</groupId>
  <artifactId>cargo-maven2-plugin</artifactId>
  <version>1.1.1</version>
  <executions>
    <execution>
      <id>start-container</id>
      <phase>pre-integration-test</phase>
      <goals>
        <goal>start</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <container>
      <containerId>tomcat6x</containerId>
      <artifactInstaller>
        <groupId>org.apache</groupId>
        <artifactId>tomcat</artifactId>
        <version>6.0.32</version>
      </artifactInstaller>
      <systemProperties>
        <foo.config.location>file:etc/conf/</foo.config.location>
        <hoo.config.location>file:etc/conf/</hoo.config.location>
      </systemProperties>
    </container>
    <configuration>
      <deployables>
        <deployable>
          <groupId>com.aspectworks.examples</groupId>
          <artifactId>foo</artifactId>
          <type>war</type>
          <properties>
            <context>foo</context>
          </properties>
        </deployable>
        <deployable>
          <groupId>com.aspectworks.examples</groupId>
          <artifactId>hoo</artifactId>
          <type>war</type>\
          <properties>
            <context>hoo</context>
          </properties>
        </deployable>
      </deployables>
      <properties>
        <cargo.servlet.port>${cargo.port}</cargo.servlet.port>
      </properties>
    </configuration>
  </configuration>
</plugin>


Je dobrým zvykem držet konfigurační soubory mimo war. Jediný build tak můžete nasadit v různých prostředích, pouze s jinou konfigurací. V předchozí ukázce pomu jste si mohli všimnout nastavení systémových properties. Tímto způsobem zadáme cestu právě k těmto konfiguračním souborům, které se v našem případě od produkčního prostředí liší například tím, že nastavují in memory HSQL databázi. Spouštění selenium serveru pro integrační test nastavíme v pomu následujícím způsobem.

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>selenium-maven-plugin</artifactId>
  <version>1.1</version>
  <executions>
    <execution>
      <id>start</id>
      <phase>pre-integration-test</phase>
      <goals>
        <goal>start-server</goal>
      </goals>
      <configuration>
        <background>true</background>
      </configuration>
    </execution>
    <execution>
      <id>stop</id>
      <phase>post-integration-test</phase>
      <goals>
        <goal>stop-server</goal>
      </goals>
    </execution>
  </executions>
</plugin>


A nyní můžete konečně spustit mvn clean verify

Závěr

Ukázali jsme si, že i testování rozsáhlejších projektů nemusí být složité. Doufám, že jsem inspiroval alespoň jeden projekt, kde již dnes zavedete integrační testy. Pokud by vás zajímalo, jak pro integrační testy a nightly buildy inicializujeme data, dejte nám vědět v komentářích, můžeme se tomuto tématu věnovat v nějakém z příštích příspěvků.

Vaše emailová adresa nebude zveřejněna

Komentáře

Děkujeme za váš komentář
Další
  • Libor

    > Možná máte někde v podvědomí zapsané, > že na war souboru nelze záviset. Binárně nikoliv, ... To není tak úplně pravda. Pokud se ve war pomu, nastaví maven-war-pluginu vlastnost "addClasspath", je pak možné závislost využívat (classifier=classes). Tedy prakticky: war pom: org.apache.maven.plugins maven-war-plugin 2.1.1 true true aplikační pom: some.group.id war-application 1.1.0 classes Není to kdoví jaká krása a určitě to ukazuje na vadu v návrhu modularity, ale jde to.

  • Libor

    Moc přísná kontrola html odstranila tagy, zkusím to tedy bez nich: U war projektu do pom.xml přidat do build/plugins/plugin: org.apache.maven.plugins / maven-war-plugin / 2.1.1 a v konfiguraci tohoto pluginu přidat attachClasses s hodnotou true. U jiného projektu přidat normální závislost na výše upraveném waru a jako classifier se musí zadat classes .

  • Luboš Račanský

    Libore, děkujeme za připomínku. Navíc jsme upravili komentáře tak, že lze použít tag [sourcecode] pro vkládání zdrojového kódu.

  • Vlada

    Pokud mám testy napsány klasicky jako JUnit, tak jsem měl drobné problémy při spouštění celého maven buildu, jelikož se testy spouštěly jako první. To se dědilo z obecného nastavení nějakého parent pomu. Přidal jsem pak ještě následující konfiguraci do pom.xml pro selenium projekt: [sourcecode language="xml"][/sourcecode] org.apache.maven.plugins maven-surefire-plugin **/*Test.java integration-tests integration-test test false none **/test/*Test.java [sourcecode][/sourcecode]

  • Vlada

    Škoda, že tu není náhled komentáře :-) To bych pak i mohl vidět, jak se mi zdrojový kód zformátuje a že tam neudělám nějakou botu :-)