<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>agimatec &#187; Selenium</title>
	<atom:link href="http://www.agimatec.de/blog/tag/selenium/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.agimatec.de/blog</link>
	<description>Clash of realities</description>
	<lastBuildDate>Tue, 22 Dec 2009 16:50:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Javascript Unit Tests with the YUI TestManager</title>
		<link>http://www.agimatec.de/blog/2009/01/javascript-unit-tests-with-the-yui-testmanager/</link>
		<comments>http://www.agimatec.de/blog/2009/01/javascript-unit-tests-with-the-yui-testmanager/#comments</comments>
		<pubDate>Thu, 29 Jan 2009 14:02:30 +0000</pubDate>
		<dc:creator>Simon Tiffert</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[Test]]></category>
		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://www.agimatec.de/blog/?p=473</guid>
		<description><![CDATA[Testing your Javascript is very important. Especially when the amount of code is growing and growing. The easiest method are unit tests. We have tried several JS unit test frameworks. Including JSUnit, Scriptaculous Unit Test Runner and YUI test. With a lot of YUI components like the YUI Loader and many YUI widgets we refactored [...]]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment wp-att-474" href="http://www.agimatec.de/blog/2009/01/javascript-unit-tests-with-the-yui-testmanager/steps-2/"><img class="alignleft size-full wp-image-474" title="steps" src="http://www.agimatec.de/blog/wp-content/uploads/2009/01/steps.jpg" alt="steps" width="425" height="282" /></a>Testing your Javascript is very important. Especially when the amount of code is growing and growing.</p>
<p>The easiest method are unit tests. We have tried several JS unit test frameworks. Including JSUnit, Scriptaculous Unit Test Runner and YUI test. With a lot of YUI components like the <a href="http://www.agimatec.de/blog/2009/01/using-yui-to-load-your-javascript-modules/">YUI Loader</a> and many <a href="http://developer.yahoo.com/yui/">YUI widgets</a> we refactored our unit tests to use YUI Test. We like the Yahoo User Interface because of its documentation and also of its code quality.</p>
<p>YUI Test is not bundled with YUI. You can use it with YUI but we also use other frameworks like Prototype and DWR. To learn more about YUI Test you can <a href="http://developer.yahoo.com/yui/yuitest/">watch the presentation of Nicholas C. Zakas</a>.</p>
<p>Ok, this is great, now I can test my Javascript. But wait, what is if I have a lot of Javascript. I can group my tests in test cases and test cases in test suites. This is supported. But while the amount of Javascript is growing one file for all tests isn&#8217;t enough. We have a lot of different modules. Each consists of a lot of test cases. Sure, you can copy them all together in a file which is several thousand lines long. But every test run takes then a lot of time, debugging is more complex and it is more complicated to manage this file.</p>
<p><span id="more-473"></span></p>
<h2>YUI TestManager</h2>
<p>Wouldn&#8217;t it be great to have a test runner. A script which takes a lot of unit test files and run them one after another.  Our first approach was based on the Scriptaculous Unit Test Runner embedded in a frameset. We had a navigation frame and some Javascript included to run one unit test file in the main frame. One problem was to collect the results of all unit test files. We patched the Unit Test Runner and collected the data. It was ok and I wanted to refactor the solution to publish it. After starting I suddenly found an undocumented feature of YUI Test &#8211; The <a href="http://developer.yahoo.com/yui/docs/YAHOO.tool.TestManager.html">YUI TestManager</a>. It is exactly what I wanted to do, define the unit test files, run through all of them and collect the results. I think Yahoo is using this feature internally and didn&#8217;t talk a lot about it. But it is included in the <a href="http://developer.yahoo.com/yui/docs/YAHOO.tool.TestManager.html">API</a>, so please YUI team, include it to the documentation. It is a great piece of code.</p>
<h2>Continuous Integration of Javascript with Selenium</h2>
<p>Before I will show you how to use it, some more thoughts about this. We are coming from the agile Java world. So continuous integration is very important for us. Please search for &#8220;Continuous Integration Javascript&#8221; in your search machine. There are just a few hits and no ready to use solution. Yes, you can try to go back to the Java world and run tests with Rhino. There are some Java based unit test frameworks for Javascript. But there are two downsides. You are leaving the Javascript world and you are leaving the browser. It can be ok for you but I don&#8217;t trust the different browsers. I want to be able to run the tests fast in the browser when I&#8217;m developing and I want to test as many browsers as I can. We searched for a solution and what we have running is a suite of Selenium tests. They are at another level. Functional tests which run through use cases in the web frontend. But if we could give them a result of our unit tests we are able to include this in our setup. Then we can run the unit tests in IE, Firefox and Opera automatically.</p>
<p>YUI Test gives you the logger to view the results of your tests. It is not the best view for test results but it is ok. Also there are a lot of events which include the results of the tests after running them. We have implemented a little script which displays a nice summary which we test with Selenium.</p>
<h2>Source code</h2>
<p>Now let&#8217;s head to the source code.</p>
<p>At the beginning we need a unit test. Because I&#8217;m want to concentrate on the TestManager you will find a very very simple test.</p>
<pre name="code" class="javascript">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
&lt;head&gt;
    &lt;title&gt;String test&lt;/title&gt;

    &lt;!--CSS--&gt;
	&lt;link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.6.0/build/logger/assets/logger.css"&gt;
	&lt;link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.6.0/build/yuitest/assets/testlogger.css"&gt;

	&lt;!-- Dependencies --&gt;
	&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/yahoo-dom-event/yahoo-dom-event.js"&gt;&lt;/script&gt;
	&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/logger/logger-min.js"&gt;&lt;/script&gt;

	&lt;!-- Source File --&gt;
	&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/yuitest/yuitest-min.js"&gt;&lt;/script&gt;

    &lt;script type="text/javascript"&gt;
    YAHOO.tool.TestRunner.add(new YAHOO.tool.TestCase({

        name: "String test",

        testEqualityAsserts : function () {
            var Assert = YAHOO.util.Assert;

            Assert.areEqual("hel"+"lo", "hello");     //passes
            Assert.areEqual("YUI test".substr(0,3), "YUI");     //passes
        }
    }));

    YAHOO.util.Event.onDOMReady(function (){

	    if (parent &#038;&#038; parent.TestManager) {
            parent.TestManager.load();
        }
        else {
            var logger = new YAHOO.tool.TestLogger();

            //run the tests
            YAHOO.tool.TestRunner.run();
        }
  	});
  	&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>In the first part we define our tests. In the second part you will see that the test will be called after the DOM is ready. It is a little bit different from the normal examples, because we call <em>parent.TestManager.load()</em> if it is available. Now you can copy this code, write your own tests, define test suites, &#8230; It starts to get interesting, if you have so many tests, that you want to group them into different files. With the code above you can go ahead and  create multiple tests. In the example code I have created to test files calcTest.html and stringTest.html.</p>
<p>To run all tests in all your test files you need to call the TestManager:</p>
<pre name="code" class="html">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
&lt;head&gt;
    &lt;title&gt;JS Unit Tests&lt;/title&gt;
    &lt;meta http-equiv="content-type" content="text/html; charset=utf-8"/&gt;

    &lt;!--CSS--&gt;
    &lt;link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.6.0/build/logger/assets/logger.css"&gt;
    &lt;link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.6.0/build/yuitest/assets/testlogger.css"&gt;

    &lt;!-- Dependencies --&gt;
    &lt;script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/yahoo-dom-event/yahoo-dom-event.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/logger/logger-min.js"&gt;&lt;/script&gt;

    &lt;!-- Source File --&gt;
    &lt;script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/yuitest/yuitest-min.js"&gt;&lt;/script&gt;

    &lt;!-- Source file --&gt;
    &lt;script type="text/javascript"&gt;
    	var TestManager = YAHOO.tool.TestManager;

        TestManager.setPages([
            "./stringTest.html",
            "./calcTest.html"
            ]);

        YAHOO.util.Event.onDOMReady(function() {
        	TestManager.start();
        });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;h1&gt;JS Unit Tests&lt;/h1&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>That&#8217;s simple, isn&#8217;t it?</p>
<p>That will give you the following output:<br />
<img src="http://www.agimatec.de/blog/wp-content/uploads/2009/01/logger.png" alt="logger" title="logger" width="656" height="303" class="alignnone size-full wp-image-491" /></p>
<p>We wanted to give it more the feeling of a unit test suite. As I told you there is an event after test completion, which includes the test results. With our script we are building a summary table which gives you a nice overview for your test results.<br />
<img src="http://www.agimatec.de/blog/wp-content/uploads/2009/01/testrunner.png" alt="testrunner" title="testrunner" width="713" height="502" class="alignnone size-full wp-image-492" /></p>
<p>With the overview table we also can track the results with a simple Selenium test:</p>
<pre name="code" class="java">
package com.agimatec.ostium.portlets.jsunit;

import com.agimatec.ostium.portlets.util.ScreenshottingSelenium;
import com.thoughtworks.selenium.Selenium;
import org.testng.Assert;
import org.testng.Reporter;
import org.testng.annotations.*;

public class JsUnitTest {
    Selenium selenium;

    @BeforeMethod
    @Parameters({"selenium.host", "selenium.port", "browser", "baseUrl", "ostium.login",
            "ostium.password"})
    public void startSelenium(
            @Optional("localhost")String host,
            @Optional("4444")int port,
            @Optional("*firefox")String browser,
            @Optional("http://localhost:8080")String baseUrl
    ) throws Exception {
        Reporter.log("Running selenium");
        selenium = new ScreenshottingSelenium(host, port, browser, baseUrl);
        selenium.start();
    }

    @Test
    public void checkPassedJsUnitTests() throws InterruptedException {
        selenium.open("/portlets/ostium/utilities/ajf/src/test/javascript/testrunner.html");
        for (int second = 0; ; second++) {
            if (second >= 60) Assert.fail("timeout");
            try {
                if (selenium.isElementPresent("//div[@id='testcontainer']/div/h2")) break;
            } catch (Exception e) {
            }
            Thread.sleep(1000);
        }

        Assert.assertTrue(
                selenium.isTextPresent("exact:Result: Passed"),
                "The result of the JS tests should be 'PASSED'.");
    }

    @AfterMethod
    public void stopSelenium() {
        Reporter.log("Stopping selenium");
        selenium.stop();
    }
}
</pre>
<p>The only thing to do is to run the files on a local server. We use a Jetty with Maven to host the files because Selenium needs to include a proxy which didn&#8217;t work if you access the file directly. </p>
<p>Find more to Selenium on our other posts:</p>
<ul>
<li><a href="http://www.agimatec.de/blog/2008/08/selenium-testing-of-massive-ajax-apps/">Selenium testing of massive Ajax Apps</a></li>
<li><a href="http://www.agimatec.de/blog/2008/07/selenium-ci-tests-with-teamcity/">Selenium CI tests with TeamCity</a></li>
<li><a href="http://www.agimatec.de/blog/2008/07/robust-portlet-testing/">Robust portlet testing</a></li>
</ul>
<p><a href='http://www.agimatec.de/blog/wp-content/uploads/2009/01/yuitestmanager.zip'>Download the script and some examples here.</a> We are planning to release it with some other JS stuff as a Google code project, but we are still searching for a name. </p>
<p>If this post was helpful or you have additional ideas, please don&#8217;t hesitate to comment. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.agimatec.de/blog/2009/01/javascript-unit-tests-with-the-yui-testmanager/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Selenium-Flex-Tests with Maven</title>
		<link>http://www.agimatec.de/blog/2008/11/selenium-flex-tests-with-maven/</link>
		<comments>http://www.agimatec.de/blog/2008/11/selenium-flex-tests-with-maven/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 19:05:05 +0000</pubDate>
		<dc:creator>Simon Tiffert</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[TeamCity]]></category>

		<guid isPermaLink="false">http://www.agimatec.de/blog/?p=385</guid>
		<description><![CDATA[I wanted to integrate our Flex application with tests into our Maven build. A few days ago I moved the app to Flex 3 and changed the Maven Plugin from the Maven2 Flex Plugin to Flex-mojos. Now the artifacts are in the repository and you don&#8217;t need to install the Flex SDK to build the [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.agimatec.de/blog/wp-content/uploads/2008/11/img_2340.jpg" alt="" title="london" width="300" height="225" class="alignleft size-medium wp-image-390" />I wanted to integrate our Flex application with tests into our Maven build. A few days ago I moved the app to Flex 3 and changed the Maven Plugin from the <a href="http://www.israfil.net/projects/mojo/maven-flex2-plugin/">Maven2 Flex Plugin</a> to <a href="http://blog.flex-mojos.info">Flex-mojos</a>. Now the artifacts are in the repository and you don&#8217;t need to install the Flex SDK to build the application.</p>
<p>We have written the application as a demo in the first place and now wanting to test it in the wild. Because we use Cairngorm the application is well structured and contains as view layer only minimal parts of logic. Yes, we could include unit tests, but integration tests are far more interesting (from my point of view). In a large code base it could happen, that because of refactoring some things are broken. No deal, if you have tests and a CI system. But in the Flex app there are just tiny parts which I could test in a normal unit test.</p>
<p>Okay, so it should be integration test. Sounds good and not too complicated. There should exist a lot of frameworks because a lot of people start to use BlazeDS and other stuff in Java environments. Just something to start the app, run some tests and get the result back in the CI system.</p>
<p>I started to search on google and was surprised. Most of the blog posts I have found on that topic are just two month old. And there are not so many posts about that topic. With the combination of those posts I figured out, how to solve that problem. What problem?</p>
<ul>
<li>Integration tests of our Flex app</li>
<li>Integrated in Maven</li>
<li>Should work together with Cairngorm (would be more complicated with some unit tests frameworks)</li>
<li>Could be Selenium (to start the app and run tests)</li>
<li>Should be integrated in our continuous integration server TeamCity</li>
<li>Could be written in Java</li>
</ul>
<p><span id="more-385"></span></p>
<p>First thanks to the <a href="http://www.blackpepper.co.uk/black-pepper-blog/Flex-acceptance-testing-and-continuous-integration.html">blog post of Julia at Blackpepper</a>. She opened my eyes how to work with Java and Flex in combination. It is the combination of the SeleniumFlexAPI, which integrates as Flex to Javascript bridge in your Flex application and FlashSelenium.</p>
<p><a href="http://sourceforge.net/projects/seleniumflexapi/">SeleniumFlexApi</a> is in one part a Flex library which needs to be included in your app and on the other part an extension to the Selenium IDE. I like the Flex part, because it makes it easy to dive over Javascript into the details of your Flex app. What I don&#8217;t really like is the Javascript extension. Yes, it is not only a Selenium IDE part and you can include it into the start of the Selenium Server, but it is far away from Java and Maven.</p>
<p><a href="http://code.google.com/p/flash-selenium/">FlashSelenium</a> is a piece of code which let&#8217;s you talk from Java over Selenium with your Flex app. The Java part is very handy, but you need to code into Flex, which methods you could call over your bridge. So I need to write special code, which opens the bridge. The SeleniumFlexAPI is much better in this part.</p>
<p>I liked the solution of the blog post and started to implement it.</p>
<p>First the pom.xml where you need to include the SeleniumFlexAPI (the scope cost me some time):</p>
<pre class="xml" name="code">&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&gt;

   &lt;parent&gt;
        &lt;groupId&gt;agimatec&lt;/groupId&gt;
        &lt;artifactId&gt;assessor&lt;/artifactId&gt;
        &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
        &lt;relativePath&gt;../pom.xml&lt;/relativePath&gt;
    &lt;/parent&gt;

  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
  &lt;groupId&gt;agimatec&lt;/groupId&gt;
  &lt;artifactId&gt;assessor-flexapp&lt;/artifactId&gt;
  &lt;packaging&gt;swf&lt;/packaging&gt;
  &lt;version&gt;${agimatec-assessor-version}&lt;/version&gt;
  &lt;name&gt;Assessor Flex Application&lt;/name&gt;
  &lt;url&gt;http://www.agimatec.de&lt;/url&gt;

  &lt;dependencies&gt;
    		 &lt;!--Flex SDK dependencies--&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;com.adobe.flex.sdk&lt;/groupId&gt;
			&lt;artifactId&gt;playerglobal&lt;/artifactId&gt;
			&lt;version&gt;3.0.0.477&lt;/version&gt;
			&lt;type&gt;swc&lt;/type&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;com.adobe.flex.sdk&lt;/groupId&gt;
			&lt;artifactId&gt;flex&lt;/artifactId&gt;
			&lt;version&gt;3.0.0.477&lt;/version&gt;
			&lt;type&gt;swc&lt;/type&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;com.adobe.flex.sdk&lt;/groupId&gt;
			&lt;artifactId&gt;framework&lt;/artifactId&gt;
			&lt;version&gt;3.0.0.477&lt;/version&gt;
			&lt;type&gt;swc&lt;/type&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;com.adobe.flex.sdk&lt;/groupId&gt;
			&lt;artifactId&gt;framework&lt;/artifactId&gt;
			&lt;version&gt;3.0.0.477&lt;/version&gt;
			&lt;type&gt;resource-bundle&lt;/type&gt;
			&lt;classifier&gt;en_US&lt;/classifier&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;com.adobe.flex.sdk&lt;/groupId&gt;
			&lt;artifactId&gt;rpc&lt;/artifactId&gt;
			&lt;version&gt;3.0.0.477&lt;/version&gt;
			&lt;type&gt;swc&lt;/type&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;com.adobe.flex.sdk&lt;/groupId&gt;
			&lt;artifactId&gt;rpc&lt;/artifactId&gt;
			&lt;version&gt;3.0.0.477&lt;/version&gt;
			&lt;type&gt;resource-bundle&lt;/type&gt;
			&lt;classifier&gt;en_US&lt;/classifier&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;com.adobe.flex.sdk&lt;/groupId&gt;
			&lt;artifactId&gt;utilities&lt;/artifactId&gt;
			&lt;version&gt;3.0.0.477&lt;/version&gt;
			&lt;type&gt;swc&lt;/type&gt;
		&lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;com.adobe.cairngorm&lt;/groupId&gt;
      &lt;artifactId&gt;cairngorm-bin&lt;/artifactId&gt;
      &lt;version&gt;2.2.1&lt;/version&gt;
      &lt;type&gt;swc&lt;/type&gt;
    &lt;/dependency&gt;

      &lt;dependency&gt;
        &lt;groupId&gt;org.openqa.selenium&lt;/groupId&gt;
        &lt;artifactId&gt;flex-api&lt;/artifactId&gt;
        &lt;version&gt;0.22&lt;/version&gt;
        &lt;type&gt;swc&lt;/type&gt;
          &lt;scope&gt;internal&lt;/scope&gt;
      &lt;/dependency&gt;

		 &lt;!--FlexUnit dependencies--&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;flexunit&lt;/groupId&gt;
			&lt;artifactId&gt;flexunit&lt;/artifactId&gt;
			&lt;version&gt;0.85&lt;/version&gt;
			&lt;type&gt;swc&lt;/type&gt;
			&lt;scope&gt;test&lt;/scope&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;flexunit.junit&lt;/groupId&gt;
			&lt;artifactId&gt;flexunit-optional&lt;/artifactId&gt;
			&lt;version&gt;0.85&lt;/version&gt;
			&lt;type&gt;swc&lt;/type&gt;
			&lt;scope&gt;test&lt;/scope&gt;
		&lt;/dependency&gt;
  &lt;/dependencies&gt;

  &lt;build&gt;
    &lt;sourceDirectory&gt;src/main/flex&lt;/sourceDirectory&gt;
    &lt;plugins&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;info.rvin.mojo&lt;/groupId&gt;
        &lt;artifactId&gt;flex-compiler-mojo&lt;/artifactId&gt;
        &lt;extensions&gt;true&lt;/extensions&gt;
        &lt;configuration&gt;
          &lt;includeSources&gt;
            &lt;param&gt;${project.build.sourceDirectory}&lt;/param&gt;
          &lt;/includeSources&gt;
          &lt;locales&gt;
            &lt;param&gt;en_US&lt;/param&gt;
            &lt;param&gt;de_DE&lt;/param&gt;
          &lt;/locales&gt;
          &lt;debug&gt;true&lt;/debug&gt;
        &lt;/configuration&gt;
      &lt;/plugin&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;info.rvin.mojo&lt;/groupId&gt;
        &lt;artifactId&gt;asdoc&lt;/artifactId&gt;
      &lt;/plugin&gt;
    &lt;/plugins&gt;
  &lt;/build&gt;
&lt;/project&gt;</pre>
<p>To get the Flex application compile with Maven you need to download the SeleniumFlexAPI and include the swc-file into your Maven repository, because it is (not yet) available on public repositories.</p>
<p>After compiling you can start the Selenium IDE and load the extension or go directly to FireBug and try to call the methods. Be aware, that the args-parameter is normally optional, but needs to be filled for the Javascript-Flex bridge (also cost me some time).</p>
<p>To call a method of your running application in Firefox fire up in FireBug&#8217;s console:</p>
<pre class="html" name="code">window.document['AppName'].getFlexExists('NameOfAnElement','');</pre>
<p>To test your application you need to know, what the name of your application is (can be found in the HTML calling the Flash file) and you need to give ids to your elements, because there is just an id locator at the moment.</p>
<p>If you are at this point we can now switch to the Java part with Selenium. Selenium is just Javascript when you are in the browser. So all you do is to call the Javascript function which you called before over Firebug. FlashSelenium is a good wrapper for that call which means that you don&#8217;t have to write normal strings into your Selenium commands. I like a little bit more comfort and wanted to wrap the SeleniumFlexAPI a little bit closer. Also there are some methods in the FlashSelenium you don&#8217;t need with this solution. So I started to implement my own little wrapper. Maybe it is also interesting for the SeleniumFlexAPI (if completed with all methods).</p>
<p>Here is the beginning of the code:</p>
<pre class="java" name="code">package com.agimatec.assessor.selenium;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;

public class FlexSelenium {
    Selenium selenium;
    String flexApp;

    public FlexSelenium(String ip, int port, String browser, String url, String flexApp) {
        selenium = new DefaultSelenium(ip, port, browser, url);
        this.flexApp = flexApp;
    }

    public void start() {
        selenium.start();
    }

    public void open(String url) {
        selenium.open(url);
    }

    public void stop() {
        selenium.stop();
    }

    public String doFlexClick(String id) {
        return callFlexBridge("doFlexClick",id);
    }

    public boolean getFlexExists(String id) {
        return callFlexBridge("getFlexExists",id).equals("true");
    }

    private String callFlexBridge(String method, String id) {
        return callFlexBridge(method, id, null);
    }

    private String callFlexBridge(String method, String id, String args) {
        if(args == null || args.trim().equals("")) {
            args = "''";
        }
        return selenium.getEval("window.document['"+flexApp+"']."+method+"('"+id+"',"+args+");");
    }
}</pre>
<p>And now the test case is the only thing which is missing. I used TestNG because it can be easier configured in a Selenium environment (when it started to become more complicated with several browsers, plattforms, test suites, test groups &#8230;):</p>
<pre class="java" name="code">package com.agimatec.assessor.selenium;

import org.testng.annotations.Test;

public class AssessorTest {
    private final static String URL = "http://192.168.1.175:8080/assessor-webapp";
    FlexSelenium selenium;

    @Test
    public void setUp() throws InterruptedException {
        selenium = new FlexSelenium("192.168.1.254", 4444, "*firefox", URL, "Terminal");
        selenium.start();
        selenium.open(URL);
        while(!selenium.getFlexExists("videoPlayer")) {
            Thread.sleep(1000);
        }

        selenium.doFlexClick("videoPlayer");
        Thread.sleep(300);
        selenium.doFlexClick("enterUserModeButton");
        selenium.stop();
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.agimatec.de/blog/2008/11/selenium-flex-tests-with-maven/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Perfect Selenium Setup</title>
		<link>http://www.agimatec.de/blog/2008/10/perfect-selenium-setup/</link>
		<comments>http://www.agimatec.de/blog/2008/10/perfect-selenium-setup/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 14:15:45 +0000</pubDate>
		<dc:creator>Simon Tiffert</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[TeamCity]]></category>

		<guid isPermaLink="false">http://www.agimatec.de/blog/?p=369</guid>
		<description><![CDATA[It takes some time, but I&#8217;m now nearly happy with our Selenium setup. In this series I want to explain what goals existed and how we get a larger suite of Selenium tests running. You can find some posts around Selenium in this blog, but I want to get in more detail. Also there are [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.agimatec.de/blog/wp-content/uploads/2008/10/fotolia_1476264_xs.jpg"><img class="alignleft size-medium wp-image-371" title="crash test dummy" src="http://www.agimatec.de/blog/wp-content/uploads/2008/10/fotolia_1476264_xs.jpg" alt="" width="300" height="195" /></a>It takes some time, but I&#8217;m now nearly happy with our Selenium setup. In this series I want to explain what goals existed and how we get a larger suite of Selenium tests running.</p>
<p>You can find some posts around Selenium in this blog, but I want to get in more detail. Also there are some improvements to the solutions which could be really interesting if you start with Selenium or get an idea, how others deal with larger Selenium test suites. I will try to publish a new part every week, because there is so much to say, which wouldn&#8217;t fit into one single post.</p>
<p>Goals:</p>
<ul>
<li>Continuous integration of web application tests</li>
<li>Tests in different browsers</li>
<li>TestNG Setup</li>
<li>Integration in Maven2</li>
<li>Faster Selenium tests</li>
</ul>
<p>Tests:</p>
<ul>
<li>Running use cases of the web application</li>
<li>Running Javascript Unit Tests in different browsers</li>
<li>Take screenshots of the application</li>
</ul>
<p>I&#8217;m a web developer and no full-time tester, that&#8217;s why you should see the posts as support in an agile environment. There are different solutions and methods to test a web application, but I feel very comfortable with coding my tests and provide solutions which helps in the day-to-day work.</p>
<p>Until I will continue with the series, you can have a look at the previous posts:</p>
<ul>
<li><a href="http://www.agimatec.de/blog/2008/04/web20-oberflachen-testen/">Testing of Web 2.0 interfaces</a> (in german, but you will understand the code part)</li>
<li><a href="http://www.agimatec.de/blog/2008/07/robust-portlet-testing/">Robust portlet testing</a></li>
<li><a href="http://www.agimatec.de/blog/2008/07/selenium-ci-tests-with-teamcity/">Selenium CI tests with TeamCity</a></li>
<li><a href="http://www.agimatec.de/blog/2008/08/selenium-testing-of-massive-ajax-apps/">Selenium testing of massive Ajax Apps</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.agimatec.de/blog/2008/10/perfect-selenium-setup/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Selenium Testing of massive Ajax Apps</title>
		<link>http://www.agimatec.de/blog/2008/08/selenium-testing-of-massive-ajax-apps/</link>
		<comments>http://www.agimatec.de/blog/2008/08/selenium-testing-of-massive-ajax-apps/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 19:36:40 +0000</pubDate>
		<dc:creator>Simon Tiffert</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[Test]]></category>

		<guid isPermaLink="false">http://www.agimatec.de/blog/?p=247</guid>
		<description><![CDATA[Testing of a web application is a hard work. You don&#8217;t handle with data in a direct way. You got a lot of markup around it. How to handle this in a flexible and more robust way could be found in the post Robust Portlet Testing. If you have fought your way through the markup, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-249" title="img_25211" src="http://www.agimatec.de/blog/wp-content/uploads/2008/08/img_25211.jpg" alt="" width="300" height="225" />Testing of a web application is a hard work. You don&#8217;t handle with data in a direct way. You got a lot of markup around it. How to handle this in a flexible and more robust way could be found in the post <a href="http://www.agimatec.de/blog/2008/07/robust-portlet-testing/">Robust Portlet Testing</a>.</p>
<p>If you have fought your way through the markup, you now get to another trap on your way to get your tests flying. The markup is changing, because you are using the Ajax technology. After the page is rendered there are asynchronous calls changing your DOM. You are asking: Where is the problem? The problem of testing is, that you need to teach your test tool, to look at the page in the same way you are looking at it. On the first look you want to get the third row of the table. But wait, it is still loading, even if there is just a minimal delay. If you do automatic tests they should run through all the tests as fast as possible. The tool is not to twiddle one&#8217;s thumbs to click on the button.</p>
<p>You need to write your tests in another way. The question isn&#8217;t only if the data could be found in the DOM, it is changing to if the surrounding element has loaded could the data be found then. And this is the essential point, where most recording tools like Selenium IDE are failing. It doesn&#8217;t give you a hint, what is loading after the DOM is ready the first time. Yes it is possible to add pause or a waitForElement-function before every field, but wouldn&#8217;t it be easier to have little helpers for the case.</p>
<p><span id="more-247"></span></p>
<p>First let&#8217;s have a look at how the waitForElement-function in Selenium is working in Selenium-RC:</p>
<pre class="java" name="code">for (int second = 0; ; second++) {
    if (second &gt;= timeout) throw new ElementNotFoundException("Element not present: " + locator);
    try {
        if (this.isElementPresent(locator)) break;
    } catch (Exception e) {
    }
    Thread.sleep(1000);
}</pre>
<p>It is polling every second, if the element specified be the locator could be found. That is better than adding a pause. Why?</p>
<p>How long does your pause needs to be? 500ms, 1s, 2s? You are not sure about it, I am sure. It is a guessing and it is really slowing down your tests. You have 20 elements in one test. And let&#8217;s say you&#8217;ve got  50-100 tests at the beginning. Well &#8211; you are pausing damn long.</p>
<p>That&#8217;s why you should start using the waitForX-functions of Selenium. Now nearly every line of your massive Ajax test has a previous waitForX-function. It doesn&#8217;t make your tests more readable, but more stable and as fast as possible.</p>
<p>Now we are in a Java world, writing our Selenium tests and are tired of writing waitForX-functions. The next step is to extend the DefaultSelenium class and adding some tiny helper functions:</p>
<ul>
<li>safeOpen</li>
<li>safeGetText</li>
<li>safeGetValue</li>
<li>safeClick</li>
<li>&#8230;</li>
</ul>
<p>All these functions are equivalents of the normal Selenium functions, but having a waitForX-function build-in. Normally you are saying: getText for this element and giving a locator. Now use the locator to do a pre-test of the element. If the element could be found, get the text. It is just a little helper, but it makes your tests much cleaner and robust.</p>
<p>We have introduced another trick for the safeOpen function. Because we are fetching our dependend Javascript files asynchronously after the normal rendering has finished (check out the <a href="http://developer.yahoo.com/yui/yuiloader/">YUI Loader</a>), we add a new element with an id after the Javascript has finished its loading process. Now we can poll if the element is in the DOM and start after all the Javascript has loaded.</p>
<p>Check out the following example and try out how it helps to speed up writing your Ajax tests and reduce the test <em>to the test</em>.</p>
<p>See the following example test. Even if you don&#8217;t understand which application is tested, you can <em>read</em> the test:</p>
<pre class="java" name="code">    @Test(dataProvider = "users")
    public void testUserDetails(User user) throws InterruptedException, ElementNotFoundException {
        selenium.safeOpen(URL);

        // fill in search form
        selenium.safeType(
                browserXPath().elementByClassName("searchForm").textField().toString(),
                user.getUserIdentification());

        selenium.safeClick(
                browserXPath().elementByClassName("searchForm").submitButton().toString());

        // action to detail portlet with service menu
        selenium.safeClick(
                browserXPath().table().tr(1).td(1).a().toString());

        // check if all fields are available
        String[] userDetails = {user.getUserIdentification(), user.getGender().toString(), user.getFirstName(), user.getLastName(), user.getEmail(), user.getMobilePrefix(), user.getMobileNumber()};
        for (int i = 1; i &lt;= userDetails.length; i++) {
            selenium.waitForText(detailXPath().table().tr(i).td(2).toString(),
                    checkEmpty(userDetails[i]));
        }
    }</pre>
<p>To see the &#8220;<em>unbelievable magic</em>&#8221; behind the scenes, check out the <strong>AjaxSelenium</strong> extension:</p>
<pre class="java" name="code">
import com.thoughtworks.selenium.DefaultSelenium;

public class AjaxSelenium extends DefaultSelenium {
    public void safeClick(String locator) throws ElementNotFoundException, InterruptedException {
        this.waitForElement(locator);
        this.click(locator);
    }

    public void safeOpen(String pageUrl) throws InterruptedException, ElementNotFoundException {
        this.open(pageUrl);
        this.waitForPageToLoad("30000");
        this.waitForElement("//div[@id='javascript-loaded']");
    }

    public String safeGetText(String locator) throws ElementNotFoundException, InterruptedException {
        this.waitForElement(locator);
        return this.getText(locator);
    }

    public String safeGetValue(String locator) throws ElementNotFoundException, InterruptedException {
        this.waitForElement(locator);
        return this.getValue(locator);
    }

    public void safeType(String locator, String text) throws ElementNotFoundException, InterruptedException {
        this.waitForElement(locator);
        this.type(locator,text != null ? text : "");
    }

    public void waitForElement(String locator) throws ElementNotFoundException, InterruptedException {
        for (int second = 0; ; second++) {
            if (second &gt;= timeout) throw new ElementNotFoundException("Element not present: " + locator);
            try {
                if (this.isElementPresent(locator)) break;
            } catch (Exception e) {
            }
            Thread.sleep(1000);
        }
    }

    public void waitForText(String locator, String text) throws InterruptedException, ElementNotFoundException {
        for (int second = 0;; second++) {
            if (second &gt;= timeout) throw new ElementNotFoundException("Text '" + text + "' in element '"+ locator +"' not present.");
            try {
                if (text.trim().equals(this.getText(locator).trim())) break;
            } catch (Exception e) {}
            Thread.sleep(1000);
        }
    }

    public void waitForValue(String locator, String text) throws ElementNotFoundException, InterruptedException {
        for (int second = 0;; second++) {
            if (second &gt;= timeout) throw new ElementNotFoundException("Text '" + text + "' in element '"+ locator +"' not present.");
            try {
                if (text.trim().equals(this.getValue(locator).trim())) break;
            } catch (Exception e) {}
            Thread.sleep(1000);
        }
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.agimatec.de/blog/2008/08/selenium-testing-of-massive-ajax-apps/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Selenium CI Tests with TeamCity</title>
		<link>http://www.agimatec.de/blog/2008/07/selenium-ci-tests-with-teamcity/</link>
		<comments>http://www.agimatec.de/blog/2008/07/selenium-ci-tests-with-teamcity/#comments</comments>
		<pubDate>Wed, 30 Jul 2008 14:33:08 +0000</pubDate>
		<dc:creator>Simon Tiffert</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[TeamCity]]></category>

		<guid isPermaLink="false">http://www.agimatec.de/blog/?p=219</guid>
		<description><![CDATA[TeamCity&#8217;s build agents are great. You can build a grid of servers running your continuous integration tests. This speeds up the build process when there are many commits over the day. But there is another great feature of the grid: You can setup different environments for your builds. Think of Java version, operating system, databases [...]]]></description>
			<content:encoded><![CDATA[<p>TeamCity&#8217;s build agents are great. You can build a grid of servers running your continuous integration tests. This speeds up the build process when there are many commits over the day. But there is another great feature of the grid:</p>
<p>You can setup different environments for your builds. Think of Java version, operating system, databases and browsers.</p>
<p>These are great news for web frontend tests because you can setup a clean environment with all your needs. Just fire your Selenium-Rc with TestNG against this agent.</p>
<p>There is just one problem: You shouldn&#8217;t install the build agent for the browser tests as service. We setup a new Xen container for the tests and no browser was visible. It was in the TaskManager but won&#8217;t show our tests.</p>
<p>After searching in Google and asking (the really fast) JetBrains support the solution is to start the agent from the command line. To get the agent running after reboots just write a little bat file and place it in the autostart folder:</p>
<pre name="code" class="java">
cd C:\TeamCityAgent\bin\
agent.bat start
</pre>
<p>Another tipp is to install a VNC server, because if you are using remote desktop you are stealing the Windows session.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.agimatec.de/blog/2008/07/selenium-ci-tests-with-teamcity/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Robust Portlet Testing</title>
		<link>http://www.agimatec.de/blog/2008/07/robust-portlet-testing/</link>
		<comments>http://www.agimatec.de/blog/2008/07/robust-portlet-testing/#comments</comments>
		<pubDate>Mon, 28 Jul 2008 20:13:03 +0000</pubDate>
		<dc:creator>Simon Tiffert</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[Test]]></category>

		<guid isPermaLink="false">http://www.agimatec.de/blog/?p=200</guid>
		<description><![CDATA[Testing of web applications isn&#8217;t easy. If you are in a portlet environment things getting even more complicated. A portlet is a web application for itself and there could be a lot of different combinations on every page. There could also be many instances of each portlet on a page. What are the consequences? You [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_202" class="wp-caption alignleft" style="width: 310px"><img class="size-medium wp-image-202" title="stonehenge" src="http://www.agimatec.de/blog/wp-content/uploads/2008/07/stonehenge.jpg" alt="Robust and durable" width="300" height="199" /><p class="wp-caption-text">Robust and durable</p></div>
<p>Testing of web applications isn&#8217;t easy. If you are in a portlet environment things getting even more complicated. A portlet is a web application for itself and there could be a lot of different combinations on every page. There could also be many instances of each portlet on a page.</p>
<p><strong>What are the consequences?</strong><br />
You couldn&#8217;t use normal ids on tags, because ids are unique on a page which conflicts when many instances of the portlet are on the same page.</p>
<p>A portal is themeable. The design and also the HTML structure depends on the user settings.</p>
<p>Portlets could be rearranged on a page, which means that the HTML structure is changing every time a new portlet is on a page or a portlet is moved to another place.</p>
<p><strong>Lessons we learned with portlet testing</strong></p>
<div id="attachment_208" class="wp-caption alignleft" style="width: 143px"><img class="size-medium wp-image-208" title="zen-stones" src="http://www.agimatec.de/blog/wp-content/uploads/2008/07/zen-stones.jpg" alt="Nice but unstable" width="133" height="144" /><p class="wp-caption-text">Nice but unstable</p></div>
<p>Try to write your tests as robust as possible. Nothing is as painful as seeing your test suite fallen to the ground.</p>
<p>You are developing a new theme or modifying your old one and all locators, in all tests, every field is broken.</p>
<p>You have a defined a set of portlets. Suddenly you need new portlets in this setup. You added the portlet at the top of the page and the tests are broken again.</p>
<p>Make portlet testing fun again.</p>
<p><strong>Using XPath the right way</strong></p>
<p>There are three tipps:</p>
<ul>
<li>Isolation</li>
<li>Wildcards</li>
<li>Abstraction</li>
</ul>
<p><strong>Isolation:</strong></p>
<p>Normally there is a surrounding div-container with an id of the portlet instance. Try to use this element as entry point for your XPath. If you use the generated XPath expression of a tool like Selenium IDE, XPath Checker or other tools you will never get structured expressions which are easy maintainable.</p>
<pre name="code" class="xml">
//div[@id='agimatec_portlet_curatorArcaeEdit__CuratorArcaeEditPortlet_WAR_ostiumcuratorarcae__editParcel']
</pre>
<p><strong>Wildcards:</strong></p>
<p>I have never seen a portal source code with a really clean html structure. Because there are many columns, many layouts, many supported browsers you end in a kind of tag soup. Yes you can get an XPath expression with 20 elements. As mentioned there are tools which are generating the expression, but one change and you are doing the work again. Use a kind of wildcards in XPath. With the isolation you are at the portlet instance and right into your own code. Maybe there is just one table inside the portlet, but a lot of more div-layers between the table. With the // syntax you can navigate recursive to the next child element of that type.</p>
<pre name="code" class="xml">
//div[@id='agimatec_portlet_curatorArcaeEdit__CuratorArcaeEditPortlet_WAR_ostiumcuratorarcae__editParcel']//table/tr[1]/td[2]
</pre>
<p><strong>Abstraction:</strong></p>
<p>Don&#8217;t write the same code again and again. Write a helper which constructs the XPath for you. If you use a framework to build your forms, you can write a library which navigates directly to the form elements. XPath expression aren&#8217;t fun. It is better that it hurts one person than the hole team. Strive for abstraction.</p>
<pre name="code" class="java">
detailPath().tab(1).ostiumTable().tr(1).td(2).toString())
</pre>
<p><strong>Conclusion</strong></p>
<p>There are a lot of tools for test recording. If you are using Selenium it is the Selenium IDE, if you use WebTest there is the WebTest Recorder. These tools are great for starting your web tests. But if your test suite is getting larger and you are working in an agile environment things are changing. Things are changing to often for maintaining recorded tests.</p>
<blockquote><p>Learn with recorders but test with logic</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.agimatec.de/blog/2008/07/robust-portlet-testing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Maven2 Build Lifecycle</title>
		<link>http://www.agimatec.de/blog/2008/07/maven2-build-livecycle/</link>
		<comments>http://www.agimatec.de/blog/2008/07/maven2-build-livecycle/#comments</comments>
		<pubDate>Tue, 15 Jul 2008 19:45:55 +0000</pubDate>
		<dc:creator>Simon Tiffert</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Selenium]]></category>

		<guid isPermaLink="false">http://www.agimatec.de/blog/?p=197</guid>
		<description><![CDATA[When you start building your large project with Maven2 it is not easy. You need to understand the concepts behind Maven2. One concept is the build lifecycle, which will be explained in this post. Why is it important? I always call mvn clean install and everything is running. For a simple project this is no [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft alignnone size-full wp-image-198" style="float: left;" title="lifecycle" src="http://www.agimatec.de/blog/wp-content/uploads/2008/07/lifecycle.jpg" alt="" width="401" height="299" />When you start building your large project with Maven2 it is not easy. You need to understand the concepts behind Maven2. One concept is the build lifecycle, which will be explained in this post.</p>
<p>Why is it important? I always call <em>mvn clean install</em> and everything is running.</p>
<p>For a simple project this is no problem, but in a real world project you need to know what is happening behind the scenes.</p>
<p>The default lifecycle consists of the following phases:</p>
<ul>
<li>validate</li>
<li>compile</li>
<li>test</li>
<li>package</li>
<li>integration-test</li>
<li>verify</li>
<li>install</li>
<li>deploy</li>
</ul>
<p>If you call <em>mvn install</em> in the default lifecycle, all phases until install will be running. Let&#8217;s step through the phases:</p>
<p><span id="more-197"></span></p>
<p><strong>Validate:</strong> Check if all the pom.xml-Files in the project are valid and if all information for the build is available</p>
<p><strong>Compile:</strong> Compile the source code, nothing special in here. For information where the compiled files are stored, check the <a href="http://docs.codehaus.org/display/MAVENUSER/The+Standard+Directory+Layout">default directory layout</a> in Maven2.</p>
<p><strong>Test:</strong> If nothing special is configured and you have stored your tests under src/test/java, the <a href="http://maven.apache.org/plugins/maven-surefire-plugin/">Surefire-Plugin</a> will run your tests and generate reports</p>
<p><strong>Package:</strong> If you are building a JAR, WAR, EAR or something else, it will be packaged in this phase. This is very important if you want to include sources into the package. Then you need choose a phase before the package phase is running.</p>
<p><strong>Integration-Test:</strong> In this phase you can run your integration tests. Some phases have a pre- and post-phase, where you can prepare some things. We use it to start and end selenium to run our web tests in this phase. If you are testing something else, maybe Cargo then you will the pre- and post-phase useful to start and end your server(s).</p>
<p><strong>Verify:</strong> Verify the generated package (I have never used this phase)</p>
<p><strong>Install:</strong> This phase is important because the package (and its pom.xml) will be installed in the local repository. If there are dependencies to this project, it will be searched in the local repository.</p>
<p><strong>Deploy:</strong> The deploy phase installs the package in the remote repository. In our environment this is the main proxy <a href="http://archiva.apache.org/">Archiva</a>. Packages are build nightly in the CI-Server to be available for all developers. This phase could also be used, to deploy the hole project into a server.</p>
<p><strong>Other phases:</strong></p>
<p>You need to have a closer look at the phases if you need to generate (re)sources. To process our javascript (minify, verify with JSLint, &#8230;) we make heavy use of the following phases before the compile phase starts:</p>
<ul>
<li>generate-sources</li>
<li>process-sources</li>
<li>generate-resources</li>
<li>process-resources</li>
</ul>
<p>There are a lot of pre-configured <a href="http://cvs.peopleware.be/training/maven/maven2/buildLifecyclePhases.html">goals</a> defined for the lifecycle. Which goals are defined depends on the choosen packaging (JAR, WAR, EAR, &#8230;). You normally don&#8217;t need to know which goals are running, because they will fit to your packaging. If you need to hook into the lifecycle you configure your plugins to run in the appropriate phase. One the hand it is important to find the right phase that e.g. your resources are packaged, on the other hand we often try to find the phase which fits best to the concept of Maven2. This is important if other developers try to find out what is happening in the hole lifecycle.</p>
<p>We often use the <a href="http://maven.apache.org/plugins/maven-antrun-plugin/">AntRun-Plugin</a> because it is a very easy way, to copy things, move things around or include tasks where you don&#8217;t want to write your own plugin. See an example for including this in your lifecycle:</p>
<pre class="xml" name="code">
...
  &lt;build&gt;
    &lt;plugins&gt;
      &lt;plugin&gt;
        &lt;artifactId&gt;maven-antrun-plugin&lt;/artifactId&gt;
        &lt;executions&gt;
          &lt;execution&gt;
            &lt;id&gt;Deploy .war&lt;/id&gt;
            &lt;phase&gt;install&lt;/phase&gt;
            &lt;configuration&gt;
              &lt;tasks&gt;
                &lt;copy file="target/example.war"
                      tofile="${liferay_home}/deploy/example.war"/&gt;
              &lt;/tasks&gt;
            &lt;/configuration&gt;
            &lt;goals&gt;
              &lt;goal&gt;run&lt;/goal&gt;
            &lt;/goals&gt;
          &lt;/execution&gt;
        &lt;/executions&gt;
      &lt;/plugin&gt;
    &lt;/plugins&gt;
  &lt;/build&gt;

...
</pre>
<p>In the next example you will see, how to start an integration test:</p>
<pre class="xml" name="code">
...
    &lt;build&gt;
        &lt;finalName&gt;ostium-mobile-suite&lt;/finalName&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
                &lt;configuration&gt;
                    &lt;source&gt;1.5&lt;/source&gt;
                    &lt;target&gt;1.5&lt;/target&gt;
                    &lt;encoding&gt;UTF-8&lt;/encoding&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.codehaus.cargo&lt;/groupId&gt;
                &lt;artifactId&gt;cargo-maven2-plugin&lt;/artifactId&gt;
                &lt;version&gt;0.3-SNAPSHOT&lt;/version&gt;
                &lt;configuration&gt;
                    &lt;wait&gt;false&lt;/wait&gt;
                    &lt;container&gt;
                        &lt;containerId&gt;tomcat5x&lt;/containerId&gt;
                        &lt;zipUrlInstaller&gt;
                            &lt;url&gt;http://www.apache.org/dist/tomcat/tomcat-5/v5.5.16/bin/apache-tomcat-5.5.16.zip&lt;/url&gt;
                        &lt;/zipUrlInstaller&gt;
                        &lt;output&gt;${project.build.directory}/tomcat5x.log&lt;/output&gt;
                        &lt;log&gt;${project.build.directory}/cargo.log&lt;/log&gt;
                    &lt;/container&gt;
                    &lt;configuration&gt;
                        &lt;home&gt;${project.build.directory}/tomcat5x/container&lt;/home&gt;
                        &lt;properties&gt;
                            &lt;cargo.logging&gt;high&lt;/cargo.logging&gt;
                            &lt;cargo.servlet.port&gt;8080&lt;/cargo.servlet.port&gt;
                            &lt;cargo.servlet.users&gt;mobile:mobile:agent&lt;/cargo.servlet.users&gt;
                        &lt;/properties&gt;
                    &lt;/configuration&gt;

                &lt;/configuration&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;start-container&lt;/id&gt;
                        &lt;phase&gt;pre-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;start&lt;/goal&gt;
                            &lt;goal&gt;deploy&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;deployer&gt;
                                &lt;deployables&gt;
                                    &lt;deployable&gt;
                                        &lt;groupId&gt;agimatec&lt;/groupId&gt;
                                        &lt;artifactId&gt;mobile-suite&lt;/artifactId&gt;

                                        &lt;type&gt;war&lt;/type&gt;
                                        &lt;pingURL&gt;http://localhost:8080/ostium-mobile-suite/menu/index.action
                                        &lt;/pingURL&gt;
                                        &lt;pingTimeout&gt;300000&lt;/pingTimeout&gt;
                                        &lt;properties&gt;
                                            &lt;context&gt;ostium-mobile-suite&lt;/context&gt;
                                        &lt;/properties&gt;
                                    &lt;/deployable&gt;

                                &lt;/deployables&gt;
                            &lt;/deployer&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;stop-container&lt;/id&gt;
                        &lt;phase&gt;post-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;stop&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;

            &lt;/plugin&gt;

            &lt;plugin&gt;
                &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
                &lt;artifactId&gt;selenium-maven-plugin&lt;/artifactId&gt;

                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;phase&gt;pre-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;start-server&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;background&gt;true&lt;/background&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;

            &lt;plugin&gt;
                &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;

                &lt;configuration&gt;
                    &lt;skip&gt;true&lt;/skip&gt;
                &lt;/configuration&gt;

                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;phase&gt;integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;test&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;skip&gt;false&lt;/skip&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;
...</pre>
<p>To explore more details of the lifecycle phases read the <a href="http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html">Maven2 documentation</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.agimatec.de/blog/2008/07/maven2-build-livecycle/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
